Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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.

+74 -26
+2 -2
arch/x86/include/asm/xen/hypercall.h
··· 382 382 return _hypercall3(int, console_io, cmd, count, str); 383 383 } 384 384 385 - extern int __must_check HYPERVISOR_physdev_op_compat(int, void *); 385 + extern int __must_check xen_physdev_op_compat(int, void *); 386 386 387 387 static inline int 388 388 HYPERVISOR_physdev_op(int cmd, void *arg) 389 389 { 390 390 int rc = _hypercall2(int, physdev_op, cmd, arg); 391 391 if (unlikely(rc == -ENOSYS)) 392 - rc = HYPERVISOR_physdev_op_compat(cmd, arg); 392 + rc = xen_physdev_op_compat(cmd, arg); 393 393 return rc; 394 394 } 395 395
+1 -2
arch/x86/xen/mmu.c
··· 1467 1467 __xen_write_cr3(true, cr3); 1468 1468 1469 1469 xen_mc_issue(PARAVIRT_LAZY_CPU); /* interrupts restored */ 1470 - 1471 - pv_mmu_ops.write_cr3 = &xen_write_cr3; 1472 1470 } 1473 1471 #endif 1474 1472 ··· 2120 2122 #endif 2121 2123 2122 2124 #ifdef CONFIG_X86_64 2125 + pv_mmu_ops.write_cr3 = &xen_write_cr3; 2123 2126 SetPagePinned(virt_to_page(level3_user_vsyscall)); 2124 2127 #endif 2125 2128 xen_mark_init_mm_pinned();
+1 -1
drivers/xen/Kconfig
··· 182 182 183 183 config XEN_STUB 184 184 bool "Xen stub drivers" 185 - depends on XEN && X86_64 185 + depends on XEN && X86_64 && BROKEN 186 186 default n 187 187 help 188 188 Allow kernel to install stub drivers, to reserve space for Xen drivers,
+15 -5
drivers/xen/events.c
··· 403 403 404 404 if (unlikely((cpu != cpu_from_evtchn(port)))) 405 405 do_hypercall = 1; 406 - else 406 + else { 407 + /* 408 + * Need to clear the mask before checking pending to 409 + * avoid a race with an event becoming pending. 410 + * 411 + * EVTCHNOP_unmask will only trigger an upcall if the 412 + * mask bit was set, so if a hypercall is needed 413 + * remask the event. 414 + */ 415 + sync_clear_bit(port, BM(&s->evtchn_mask[0])); 407 416 evtchn_pending = sync_test_bit(port, BM(&s->evtchn_pending[0])); 408 417 409 - if (unlikely(evtchn_pending && xen_hvm_domain())) 410 - do_hypercall = 1; 418 + if (unlikely(evtchn_pending && xen_hvm_domain())) { 419 + sync_set_bit(port, BM(&s->evtchn_mask[0])); 420 + do_hypercall = 1; 421 + } 422 + } 411 423 412 424 /* Slow path (hypercall) if this is a non-local port or if this is 413 425 * an hvm domain and an event is pending (hvm domains don't have ··· 429 417 (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); 430 418 } else { 431 419 struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); 432 - 433 - sync_clear_bit(port, BM(&s->evtchn_mask[0])); 434 420 435 421 /* 436 422 * The following is basically the equivalent of
+2 -1
drivers/xen/fallback.c
··· 44 44 } 45 45 EXPORT_SYMBOL_GPL(xen_event_channel_op_compat); 46 46 47 - int HYPERVISOR_physdev_op_compat(int cmd, void *arg) 47 + int xen_physdev_op_compat(int cmd, void *arg) 48 48 { 49 49 struct physdev_op op; 50 50 int rc; ··· 78 78 79 79 return rc; 80 80 } 81 + EXPORT_SYMBOL_GPL(xen_physdev_op_compat);
+3
drivers/xen/xen-acpi-processor.c
··· 505 505 506 506 pr = per_cpu(processors, i); 507 507 perf = per_cpu_ptr(acpi_perf_data, i); 508 + if (!pr) 509 + continue; 510 + 508 511 pr->performance = perf; 509 512 rc = acpi_processor_get_performance_info(pr); 510 513 if (rc)
+44 -15
drivers/xen/xen-pciback/pci_stub.c
··· 17 17 #include <xen/events.h> 18 18 #include <asm/xen/pci.h> 19 19 #include <asm/xen/hypervisor.h> 20 + #include <xen/interface/physdev.h> 20 21 #include "pciback.h" 21 22 #include "conf_space.h" 22 23 #include "conf_space_quirks.h" ··· 86 85 static void pcistub_device_release(struct kref *kref) 87 86 { 88 87 struct pcistub_device *psdev; 88 + struct pci_dev *dev; 89 89 struct xen_pcibk_dev_data *dev_data; 90 90 91 91 psdev = container_of(kref, struct pcistub_device, kref); 92 - dev_data = pci_get_drvdata(psdev->dev); 92 + dev = psdev->dev; 93 + dev_data = pci_get_drvdata(dev); 93 94 94 - dev_dbg(&psdev->dev->dev, "pcistub_device_release\n"); 95 + dev_dbg(&dev->dev, "pcistub_device_release\n"); 95 96 96 - xen_unregister_device_domain_owner(psdev->dev); 97 + xen_unregister_device_domain_owner(dev); 97 98 98 99 /* Call the reset function which does not take lock as this 99 100 * is called from "unbind" which takes a device_lock mutex. 100 101 */ 101 - __pci_reset_function_locked(psdev->dev); 102 - if (pci_load_and_free_saved_state(psdev->dev, 103 - &dev_data->pci_saved_state)) { 104 - dev_dbg(&psdev->dev->dev, "Could not reload PCI state\n"); 105 - } else 106 - pci_restore_state(psdev->dev); 102 + __pci_reset_function_locked(dev); 103 + if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state)) 104 + dev_dbg(&dev->dev, "Could not reload PCI state\n"); 105 + else 106 + pci_restore_state(dev); 107 + 108 + if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) { 109 + struct physdev_pci_device ppdev = { 110 + .seg = pci_domain_nr(dev->bus), 111 + .bus = dev->bus->number, 112 + .devfn = dev->devfn 113 + }; 114 + int err = HYPERVISOR_physdev_op(PHYSDEVOP_release_msix, 115 + &ppdev); 116 + 117 + if (err) 118 + dev_warn(&dev->dev, "MSI-X release failed (%d)\n", 119 + err); 120 + } 107 121 108 122 /* Disable the device */ 109 - xen_pcibk_reset_device(psdev->dev); 123 + xen_pcibk_reset_device(dev); 110 124 111 125 kfree(dev_data); 112 - pci_set_drvdata(psdev->dev, NULL); 126 + pci_set_drvdata(dev, NULL); 113 127 114 128 /* Clean-up the device */ 115 - xen_pcibk_config_free_dyn_fields(psdev->dev); 116 - xen_pcibk_config_free_dev(psdev->dev); 129 + xen_pcibk_config_free_dyn_fields(dev); 130 + xen_pcibk_config_free_dev(dev); 117 131 118 - psdev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED; 119 - pci_dev_put(psdev->dev); 132 + dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED; 133 + pci_dev_put(dev); 120 134 121 135 kfree(psdev); 122 136 } ··· 370 354 err = pci_enable_device(dev); 371 355 if (err) 372 356 goto config_release; 357 + 358 + if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) { 359 + struct physdev_pci_device ppdev = { 360 + .seg = pci_domain_nr(dev->bus), 361 + .bus = dev->bus->number, 362 + .devfn = dev->devfn 363 + }; 364 + 365 + err = HYPERVISOR_physdev_op(PHYSDEVOP_prepare_msix, &ppdev); 366 + if (err) 367 + dev_err(&dev->dev, "MSI-X preparation failed (%d)\n", 368 + err); 369 + } 373 370 374 371 /* We need the device active to save the state. */ 375 372 dev_dbg(&dev->dev, "save state of device\n");
+6
include/xen/interface/physdev.h
··· 251 251 252 252 #define PHYSDEVOP_pci_device_remove 26 253 253 #define PHYSDEVOP_restore_msi_ext 27 254 + /* 255 + * Dom0 should use these two to announce MMIO resources assigned to 256 + * MSI-X capable devices won't (prepare) or may (release) change. 257 + */ 258 + #define PHYSDEVOP_prepare_msix 30 259 + #define PHYSDEVOP_release_msix 31 254 260 struct physdev_pci_device { 255 261 /* IN */ 256 262 uint16_t seg;