AMD IOMMU: (2nd try) Handle sibling device assignment correctly
PATCH 1/1 AMD IOMMU: (2nd try) Handle sibling device assignment correctly
Updated version, please comment!
Thanks,
Wei
Devices on AMD IOMMU system share a same set of IO page tables if they are indexed by a same device ID in device table. To prevent these sibling devices from being assigned to different domains, a successful device assignment requires all sibling devices are owned by either pciback or the target domain. This is a trial patch with minor modifications in the common interface to handle this situation correctly. VTD code has also been slightly touched please let me know if it breaks any VTD functionality. Thanks!
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 +8 -3
@@ -529,15 +529,19 @@ long arch_do_domctl(case XEN_DOMCTL_test_assign_device: {u8 bus, devfn; +struct domain *d; ret = -EINVAL ;if ( !iommu_enabled ) +break ; + +if (unlikely ((d =rcu_lock_domain_by_id (domctl->domain)) ==NULL ) )break ; bus = (domctl->u.assign_device.machine_bdf >>16 ) &0xff ; devfn = (domctl->u.assign_device.machine_bdf >>8 ) &0xff ; -if (device_assigned (bus, devfn) ) +if (device_assigned (d, bus, devfn) ) { gdprintk(XENLOG_ERR, "XEN_DOMCTL_test_assign_device: " "%x:%x:%x already assigned, or non-existent\n",
@@ -545,6 +549,7 @@ long arch_do_domctl(break ; } ret =0 ; +rcu_unlock_domain (d); }break ;
@@ -566,7 +571,7 @@ long arch_do_domctl( bus = (domctl->u.assign_device.machine_bdf >>16 ) &0xff ; devfn = (domctl->u.assign_device.machine_bdf >>8 ) &0xff ; -if (device_assigned (bus, devfn) ) +if (device_assigned (d, bus, devfn) ) { gdprintk(XENLOG_ERR, "XEN_DOMCTL_assign_device: " "%x:%x:%x already assigned, or non-existent\n",
@@ -599,7 +604,7 @@ long arch_do_domctl( bus = (domctl->u.assign_device.machine_bdf >>16 ) &0xff ; devfn = (domctl->u.assign_device.machine_bdf >>8 ) &0xff ; -if ( !device_assigned (bus, devfn) ) +if ( !device_assigned (d, bus, devfn) )break ;deassign_device (d, bus, devfn);
xen/arch/x86/setup.c +3 -0
@@ -38,6 +38,7 @@#include <asm/edd.h> #include <xsm/xsm.h> #include <asm/tboot.h> +#include <xen/iommu.h> #if defined(CONFIG_X86_64 )#define BOOTSTRAP_DIRECTMAP_END (1UL << 32)/* 4GB */
@@ -1041,6 +1042,8 @@ void __init __start_xen(unsigned long mb cmdline) != 0)panic ("Could not set up DOM0 guest OS\n" ); +iommu_setup_devices (dom0, cmdline); +/* Scrub RAM that is still free and so may go to an unprivileged domain. */ scrub_heap_pages ();
xen/drivers/passthrough/amd/pci_amd_iommu.c +52 -9
86 lines not on this page · raw message
xen/drivers/passthrough/iommu.c +51 -0
55 lines not on this page · raw message
xen/drivers/passthrough/vtd/iommu.c +2 -1
@@ -1789,7 +1789,7 @@ int intel_vtd_setup(void)* If the device isn't owned by dom0, it means it already * has been assigned to other domain, or it's not exist. */ -int device_assigned (u8 bus,u8 devfn) +static int intel_iommu_device_assigned (struct domain *d,u8 bus,u8 devfn) {struct pci_dev *pdev;
@@ -1915,6 +1915,7 @@ struct iommu_ops intel_iommu_ops = { .map_page = intel_iommu_map_page, .unmap_page = intel_iommu_unmap_page, .reassign_device = reassign_device_ownership, + .test_assigned = intel_iommu_device_assigned, };/*
xen/include/xen/iommu.h +3 -1
@@ -53,9 +53,10 @@ struct iommu {struct intel_iommu *intel; }; +void iommu_setup_devices (struct domain *domain,char *cmdline);int iommu_domain_init (struct domain *d);void iommu_domain_destroy (struct domain *d); -int device_assigned (u8 bus,u8 devfn); +int device_assigned (struct domain *d,u8 bus,u8 devfn);int assign_device (struct domain *d,u8 bus,u8 devfn);void deassign_device (struct domain *d,u8 bus,u8 devfn); void reassign_device_ownership(struct domain *source,
@@ -94,6 +95,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 (*test_assigned)(struct domain *d, u8 bus, u8 devfn); };#endif /* _IOMMU_H_ */
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel