aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <JBeulich@suse.com>2013-03-12 11:06:23 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2013-03-22 10:20:55 -0400
commit909b3fdb0dd4f3db07b2d75425a00a2adb551383 (patch)
treee50ce461455625ad48e450057e6fa23ab88ac9cf
parent949dd8c14fb2b20b4b815817e66120b22cf531d4 (diff)
xen-pciback: notify hypervisor about devices intended to be assigned to guests
For MSI-X capable devices the hypervisor wants to write protect the MSI-X table and PBA, yet it can't assume that resources have been assigned to their final values at device enumeration time. Thus have pciback do that notification, as having the device controlled by it is a prerequisite to assigning the device to guests anyway. This is the kernel part of hypervisor side commit 4245d33 ("x86/MSI: add mechanism to fully protect MSI-X table from PV guest accesses") on the master branch of git://xenbits.xen.org/xen.git. CC: stable@vger.kernel.org Signed-off-by: Jan Beulich <jbeulich@suse.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r--arch/x86/include/asm/xen/hypercall.h4
-rw-r--r--drivers/xen/fallback.c3
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c59
-rw-r--r--include/xen/interface/physdev.h6
4 files changed, 54 insertions, 18 deletions
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index c20d1ce62dc6..e709884d0ef9 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -382,14 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str)
382 return _hypercall3(int, console_io, cmd, count, str); 382 return _hypercall3(int, console_io, cmd, count, str);
383} 383}
384 384
385extern int __must_check HYPERVISOR_physdev_op_compat(int, void *); 385extern int __must_check xen_physdev_op_compat(int, void *);
386 386
387static inline int 387static inline int
388HYPERVISOR_physdev_op(int cmd, void *arg) 388HYPERVISOR_physdev_op(int cmd, void *arg)
389{ 389{
390 int rc = _hypercall2(int, physdev_op, cmd, arg); 390 int rc = _hypercall2(int, physdev_op, cmd, arg);
391 if (unlikely(rc == -ENOSYS)) 391 if (unlikely(rc == -ENOSYS))
392 rc = HYPERVISOR_physdev_op_compat(cmd, arg); 392 rc = xen_physdev_op_compat(cmd, arg);
393 return rc; 393 return rc;
394} 394}
395 395
diff --git a/drivers/xen/fallback.c b/drivers/xen/fallback.c
index 0ef7c4d40f86..b04fb64c5a91 100644
--- a/drivers/xen/fallback.c
+++ b/drivers/xen/fallback.c
@@ -44,7 +44,7 @@ int xen_event_channel_op_compat(int cmd, void *arg)
44} 44}
45EXPORT_SYMBOL_GPL(xen_event_channel_op_compat); 45EXPORT_SYMBOL_GPL(xen_event_channel_op_compat);
46 46
47int HYPERVISOR_physdev_op_compat(int cmd, void *arg) 47int xen_physdev_op_compat(int cmd, void *arg)
48{ 48{
49 struct physdev_op op; 49 struct physdev_op op;
50 int rc; 50 int rc;
@@ -78,3 +78,4 @@ int HYPERVISOR_physdev_op_compat(int cmd, void *arg)
78 78
79 return rc; 79 return rc;
80} 80}
81EXPORT_SYMBOL_GPL(xen_physdev_op_compat);
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 9204126f1560..a2278ba7fb27 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -17,6 +17,7 @@
17#include <xen/events.h> 17#include <xen/events.h>
18#include <asm/xen/pci.h> 18#include <asm/xen/pci.h>
19#include <asm/xen/hypervisor.h> 19#include <asm/xen/hypervisor.h>
20#include <xen/interface/physdev.h>
20#include "pciback.h" 21#include "pciback.h"
21#include "conf_space.h" 22#include "conf_space.h"
22#include "conf_space_quirks.h" 23#include "conf_space_quirks.h"
@@ -85,37 +86,52 @@ static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
85static void pcistub_device_release(struct kref *kref) 86static void pcistub_device_release(struct kref *kref)
86{ 87{
87 struct pcistub_device *psdev; 88 struct pcistub_device *psdev;
89 struct pci_dev *dev;
88 struct xen_pcibk_dev_data *dev_data; 90 struct xen_pcibk_dev_data *dev_data;
89 91
90 psdev = container_of(kref, struct pcistub_device, kref); 92 psdev = container_of(kref, struct pcistub_device, kref);
91 dev_data = pci_get_drvdata(psdev->dev); 93 dev = psdev->dev;
94 dev_data = pci_get_drvdata(dev);
92 95
93 dev_dbg(&psdev->dev->dev, "pcistub_device_release\n"); 96 dev_dbg(&dev->dev, "pcistub_device_release\n");
94 97
95 xen_unregister_device_domain_owner(psdev->dev); 98 xen_unregister_device_domain_owner(dev);
96 99
97 /* Call the reset function which does not take lock as this 100 /* Call the reset function which does not take lock as this
98 * is called from "unbind" which takes a device_lock mutex. 101 * is called from "unbind" which takes a device_lock mutex.
99 */ 102 */
100 __pci_reset_function_locked(psdev->dev); 103 __pci_reset_function_locked(dev);
101 if (pci_load_and_free_saved_state(psdev->dev, 104 if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state))
102 &dev_data->pci_saved_state)) { 105 dev_dbg(&dev->dev, "Could not reload PCI state\n");
103 dev_dbg(&psdev->dev->dev, "Could not reload PCI state\n"); 106 else
104 } else 107 pci_restore_state(dev);
105 pci_restore_state(psdev->dev); 108
109 if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
110 struct physdev_pci_device ppdev = {
111 .seg = pci_domain_nr(dev->bus),
112 .bus = dev->bus->number,
113 .devfn = dev->devfn
114 };
115 int err = HYPERVISOR_physdev_op(PHYSDEVOP_release_msix,
116 &ppdev);
117
118 if (err)
119 dev_warn(&dev->dev, "MSI-X release failed (%d)\n",
120 err);
121 }
106 122
107 /* Disable the device */ 123 /* Disable the device */
108 xen_pcibk_reset_device(psdev->dev); 124 xen_pcibk_reset_device(dev);
109 125
110 kfree(dev_data); 126 kfree(dev_data);
111 pci_set_drvdata(psdev->dev, NULL); 127 pci_set_drvdata(dev, NULL);
112 128
113 /* Clean-up the device */ 129 /* Clean-up the device */
114 xen_pcibk_config_free_dyn_fields(psdev->dev); 130 xen_pcibk_config_free_dyn_fields(dev);
115 xen_pcibk_config_free_dev(psdev->dev); 131 xen_pcibk_config_free_dev(dev);
116 132
117 psdev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED; 133 dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
118 pci_dev_put(psdev->dev); 134 pci_dev_put(dev);
119 135
120 kfree(psdev); 136 kfree(psdev);
121} 137}
@@ -355,6 +371,19 @@ static int pcistub_init_device(struct pci_dev *dev)
355 if (err) 371 if (err)
356 goto config_release; 372 goto config_release;
357 373
374 if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
375 struct physdev_pci_device ppdev = {
376 .seg = pci_domain_nr(dev->bus),
377 .bus = dev->bus->number,
378 .devfn = dev->devfn
379 };
380
381 err = HYPERVISOR_physdev_op(PHYSDEVOP_prepare_msix, &ppdev);
382 if (err)
383 dev_err(&dev->dev, "MSI-X preparation failed (%d)\n",
384 err);
385 }
386
358 /* We need the device active to save the state. */ 387 /* We need the device active to save the state. */
359 dev_dbg(&dev->dev, "save state of device\n"); 388 dev_dbg(&dev->dev, "save state of device\n");
360 pci_save_state(dev); 389 pci_save_state(dev);
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h
index 1844d31f4552..7000bb1f6e96 100644
--- a/include/xen/interface/physdev.h
+++ b/include/xen/interface/physdev.h
@@ -251,6 +251,12 @@ struct physdev_pci_device_add {
251 251
252#define PHYSDEVOP_pci_device_remove 26 252#define PHYSDEVOP_pci_device_remove 26
253#define PHYSDEVOP_restore_msi_ext 27 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
254struct physdev_pci_device { 260struct physdev_pci_device {
255 /* IN */ 261 /* IN */
256 uint16_t seg; 262 uint16_t seg;