Commit 33b65f1e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'stable/for-linus-3.9-rc4-tag' of...

Merge tag 'stable/for-linus-3.9-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen

Pull Xen bug-fixes from Konrad Rzeszutek Wilk:
 "This is mostly just the last stragglers of the regression bugs that
  this merge window had.  There are also two bug-fixes: one that adds an
  extra layer of security, and a regression fix for a change that was
  added in v3.7 (the v1 was faulty, the v2 works).

   - Regression fixes for C-and-P states not being parsed properly.
   - Fix possible security issue with guests triggering DoS via
     non-assigned MSI-Xs.
   - Fix regression (introduced in v3.7) with raising an event (v2).
   - Fix hastily introduced band-aid during c0 for the CR3 blowup."

* tag 'stable/for-linus-3.9-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  xen/events: avoid race with raising an event in unmask_evtchn()
  xen/mmu: Move the setting of pvops.write_cr3 to later phase in bootup.
  xen/acpi-stub: Disable it b/c the acpi_processor_add is no longer called.
  xen-pciback: notify hypervisor about devices intended to be assigned to guests
  xen/acpi-processor: Don't dereference struct acpi_processor on all CPUs.
parents f8966048 c26377e6
......@@ -382,14 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str)
return _hypercall3(int, console_io, cmd, count, str);
}
extern int __must_check HYPERVISOR_physdev_op_compat(int, void *);
extern int __must_check xen_physdev_op_compat(int, void *);
static inline int
HYPERVISOR_physdev_op(int cmd, void *arg)
{
int rc = _hypercall2(int, physdev_op, cmd, arg);
if (unlikely(rc == -ENOSYS))
rc = HYPERVISOR_physdev_op_compat(cmd, arg);
rc = xen_physdev_op_compat(cmd, arg);
return rc;
}
......
......@@ -1467,8 +1467,6 @@ static void __init xen_write_cr3_init(unsigned long cr3)
__xen_write_cr3(true, cr3);
xen_mc_issue(PARAVIRT_LAZY_CPU); /* interrupts restored */
pv_mmu_ops.write_cr3 = &xen_write_cr3;
}
#endif
......@@ -2122,6 +2120,7 @@ static void __init xen_post_allocator_init(void)
#endif
#ifdef CONFIG_X86_64
pv_mmu_ops.write_cr3 = &xen_write_cr3;
SetPagePinned(virt_to_page(level3_user_vsyscall));
#endif
xen_mark_init_mm_pinned();
......
......@@ -182,7 +182,7 @@ config XEN_PRIVCMD
config XEN_STUB
bool "Xen stub drivers"
depends on XEN && X86_64
depends on XEN && X86_64 && BROKEN
default n
help
Allow kernel to install stub drivers, to reserve space for Xen drivers,
......
......@@ -403,11 +403,23 @@ static void unmask_evtchn(int port)
if (unlikely((cpu != cpu_from_evtchn(port))))
do_hypercall = 1;
else
else {
/*
* Need to clear the mask before checking pending to
* avoid a race with an event becoming pending.
*
* EVTCHNOP_unmask will only trigger an upcall if the
* mask bit was set, so if a hypercall is needed
* remask the event.
*/
sync_clear_bit(port, BM(&s->evtchn_mask[0]));
evtchn_pending = sync_test_bit(port, BM(&s->evtchn_pending[0]));
if (unlikely(evtchn_pending && xen_hvm_domain()))
do_hypercall = 1;
if (unlikely(evtchn_pending && xen_hvm_domain())) {
sync_set_bit(port, BM(&s->evtchn_mask[0]));
do_hypercall = 1;
}
}
/* Slow path (hypercall) if this is a non-local port or if this is
* an hvm domain and an event is pending (hvm domains don't have
......@@ -418,8 +430,6 @@ static void unmask_evtchn(int port)
} else {
struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
sync_clear_bit(port, BM(&s->evtchn_mask[0]));
/*
* The following is basically the equivalent of
* 'hw_resend_irq'. Just like a real IO-APIC we 'lose
......
......@@ -44,7 +44,7 @@ int xen_event_channel_op_compat(int cmd, void *arg)
}
EXPORT_SYMBOL_GPL(xen_event_channel_op_compat);
int HYPERVISOR_physdev_op_compat(int cmd, void *arg)
int xen_physdev_op_compat(int cmd, void *arg)
{
struct physdev_op op;
int rc;
......@@ -78,3 +78,4 @@ int HYPERVISOR_physdev_op_compat(int cmd, void *arg)
return rc;
}
EXPORT_SYMBOL_GPL(xen_physdev_op_compat);
......@@ -505,6 +505,9 @@ static int __init xen_acpi_processor_init(void)
pr = per_cpu(processors, i);
perf = per_cpu_ptr(acpi_perf_data, i);
if (!pr)
continue;
pr->performance = perf;
rc = acpi_processor_get_performance_info(pr);
if (rc)
......
......@@ -17,6 +17,7 @@
#include <xen/events.h>
#include <asm/xen/pci.h>
#include <asm/xen/hypervisor.h>
#include <xen/interface/physdev.h>
#include "pciback.h"
#include "conf_space.h"
#include "conf_space_quirks.h"
......@@ -85,37 +86,52 @@ static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
static void pcistub_device_release(struct kref *kref)
{
struct pcistub_device *psdev;
struct pci_dev *dev;
struct xen_pcibk_dev_data *dev_data;
psdev = container_of(kref, struct pcistub_device, kref);
dev_data = pci_get_drvdata(psdev->dev);
dev = psdev->dev;
dev_data = pci_get_drvdata(dev);
dev_dbg(&psdev->dev->dev, "pcistub_device_release\n");
dev_dbg(&dev->dev, "pcistub_device_release\n");
xen_unregister_device_domain_owner(psdev->dev);
xen_unregister_device_domain_owner(dev);
/* Call the reset function which does not take lock as this
* is called from "unbind" which takes a device_lock mutex.
*/
__pci_reset_function_locked(psdev->dev);
if (pci_load_and_free_saved_state(psdev->dev,
&dev_data->pci_saved_state)) {
dev_dbg(&psdev->dev->dev, "Could not reload PCI state\n");
} else
pci_restore_state(psdev->dev);
__pci_reset_function_locked(dev);
if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state))
dev_dbg(&dev->dev, "Could not reload PCI state\n");
else
pci_restore_state(dev);
if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
struct physdev_pci_device ppdev = {
.seg = pci_domain_nr(dev->bus),
.bus = dev->bus->number,
.devfn = dev->devfn
};
int err = HYPERVISOR_physdev_op(PHYSDEVOP_release_msix,
&ppdev);
if (err)
dev_warn(&dev->dev, "MSI-X release failed (%d)\n",
err);
}
/* Disable the device */
xen_pcibk_reset_device(psdev->dev);
xen_pcibk_reset_device(dev);
kfree(dev_data);
pci_set_drvdata(psdev->dev, NULL);
pci_set_drvdata(dev, NULL);
/* Clean-up the device */
xen_pcibk_config_free_dyn_fields(psdev->dev);
xen_pcibk_config_free_dev(psdev->dev);
xen_pcibk_config_free_dyn_fields(dev);
xen_pcibk_config_free_dev(dev);
psdev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
pci_dev_put(psdev->dev);
dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
pci_dev_put(dev);
kfree(psdev);
}
......@@ -355,6 +371,19 @@ static int pcistub_init_device(struct pci_dev *dev)
if (err)
goto config_release;
if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
struct physdev_pci_device ppdev = {
.seg = pci_domain_nr(dev->bus),
.bus = dev->bus->number,
.devfn = dev->devfn
};
err = HYPERVISOR_physdev_op(PHYSDEVOP_prepare_msix, &ppdev);
if (err)
dev_err(&dev->dev, "MSI-X preparation failed (%d)\n",
err);
}
/* We need the device active to save the state. */
dev_dbg(&dev->dev, "save state of device\n");
pci_save_state(dev);
......
......@@ -251,6 +251,12 @@ struct physdev_pci_device_add {
#define PHYSDEVOP_pci_device_remove 26
#define PHYSDEVOP_restore_msi_ext 27
/*
* Dom0 should use these two to announce MMIO resources assigned to
* MSI-X capable devices won't (prepare) or may (release) change.
*/
#define PHYSDEVOP_prepare_msix 30
#define PHYSDEVOP_release_msix 31
struct physdev_pci_device {
/* IN */
uint16_t seg;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment