mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/arm: Add PHYSDEVOP_pci_device_(*add/remove) support for ARM
Hardware domain is in charge of doing the PCI enumeration and will discover the PCI devices and then will communicate to XEN via hyper call PHYSDEVOP_pci_device_add(..) to add the PCI devices in XEN. Also implement PHYSDEVOP_pci_device_remove(..) to remove the PCI device. As most of the code for PHYSDEVOP_pci_device_* is the same between x86 and ARM, move the code to a common file to avoid duplication. There are other PHYSDEVOP_pci_device_* operations to add PCI devices. Currently implemented PHYSDEVOP_pci_device_remove(..) and PHYSDEVOP_pci_device_add(..) only as those are minimum required to support PCI passthrough on ARM. Signed-off-by: Rahul Singh <rahul.singh@arm.com> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org> Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
2a04f396a3
commit
f9187cf175
7 files changed
+96
-53
No files matched your search
@@ -8,13 +8,17 @@
|
||||
#include <xen/lib.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/sched.h>
|
||||
#include <asm/hypercall.h>
|
||||
#include <xen/hypercall.h>
|
||||
|
||||
|
||||
int do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
{
|
||||
#ifdef CONFIG_HAS_PCI
|
||||
return pci_physdev_op(cmd, arg);
|
||||
#else
|
||||
gdprintk(XENLOG_DEBUG, "PHYSDEVOP cmd=%d: not implemented\n", cmd);
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+2
-50
@@ -12,7 +12,7 @@
|
||||
#include <asm/io_apic.h>
|
||||
#include <asm/msi.h>
|
||||
#include <asm/hvm/irq.h>
|
||||
#include <asm/hypercall.h>
|
||||
#include <xen/hypercall.h>
|
||||
#include <public/xen.h>
|
||||
#include <public/physdev.h>
|
||||
#include <xsm/xsm.h>
|
||||
@@ -480,54 +480,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
break;
|
||||
}
|
||||
|
||||
case PHYSDEVOP_pci_device_add: {
|
||||
struct physdev_pci_device_add add;
|
||||
struct pci_dev_info pdev_info;
|
||||
nodeid_t node;
|
||||
|
||||
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;
|
||||
|
||||
if ( add.flags & XEN_PCI_DEV_PXM )
|
||||
{
|
||||
uint32_t pxm;
|
||||
size_t optarr_off = offsetof(struct physdev_pci_device_add, optarr) /
|
||||
sizeof(add.optarr[0]);
|
||||
|
||||
if ( copy_from_guest_offset(&pxm, arg, optarr_off, 1) )
|
||||
break;
|
||||
|
||||
node = pxm_to_node(pxm);
|
||||
}
|
||||
else
|
||||
node = NUMA_NO_NODE;
|
||||
|
||||
ret = pci_add_device(add.seg, add.bus, add.devfn, &pdev_info, node);
|
||||
break;
|
||||
}
|
||||
|
||||
case PHYSDEVOP_pci_device_remove: {
|
||||
struct physdev_pci_device dev;
|
||||
|
||||
ret = -EFAULT;
|
||||
if ( copy_from_guest(&dev, arg, 1) != 0 )
|
||||
break;
|
||||
|
||||
ret = pci_remove_device(dev.seg, dev.bus, dev.devfn);
|
||||
break;
|
||||
}
|
||||
|
||||
case PHYSDEVOP_prepare_msix:
|
||||
case PHYSDEVOP_release_msix: {
|
||||
struct physdev_pci_device dev;
|
||||
@@ -663,7 +615,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
}
|
||||
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
ret = pci_physdev_op(cmd, arg);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ EMIT_FILE;
|
||||
#include <compat/xen.h>
|
||||
#include <compat/event_channel.h>
|
||||
#include <compat/physdev.h>
|
||||
#include <asm/hypercall.h>
|
||||
#include <xen/hypercall.h>
|
||||
|
||||
#define do_physdev_op compat_physdev_op
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
obj-y += pci.o
|
||||
obj-y += physdev.o
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
#include <xen/guest_access.h>
|
||||
#include <xen/hypercall.h>
|
||||
#include <xen/init.h>
|
||||
|
||||
#ifndef COMPAT
|
||||
typedef long ret_t;
|
||||
#endif
|
||||
|
||||
ret_t pci_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
{
|
||||
ret_t ret;
|
||||
|
||||
switch ( cmd )
|
||||
{
|
||||
case PHYSDEVOP_pci_device_add: {
|
||||
struct physdev_pci_device_add add;
|
||||
struct pci_dev_info pdev_info;
|
||||
nodeid_t node = NUMA_NO_NODE;
|
||||
|
||||
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 = true;
|
||||
pdev_info.physfn.bus = add.physfn.bus;
|
||||
pdev_info.physfn.devfn = add.physfn.devfn;
|
||||
}
|
||||
else
|
||||
pdev_info.is_virtfn = false;
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
if ( add.flags & XEN_PCI_DEV_PXM )
|
||||
{
|
||||
uint32_t pxm;
|
||||
size_t optarr_off = offsetof(struct physdev_pci_device_add, optarr) /
|
||||
sizeof(add.optarr[0]);
|
||||
|
||||
if ( copy_from_guest_offset(&pxm, arg, optarr_off, 1) )
|
||||
break;
|
||||
|
||||
node = pxm_to_node(pxm);
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = pci_add_device(add.seg, add.bus, add.devfn, &pdev_info, node);
|
||||
break;
|
||||
}
|
||||
|
||||
case PHYSDEVOP_pci_device_remove: {
|
||||
struct physdev_pci_device dev;
|
||||
|
||||
ret = -EFAULT;
|
||||
if ( copy_from_guest(&dev, arg, 1) != 0 )
|
||||
break;
|
||||
|
||||
ret = pci_remove_device(dev.seg, dev.bus, dev.devfn);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -107,7 +107,9 @@
|
||||
* All generic sub-operations
|
||||
*
|
||||
* HYPERVISOR_physdev_op
|
||||
* No sub-operations are currenty supported
|
||||
* Exactly these sub-operations are supported:
|
||||
* PHYSDEVOP_pci_device_add
|
||||
* PHYSDEVOP_pci_device_remove
|
||||
*
|
||||
* HYPERVISOR_sysctl
|
||||
* All generic sub-operations, with the exception of:
|
||||
|
||||
@@ -45,6 +45,10 @@ extern long
|
||||
do_platform_op(
|
||||
XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op);
|
||||
|
||||
extern long
|
||||
pci_physdev_op(
|
||||
int cmd, XEN_GUEST_HANDLE_PARAM(void) arg);
|
||||
|
||||
/*
|
||||
* To allow safe resume of do_memory_op() after preemption, we need to know
|
||||
* at what point in the page list to resume. For this purpose I steal the
|
||||
|
||||