aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/physdev.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2011-09-18 00:12:19 +0100
committerJan Beulich <jbeulich@suse.com>2011-09-18 00:12:19 +0100
commit7620c0cf9a4df9cff19be020bf84f8a71cc31d8d (patch)
tree4e0695f43d0d1ad85c0fcaf1a4d59fb5b7859740 /xen/arch/x86/physdev.c
parent21844b0e32e77c9e1a600b9279a859a7ffe01844 (diff)
downloadxen-7620c0cf9a4df9cff19be020bf84f8a71cc31d8d.tar.gz
xen-7620c0cf9a4df9cff19be020bf84f8a71cc31d8d.tar.bz2
xen-7620c0cf9a4df9cff19be020bf84f8a71cc31d8d.zip
PCI multi-seg: add new physdevop-s
The new PHYSDEVOP_pci_device_add is intended to be extensible, with a first extension (to pass the proximity domain of a device) added right away. A couple of directly related functions at once get adjusted to account for the segment number. Should we deprecate the PHYSDEVOP_manage_pci_* sub-hypercalls? Signed-off-by: Jan Beulich <jbeulich@suse.com>
Diffstat (limited to 'xen/arch/x86/physdev.c')
-rw-r--r--xen/arch/x86/physdev.c77
1 files changed, 73 insertions, 4 deletions
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index d51f4a081f..eccf8849ee 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -357,6 +357,15 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
if ( copy_from_guest(&map, arg, 1) != 0 )
break;
+ if ( map.type == MAP_PIRQ_TYPE_MSI_SEG )
+ {
+ map.type = MAP_PIRQ_TYPE_MSI;
+ msi.seg = map.bus >> 16;
+ }
+ else
+ {
+ msi.seg = 0;
+ }
msi.bus = map.bus;
msi.devfn = map.devfn;
msi.entry_nr = map.entry_nr;
@@ -480,7 +489,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
if ( copy_from_guest(&manage_pci, arg, 1) != 0 )
break;
- ret = pci_add_device(manage_pci.bus, manage_pci.devfn, NULL);
+ ret = pci_add_device(0, manage_pci.bus, manage_pci.devfn, NULL);
break;
}
@@ -493,7 +502,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
if ( copy_from_guest(&manage_pci, arg, 1) != 0 )
break;
- ret = pci_remove_device(manage_pci.bus, manage_pci.devfn);
+ ret = pci_remove_device(0, manage_pci.bus, manage_pci.devfn);
break;
}
@@ -517,12 +526,52 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
pdev_info.is_virtfn = manage_pci_ext.is_virtfn;
pdev_info.physfn.bus = manage_pci_ext.physfn.bus;
pdev_info.physfn.devfn = manage_pci_ext.physfn.devfn;
- ret = pci_add_device(manage_pci_ext.bus,
+ ret = pci_add_device(0, manage_pci_ext.bus,
manage_pci_ext.devfn,
&pdev_info);
break;
}
+ case PHYSDEVOP_pci_device_add: {
+ struct physdev_pci_device_add add;
+ struct pci_dev_info pdev_info;
+
+ ret = -EPERM;
+ if ( !IS_PRIV(current->domain) )
+ break;
+
+ ret = -EFAULT;
+ if ( copy_from_guest(&add, arg, 1) != 0 )
+ break;
+
+ pdev_info.is_extfn = !!(add.flags & XEN_PCI_DEV_EXTFN);
+ if ( add.flags & XEN_PCI_DEV_VIRTFN )
+ {
+ pdev_info.is_virtfn = 1;
+ pdev_info.physfn.bus = add.physfn.bus;
+ pdev_info.physfn.devfn = add.physfn.devfn;
+ }
+ else
+ pdev_info.is_virtfn = 0;
+ ret = pci_add_device(add.seg, add.bus, add.devfn, &pdev_info);
+ break;
+ }
+
+ case PHYSDEVOP_pci_device_remove: {
+ struct physdev_pci_device dev;
+
+ ret = -EPERM;
+ if ( !IS_PRIV(v->domain) )
+ break;
+
+ ret = -EFAULT;
+ if ( copy_from_guest(&dev, arg, 1) != 0 )
+ break;
+
+ ret = pci_remove_device(dev.seg, dev.bus, dev.devfn);
+ break;
+ }
+
#ifdef __x86_64__
case PHYSDEVOP_pci_mmcfg_reserved: {
struct physdev_pci_mmcfg_reserved info;
@@ -554,11 +603,31 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
break;
spin_lock(&pcidevs_lock);
- pdev = pci_get_pdev(restore_msi.bus, restore_msi.devfn);
+ pdev = pci_get_pdev(0, restore_msi.bus, restore_msi.devfn);
ret = pdev ? pci_restore_msi_state(pdev) : -ENODEV;
spin_unlock(&pcidevs_lock);
break;
}
+
+ case PHYSDEVOP_restore_msi_ext: {
+ struct physdev_pci_device dev;
+ struct pci_dev *pdev;
+
+ ret = -EPERM;
+ if ( !IS_PRIV(v->domain) )
+ break;
+
+ ret = -EFAULT;
+ if ( copy_from_guest(&dev, arg, 1) != 0 )
+ break;
+
+ spin_lock(&pcidevs_lock);
+ pdev = pci_get_pdev(dev.seg, dev.bus, dev.devfn);
+ ret = pdev ? pci_restore_msi_state(pdev) : -ENODEV;
+ spin_unlock(&pcidevs_lock);
+ break;
+ }
+
case PHYSDEVOP_setup_gsi: {
struct physdev_setup_gsi setup_gsi;