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) ...@@ -382,14 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str)
return _hypercall3(int, console_io, cmd, count, 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 static inline int
HYPERVISOR_physdev_op(int cmd, void *arg) HYPERVISOR_physdev_op(int cmd, void *arg)
{ {
int rc = _hypercall2(int, physdev_op, cmd, arg); int rc = _hypercall2(int, physdev_op, cmd, arg);
if (unlikely(rc == -ENOSYS)) if (unlikely(rc == -ENOSYS))
rc = HYPERVISOR_physdev_op_compat(cmd, arg); rc = xen_physdev_op_compat(cmd, arg);
return rc; return rc;
} }
......
...@@ -1467,8 +1467,6 @@ static void __init xen_write_cr3_init(unsigned long cr3) ...@@ -1467,8 +1467,6 @@ static void __init xen_write_cr3_init(unsigned long cr3)
__xen_write_cr3(true, cr3); __xen_write_cr3(true, cr3);
xen_mc_issue(PARAVIRT_LAZY_CPU); /* interrupts restored */ xen_mc_issue(PARAVIRT_LAZY_CPU); /* interrupts restored */
pv_mmu_ops.write_cr3 = &xen_write_cr3;
} }
#endif #endif
...@@ -2122,6 +2120,7 @@ static void __init xen_post_allocator_init(void) ...@@ -2122,6 +2120,7 @@ static void __init xen_post_allocator_init(void)
#endif #endif
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
pv_mmu_ops.write_cr3 = &xen_write_cr3;
SetPagePinned(virt_to_page(level3_user_vsyscall)); SetPagePinned(virt_to_page(level3_user_vsyscall));
#endif #endif
xen_mark_init_mm_pinned(); xen_mark_init_mm_pinned();
......
...@@ -182,7 +182,7 @@ config XEN_PRIVCMD ...@@ -182,7 +182,7 @@ config XEN_PRIVCMD
config XEN_STUB config XEN_STUB
bool "Xen stub drivers" bool "Xen stub drivers"
depends on XEN && X86_64 depends on XEN && X86_64 && BROKEN
default n default n
help help
Allow kernel to install stub drivers, to reserve space for Xen drivers, Allow kernel to install stub drivers, to reserve space for Xen drivers,
......
...@@ -403,11 +403,23 @@ static void unmask_evtchn(int port) ...@@ -403,11 +403,23 @@ static void unmask_evtchn(int port)
if (unlikely((cpu != cpu_from_evtchn(port)))) if (unlikely((cpu != cpu_from_evtchn(port))))
do_hypercall = 1; 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])); evtchn_pending = sync_test_bit(port, BM(&s->evtchn_pending[0]));
if (unlikely(evtchn_pending && xen_hvm_domain())) if (unlikely(evtchn_pending && xen_hvm_domain())) {
do_hypercall = 1; 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 /* 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 * an hvm domain and an event is pending (hvm domains don't have
...@@ -418,8 +430,6 @@ static void unmask_evtchn(int port) ...@@ -418,8 +430,6 @@ static void unmask_evtchn(int port)
} else { } else {
struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); 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 * The following is basically the equivalent of
* 'hw_resend_irq'. Just like a real IO-APIC we 'lose * '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) ...@@ -44,7 +44,7 @@ int xen_event_channel_op_compat(int cmd, void *arg)
} }
EXPORT_SYMBOL_GPL(xen_event_channel_op_compat); 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; struct physdev_op op;
int rc; int rc;
...@@ -78,3 +78,4 @@ int HYPERVISOR_physdev_op_compat(int cmd, void *arg) ...@@ -78,3 +78,4 @@ int HYPERVISOR_physdev_op_compat(int cmd, void *arg)
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(xen_physdev_op_compat);
...@@ -505,6 +505,9 @@ static int __init xen_acpi_processor_init(void) ...@@ -505,6 +505,9 @@ static int __init xen_acpi_processor_init(void)
pr = per_cpu(processors, i); pr = per_cpu(processors, i);
perf = per_cpu_ptr(acpi_perf_data, i); perf = per_cpu_ptr(acpi_perf_data, i);
if (!pr)
continue;
pr->performance = perf; pr->performance = perf;
rc = acpi_processor_get_performance_info(pr); rc = acpi_processor_get_performance_info(pr);
if (rc) if (rc)
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <xen/events.h> #include <xen/events.h>
#include <asm/xen/pci.h> #include <asm/xen/pci.h>
#include <asm/xen/hypervisor.h> #include <asm/xen/hypervisor.h>
#include <xen/interface/physdev.h>
#include "pciback.h" #include "pciback.h"
#include "conf_space.h" #include "conf_space.h"
#include "conf_space_quirks.h" #include "conf_space_quirks.h"
...@@ -85,37 +86,52 @@ static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev) ...@@ -85,37 +86,52 @@ static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
static void pcistub_device_release(struct kref *kref) static void pcistub_device_release(struct kref *kref)
{ {
struct pcistub_device *psdev; struct pcistub_device *psdev;
struct pci_dev *dev;
struct xen_pcibk_dev_data *dev_data; struct xen_pcibk_dev_data *dev_data;
psdev = container_of(kref, struct pcistub_device, kref); 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 /* Call the reset function which does not take lock as this
* is called from "unbind" which takes a device_lock mutex. * is called from "unbind" which takes a device_lock mutex.
*/ */
__pci_reset_function_locked(psdev->dev); __pci_reset_function_locked(dev);
if (pci_load_and_free_saved_state(psdev->dev, if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state))
&dev_data->pci_saved_state)) { dev_dbg(&dev->dev, "Could not reload PCI state\n");
dev_dbg(&psdev->dev->dev, "Could not reload PCI state\n"); else
} else pci_restore_state(dev);
pci_restore_state(psdev->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 */ /* Disable the device */
xen_pcibk_reset_device(psdev->dev); xen_pcibk_reset_device(dev);
kfree(dev_data); kfree(dev_data);
pci_set_drvdata(psdev->dev, NULL); pci_set_drvdata(dev, NULL);
/* Clean-up the device */ /* Clean-up the device */
xen_pcibk_config_free_dyn_fields(psdev->dev); xen_pcibk_config_free_dyn_fields(dev);
xen_pcibk_config_free_dev(psdev->dev); xen_pcibk_config_free_dev(dev);
psdev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED; dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
pci_dev_put(psdev->dev); pci_dev_put(dev);
kfree(psdev); kfree(psdev);
} }
...@@ -355,6 +371,19 @@ static int pcistub_init_device(struct pci_dev *dev) ...@@ -355,6 +371,19 @@ static int pcistub_init_device(struct pci_dev *dev)
if (err) if (err)
goto config_release; 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. */ /* We need the device active to save the state. */
dev_dbg(&dev->dev, "save state of device\n"); dev_dbg(&dev->dev, "save state of device\n");
pci_save_state(dev); pci_save_state(dev);
......
...@@ -251,6 +251,12 @@ struct physdev_pci_device_add { ...@@ -251,6 +251,12 @@ struct physdev_pci_device_add {
#define PHYSDEVOP_pci_device_remove 26 #define PHYSDEVOP_pci_device_remove 26
#define PHYSDEVOP_restore_msi_ext 27 #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 { struct physdev_pci_device {
/* IN */ /* IN */
uint16_t seg; 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