Bug-fixes:
- 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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.13 (GNU/Linux) iQEcBAABAgAGBQJRUxlVAAoJEFjIrFwIi8fJiUsH/2a3A8EVqS7OYDNgT0ZFb1VI rMLNiA50sRJNDsq0NbGl1Y+Lubus1czc0c7HXFQ557OakN6WqcmPPjCKp4JT6NnV Jz/IZ0iimdoHiPru1Qe4ah3fSgzUtht2LB48Z/a0Is4k3LsRP2W3/niVC3ypnyuJ 52HjjuxeFAfXIkNeqsrO2a6cUXZeXzUyR4g9GNxDozi4jHpoPQ4j9okZbo218xH+ /pRnFeMD7t7dFkgNeyeGXUiJn2AkNPHi3Hx+RH5nN9KXQ1eem9R4p7Qpez1dUEWF YEc/bs7MyOYezzTVHPYk77Yt8baOHJt7UbHjM6jfi1aGYYINTRr3m5mORd3rCmc= =61IX -----END PGP SIGNATURE----- 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.
This commit is contained in:
commit
33b65f1e9c
8 changed files with 74 additions and 26 deletions
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue