IOMMU: Handle sibling device assignment correctly (re-send)
PATCH 1/2 IOMMU: Handle sibling device assignment correctly (re-send)
Signed-off-by Wei Wang <[email protected]>
Signature · 12 lines
AMD Saxony, Dresden, Germany Operating System Research Center Legal Information: AMD Saxony Limited Liability Company & Co. KG Sitz (Geschäftsanschrift): Wilschdorfer Landstr. 101, 01109 Dresden, Deutschland Registergericht Dresden: HRA 4896 vertretungsberechtigter Komplementär: AMD Saxony LLC (Sitz Wilmington, Delaware, USA) Geschäftsführer der AMD Saxony LLC: Dr. Hans-R. Deppe, Thomas McCoy
xen/arch/x86/domctl.c +39 -0
@@ -526,6 +526,45 @@ long arch_do_domctl( }break ; +case XEN_DOMCTL_get_device_group: + { +struct domain *d; +u32 max_sdevs; +u8 bus, devfn; +XEN_GUEST_HANDLE_64 (uint32) sdevs; +int num_sdevs; + + ret = -ENOSYS ; +if ( !iommu_enabled ) +break ; + + ret = -EINVAL ; +if ( (d =rcu_lock_domain_by_id (domctl->domain)) ==NULL ) +break ; + + bus = (domctl->u.get_device_group.machine_bdf >>16 ) &0xff ; + devfn = (domctl->u.get_device_group.machine_bdf >>8 ) &0xff ; + max_sdevs = domctl->u.get_device_group.max_sdevs; + sdevs = domctl->u.get_device_group.sdev_array; + + num_sdevs =iommu_get_device_group (d, bus, devfn, sdevs, max_sdevs); +if ( num_sdevs <0 ) + { +dprintk (XENLOG_ERR ,"iommu_get_device_group() failed!\n" ); + ret = -EFAULT ; + domctl->u.get_device_group.num_sdevs =0 ; + } +else + { + ret =0 ; + domctl->u.get_device_group.num_sdevs = num_sdevs; + } +if (copy_to_guest (u_domctl, domctl,1 ) ) + ret = -EFAULT ; +rcu_unlock_domain (d); + } +break ; +case XEN_DOMCTL_test_assign_device: {u8 bus, devfn;
xen/drivers/passthrough/amd/pci_amd_iommu.c +11 -0
@@ -635,6 +635,16 @@ static void amd_iommu_return_device(reassign_device (s, t, bus, devfn); } +static int amd_iommu_group_id (u8 bus,u8 devfn) +{ +int rt; +int bdf = (bus <<8 ) | devfn; + rt = ( bdf < ivrs_bdf_entries ) ? + ivrs_mappings[bdf].dte_requestor_id : + bdf; +return rt; +} +struct iommu_ops amd_iommu_ops = { .init = amd_iommu_domain_init, .assign_device = amd_iommu_assign_device,
@@ -642,4 +652,5 @@ struct iommu_ops amd_iommu_ops = { .map_page = amd_iommu_map_page, .unmap_page = amd_iommu_unmap_page, .reassign_device = amd_iommu_return_device, + .get_device_group_id = amd_iommu_group_id, };
xen/drivers/passthrough/iommu.c +36 -1
@@ -16,6 +16,7 @@#include <xen/sched.h> #include <xen/iommu.h> #include <xen/paging.h> +#include <xen/guest_access.h> extern struct iommu_ops intel_iommu_ops;extern struct iommu_ops amd_iommu_ops;
@@ -216,7 +217,41 @@ static int iommu_setup(void) }__initcall (iommu_setup); - +int iommu_get_device_group (struct domain *d,u8 bus,u8 devfn, +XEN_GUEST_HANDLE_64 (uint32) buf,int max_sdevs) +{ +struct hvm_iommu *hd =domain_hvm_iommu (d); +struct pci_dev *pdev; +int group_id, sdev_id; +u32 bdf; +int i =0 ; +struct iommu_ops *ops = hd->platform_ops; + +if ( !iommu_enabled || !ops || !ops->get_device_group_id ) +return 0 ; + + group_id = ops->get_device_group_id (bus, devfn); + +list_for_each_entry (pdev, + &(dom0->arch.hvm_domain.hvm_iommu.pdev_list), list) + { +if ( (pdev->bus == bus) && (pdev->devfn == devfn) ) +continue ; + + sdev_id = ops->get_device_group_id (pdev->bus, pdev->devfn); +if ( (sdev_id == group_id) && (i < max_sdevs) ) + { + bdf =0 ; + bdf |= (pdev->bus &0xff ) <<16 ; + bdf |= (pdev->devfn &0xff ) <<8 ; +if (unlikely (copy_to_guest_offset (buf, i, &bdf,1 )) ) +return -1 ; + i++; + } + } + +return i; +}/* * Local variables: * mode: C
xen/drivers/passthrough/vtd/iommu.c +1 -0
@@ -1946,6 +1946,7 @@ struct iommu_ops intel_iommu_ops = { .map_page = intel_iommu_map_page, .unmap_page = intel_iommu_unmap_page, .reassign_device = reassign_device_ownership, + .get_device_group_id = NULL, };/*
xen/include/public/domctl.h +11 -0
@@ -448,6 +448,16 @@ typedef struct xen_domctl_assign_devicetypedef struct xen_domctl_assign_device xen_domctl_assign_device_t ;DEFINE_XEN_GUEST_HANDLE (xen_domctl_assign_device_t); +/* Retrieve sibling devices infomation of machine_bdf */ +#define XEN_DOMCTL_get_device_group 50 +struct xen_domctl_get_device_group { +uint32_t machine_bdf;/* IN */ +uint32_t max_sdevs;/* IN */ +uint32_t num_sdevs;/* OUT */ +XEN_GUEST_HANDLE_64 (uint32) sdev_array;/* OUT */ +}; +typedef struct xen_domctl_get_device_group xen_domctl_get_device_group_t ; +DEFINE_XEN_GUEST_HANDLE (xen_domctl_get_device_group_t);/* Pass-through interrupts: bind real irq -> hvm devfn. */ #define XEN_DOMCTL_bind_pt_irq 38
@@ -619,6 +629,7 @@ struct xen_domctl {struct xen_domctl_hvmcontext hvmcontext;struct xen_domctl_address_size address_size;struct xen_domctl_sendtrigger sendtrigger; +struct xen_domctl_get_device_group get_device_group;struct xen_domctl_assign_device assign_device;struct xen_domctl_bind_pt_irq bind_pt_irq;struct xen_domctl_memory_mapping memory_mapping;
xen/include/xen/iommu.h +3 -0
@@ -59,6 +59,8 @@ int device_assigned(u8 bus, u8 devfn);int device_assigned (u8 bus,u8 devfn);int assign_device (struct domain *d,u8 bus,u8 devfn);void deassign_device (struct domain *d,u8 bus,u8 devfn); +int iommu_get_device_group (struct domain *d,u8 bus,u8 devfn, +XEN_GUEST_HANDLE_64 (uint32) buf,int max_sdevs);void reassign_device_ownership (struct domain *source,struct domain *target,u8 bus,u8 devfn);
@@ -95,6 +97,7 @@ struct iommu_ops {int (*unmap_page)(struct domain *d,unsigned long gfn);void (*reassign_device)(struct domain *s,struct domain *t,u8 bus,u8 devfn); + int (*get_device_group_id)(u8 bus, u8 devfn); };#endif /* _IOMMU_H_ */
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel