amd iommu: support ats/gpgpu passthru on iommuv2 systems
PATCH v5 1/1 amd iommu: support ats/gpgpu passthru on iommuv2 systems
Hi,
This is patch set v5. It includes all pending patches that are needed to enable gpgpu passthrough and heterogeneous computing in guest OSes. Basically, this patch set gives guest VM the same capability of running openCL applications on amd platforms as native OSes. Upstream Linux 3.3 rc2 with amd iommuv2 kernel driver has been tested well as guest OS, and since last submission, lots of regression tests have been done to make sure this does not break non-iommuv2 systems. Please review it, feedbacks are appreciated.
Many thanks,
Wei
For more details, please refer to old thread.
http://lists.xen.org/archives/html/xen-devel/2012-01/msg01646.html
and, for an overview of the design, please refer to
http://www.amd64.org/pub/iommuv2.png
======================================================================
changes in v5:
* Remove patch 2 after upstream c/s 24729:6f6a6d1d2fb6
changes in v4:
* Only tool part in this version, since hypervisor patches have already been committed.
* rename guest config option from "iommu = {0,1}" to "guest_iommu = {0,1}"
* add description into docs/man/xl.cfg.pod.5
changes in v3:
* Use xenstore to receive guest iommu configuration instead of adding in a new field in hvm_info_table.
* Support pci segment in vbdf to mbdf bind.
* Make hypercalls visible for non-x86 platforms.
* A few code cleanups according to comments from Jan and Ian.
Changes in v2:
* Do not use linked list to access guest iommu tables.
* Do not parse iommu parameter in libxl_device_model_info again.
* Fix incorrect logical calculation in patch 11.
* Fix hypercall definition for non-x86 systems.
PATCH v5 1/1 amd iommu: Add 2 hypercalls for libxc
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1328885349 -3600
# Node ID 9cf24ad61936e5d9a6acac9de1dc1fac6694c31e # Parent 593deed8f62d73dc617f6dd0a95abd05755d002e amd iommu: Add 2 hypercalls for libxc
iommu_set_msi: used by qemu to inform hypervisor iommu vector number in guest space. Hypervisor needs this vector to inject msi into guest after write PPR log entry into guest buffer.
iommu_bind_bdf: used by xl to bind virtual bdf of passthru device to machine bdf. IOMMU emulator receives iommu cmd from guest OS and then forwards them to host iommu. But virtual device id in cmds from guest must be converted into physical id before sending them to real hardware.
xen/drivers/passthrough/amd/iommu_guest.c +68 -9
@@ -48,14 +48,31 @@ (reg)->hi = (val) >>32 ; \ }while (0 ) -static unsigned int machine_bdf(struct domain *d, uint16_t guest_bdf) +static unsigned int machine_bdf(struct domain *d, uint16_t guest_seg, +uint16_t guest_bdf) { -return guest_bdf; +struct pci_dev *pdev; +uint16_t mbdf =0 ; + +for_each_pdev ( d, pdev ) + { +if ( (pdev->gbdf == guest_bdf) && (pdev->gseg == guest_seg) ) + { + mbdf =PCI_BDF2 (pdev->bus, pdev->devfn); +break ; + } + } +return mbdf; } -static uint16_t guest_bdf (struct domain *d,uint16_t machine_bdf) +static uint16_t guest_bdf (struct domain *d,uint16_t machine_seg, +uint16_t machine_bdf) { -return machine_bdf; +struct pci_dev *pdev; + + pdev =pci_get_pdev_by_domain (d, machine_seg,PCI_BUS (machine_bdf), +PCI_DEVFN2 (machine_bdf)); +return pdev->gbdf; }static inline struct guest_iommu *domain_iommu (struct domain *d)
@@ -207,7 +224,7 @@ void guest_iommu_add_ppr_log(struct doma log = log_base + tail % (PAGE_SIZE /sizeof (ppr_entry_t));/* Convert physical device id back into virtual device id */ - gdev_id =guest_bdf (d,iommu_get_devid_from_cmd (entry[0 ])); + gdev_id =guest_bdf (d,0 ,iommu_get_devid_from_cmd (entry[0 ]));iommu_set_devid_to_cmd (&entry[0 ], gdev_id);memcpy (log, entry,sizeof (ppr_entry_t));
@@ -256,7 +273,7 @@ void guest_iommu_add_event_log(struct do log = log_base + tail % (PAGE_SIZE /sizeof (event_entry_t));/* re-write physical device id into virtual device id */ - dev_id =guest_bdf (d,iommu_get_devid_from_cmd (entry[0 ])); + dev_id =guest_bdf (d,0 ,iommu_get_devid_from_cmd (entry[0 ]));iommu_set_devid_to_cmd (&entry[0 ], dev_id);memcpy (log, entry,sizeof (event_entry_t));
@@ -278,7 +295,7 @@ static int do_complete_ppr_request(strucuint16_t dev_id;struct amd_iommu *iommu; - dev_id =machine_bdf (d,iommu_get_devid_from_cmd (cmd->data[0 ])); + dev_id =machine_bdf (d,0 ,iommu_get_devid_from_cmd (cmd->data[0 ])); iommu =find_iommu_for_device (0 , dev_id);if ( !iommu )
@@ -330,7 +347,7 @@ static int do_invalidate_iotlb_pages(strstruct amd_iommu *iommu;uint16_t dev_id; - dev_id =machine_bdf (d,iommu_get_devid_from_cmd (cmd->data[0 ])); + dev_id =machine_bdf (d,0 ,iommu_get_devid_from_cmd (cmd->data[0 ])); iommu =find_iommu_for_device (0 , dev_id);if ( !iommu )
@@ -409,7 +426,7 @@ static int do_invalidate_dte(struct doma g_iommu =domain_iommu (d); gbdf =iommu_get_devid_from_cmd (cmd->data[0 ]); - mbdf =machine_bdf (d, gbdf); + mbdf =machine_bdf (d,0 , gbdf);/* Guest can only update DTEs for its passthru devices */ if ( mbdf ==0 || gbdf ==0 )
@@ -916,3 +933,45 @@ const struct hvm_mmio_handler iommu_mmio .read_handler = guest_iommu_mmio_read, .write_handler = guest_iommu_mmio_write }; + +/* iommu hypercall handler */ +int iommu_bind_bdf (struct domain * d,uint16_t gseg,uint16_t gbdf, +uint16_t mseg,uint16_t mbdf) +{ +struct pci_dev *pdev; +int ret = -ENODEV ; + +if ( !iommu_found () || !iommu_enabled || !iommuv2_enabled ) +return ret; + +spin_lock (&pcidevs_lock); + +for_each_pdev ( d, pdev ) + { +if ( (pdev->seg != mseg) || (pdev->bus !=PCI_BUS (mbdf) ) || + (pdev->devfn !=PCI_DEVFN2 (mbdf)) ) +continue ; + + pdev->gseg = gseg; + pdev->gbdf = gbdf; + ret =0 ; + } + +spin_unlock (&pcidevs_lock); +return ret; +} + +void iommu_set_msi (struct domain * d,uint16_t vector,uint16_t dest, +uint16_t dest_mode,uint16_t delivery_mode, +uint16_t trig_mode) +{ +struct guest_iommu *iommu =domain_iommu (d); + +if ( !iommu ) +return ; + + iommu->msi.vector = vector; + iommu->msi.dest = dest; + iommu->msi.dest_mode = dest_mode; + iommu->msi.trig_mode = trig_mode; +}
xen/drivers/passthrough/iommu.c +34 -0
@@ -648,6 +648,40 @@ int iommu_do_domctl(put_domain (d);break ; +case XEN_DOMCTL_guest_iommu_op: + { +xen_domctl_guest_iommu_op_t * guest_op; + +if (unlikely ((d =get_domain_by_id (domctl->domain)) ==NULL ) ) + { +gdprintk (XENLOG_ERR , +"XEN_DOMCTL_guest_iommu_op: get_domain_by_id() failed\n" ); + ret = -EINVAL ; +break ; + } + + guest_op = &(domctl->u.guest_iommu_op); +switch ( guest_op->op ) + { +case XEN_DOMCTL_GUEST_IOMMU_OP_SET_MSI : +iommu_set_msi (d, guest_op->u.msi.vector, + guest_op->u.msi.dest, + guest_op->u.msi.dest_mode, + guest_op->u.msi.delivery_mode, + guest_op->u.msi.trig_mode); + ret =0 ; +break ; +case XEN_DOMCTL_GUEST_IOMMU_OP_BIND_BDF : + ret =iommu_bind_bdf (d, guest_op->u.bdf_bind.g_seg, + guest_op->u.bdf_bind.g_bdf, + guest_op->u.bdf_bind.m_seg, + guest_op->u.bdf_bind.m_bdf); +break ; + } +put_domain (d); +break ; + } +default : ret = -ENOSYS ;break ;
xen/include/public/domctl.h +27 -0
@@ -871,6 +871,31 @@ struct xen_domctl_set_access_required {typedef struct xen_domctl_set_access_required xen_domctl_set_access_required_t ;DEFINE_XEN_GUEST_HANDLE (xen_domctl_set_access_required_t); +/* Support for guest iommu emulation */ +struct xen_domctl_guest_iommu_op { +/* XEN_DOMCTL_GUEST_IOMMU_OP_* */ +#define XEN_DOMCTL_GUEST_IOMMU_OP_SET_MSI 0 +#define XEN_DOMCTL_GUEST_IOMMU_OP_BIND_BDF 1 +uint8_t op; +union { +struct iommu_msi { +uint8_t vector; +uint8_t dest; +uint8_t dest_mode; +uint8_t delivery_mode; +uint8_t trig_mode; + } msi; +struct bdf_bind { +uint16_t g_seg; +uint16_t g_bdf; +uint16_t m_seg; +uint16_t m_bdf; + } bdf_bind; + } u; +}; +typedef struct xen_domctl_guest_iommu_op xen_domctl_guest_iommu_op_t ; +DEFINE_XEN_GUEST_HANDLE (xen_domctl_guest_iommu_op_t); +struct xen_domctl {uint32_t cmd;#define XEN_DOMCTL_createdomain 1
@@ -936,6 +961,7 @@ struct xen_domctl {#define XEN_DOMCTL_set_access_required 64#define XEN_DOMCTL_audit_p2m 65#define XEN_DOMCTL_set_virq_handler 66 +#define XEN_DOMCTL_guest_iommu_op 67#define XEN_DOMCTL_gdbsx_guestmemio 1000#define XEN_DOMCTL_gdbsx_pausevcpu 1001#define XEN_DOMCTL_gdbsx_unpausevcpu 1002
@@ -984,6 +1010,7 @@ struct xen_domctl {struct xen_domctl_debug_op debug_op;struct xen_domctl_mem_event_op mem_event_op;struct xen_domctl_mem_sharing_op mem_sharing_op; +struct xen_domctl_guest_iommu_op guest_iommu_op;#if defined(__i386__) || defined(__x86_64__)struct xen_domctl_cpuid cpuid;struct xen_domctl_vcpuextstate vcpuextstate;
xen/include/xen/iommu.h +6 -0
@@ -164,6 +164,12 @@ int iommu_do_domctl(struct xen_domctl *,void iommu_iotlb_flush (struct domain *d,unsigned long gfn,unsigned int page_count);void iommu_iotlb_flush_all (struct domain *d); +/* Only used by AMD IOMMU so far */ +void iommu_set_msi (struct domain * d,uint16_t vector,uint16_t dest, +uint16_t dest_mode,uint16_t delivery_mode, +uint16_t trig_mode); +int iommu_bind_bdf (struct domain * d,uint16_t gseg,uint16_t gbdf, +uint16_t mseg,uint16_t mbdf);/* * The purpose of the iommu_dont_flush_iotlb optional cpu flag is to * avoid unecessary iotlb_flush in the low level IOMMU code.
xen/include/xen/pci.h +5 -0
@@ -62,6 +62,11 @@ struct pci_dev {const u16 seg;const u8 bus;const u8 devfn; + +/* Used by iommu to represent virtual seg and bdf value in guest space */ +u16 gseg; +u16 gbdf; +struct pci_dev_info info;struct arch_pci_dev arch;u64 vf_rlen[6 ];
Re: [PATCH 1 of 6 V5] amd iommu: Add 2 hypercalls for libxc
Quoted 26 lines
Quoted 1 line
Quoted 1 line · Wei Wang
xen/drivers/passthrough/amd/iommu_guest.c +21
-0@@ -916,3 +933,45 @@ const struct hvm_mmio_handler iommu_mmio .read_handler = guest_iommu_mmio_read, .write_handler = guest_iommu_mmio_write }; + +/* iommu hypercall handler */ +int iommu_bind_bdf (struct domain * d,uint16_t gseg,uint16_t gbdf, +uint16_t mseg,uint16_t mbdf) +{ +struct pci_dev *pdev; +int ret = -ENODEV ; + +if ( !iommu_found () || !iommu_enabled || !iommuv2_enabled ) +return ret; + +spin_lock (&pcidevs_lock); + +for_each_pdev ( d, pdev ) + { +if ( (pdev->seg != mseg) || (pdev->bus !=PCI_BUS (mbdf) ) || + (pdev->devfn !=PCI_DEVFN2 (mbdf)) ) +continue ; + + pdev->gseg = gseg; + pdev->gbdf = gbdf;
xen/drivers/passthrough/amd/iommu_guest.c const struct hvm_mmio_handler iommu_mmio · line 966
Quoted 10 lines
xen/drivers/passthrough/amd/iommu_guest.c +10
-0+ ret =0 ; + } + +spin_unlock (&pcidevs_lock); +return ret; +} + +void iommu_set_msi (struct domain * d,uint16_t vector,uint16_t dest, +uint16_t dest_mode,uint16_t delivery_mode, +uint16_t trig_mode)
Why are these all uint16_t?
Quoted 25 lines
xen/drivers/passthrough/amd/iommu_guest.c +11
-0+{ +struct guest_iommu *iommu =domain_iommu (d); + +if ( !iommu ) +return ; + + iommu->msi.vector = vector; + iommu->msi.dest = dest; + iommu->msi.dest_mode = dest_mode; + iommu->msi.trig_mode = trig_mode; +}diff -r
593deed8f62d-r9cf24ad61936xen/drivers/passthrough/iommu.cxen/drivers/passthrough/iommu.c +7
-0@@ -648,6 +648,40 @@ int iommu_do_domctl(put_domain (d);break ; +case XEN_DOMCTL_guest_iommu_op: + { +xen_domctl_guest_iommu_op_t * guest_op; + +if (unlikely ((d =get_domain_by_id (domctl->domain)) ==NULL ) ) + { + gdprintk(XENLOG_ERR,
xen/drivers/passthrough/iommu.c int iommu_do_domctl( · line 667
Quoted 10 lines
xen/drivers/passthrough/iommu.c +9
-0+ "XEN_DOMCTL_guest_iommu_op: get_domain_by_id() failed\n"); + ret = -EINVAL ; +break ; + } + + guest_op = &(domctl->u.guest_iommu_op); +switch ( guest_op->op ) + { +case XEN_DOMCTL_GUEST_IOMMU_OP_SET_MSI :
Indentation.
Quoted 32 lines
xen/drivers/passthrough/iommu.c +18
-0+iommu_set_msi (d, guest_op->u.msi.vector, + guest_op->u.msi.dest, + guest_op->u.msi.dest_mode, + guest_op->u.msi.delivery_mode, + guest_op->u.msi.trig_mode); + ret =0 ; +break ; +case XEN_DOMCTL_GUEST_IOMMU_OP_BIND_BDF : + ret =iommu_bind_bdf (d, guest_op->u.bdf_bind.g_seg, + guest_op->u.bdf_bind.g_bdf, + guest_op->u.bdf_bind.m_seg, + guest_op->u.bdf_bind.m_bdf); +break ; + } +put_domain (d); +break ; + } +default : ret = -ENOSYS ;break;diff -r
593deed8f62d-r9cf24ad61936xen/include/public/domctl.hxen/include/public/domctl.h +3
-0@@ -871,6 +871,31 @@ struct xen_domctl_set_access_required {typedef struct xen_domctl_set_access_required xen_domctl_set_access_required_t ;DEFINE_XEN_GUEST_HANDLE (xen_domctl_set_access_required_t); +/* Support for guest iommu emulation */ +struct xen_domctl_guest_iommu_op { +/* XEN_DOMCTL_GUEST_IOMMU_OP_* */
xen/include/public/domctl.h struct xen_domctl_set_access_required { · line 887
Quoted 10 lines
xen/include/public/domctl.h +10
-0+#define XEN_DOMCTL_GUEST_IOMMU_OP_SET_MSI 0 +#define XEN_DOMCTL_GUEST_IOMMU_OP_BIND_BDF 1 +uint8_t op; +union { +struct iommu_msi { +uint8_t vector; +uint8_t dest; +uint8_t dest_mode; +uint8_t delivery_mode; +uint8_t trig_mode;
Indentation again.
Jan
Quoted 15 lines
xen/include/public/domctl.h +12
-0+ } msi; +struct bdf_bind { +uint16_t g_seg; +uint16_t g_bdf; +uint16_t m_seg; +uint16_t m_bdf; + } bdf_bind; + } u; +}; +typedef struct xen_domctl_guest_iommu_op xen_domctl_guest_iommu_op_t ; +DEFINE_XEN_GUEST_HANDLE (xen_domctl_guest_iommu_op_t); +struct xen_domctl {uint32_t cmd;#define
XEN_DOMCTL_createdomain1
Re: [PATCH 1 of 6 V5] amd iommu: Add 2 hypercalls for libxc
Quoted 30 lines · Jan Beulich
Quoted 30 lines
Quoted 1 line
Quoted 1 line · Wei Wang
xen/drivers/passthrough/amd/iommu_guest.c +25
-0@@ -916,3 +933,45 @@ const struct hvm_mmio_handler iommu_mmio .read_handler = guest_iommu_mmio_read, .write_handler = guest_iommu_mmio_write }; + +/* iommu hypercall handler */ +int iommu_bind_bdf (struct domain * d,uint16_t gseg,uint16_t gbdf, +uint16_t mseg,uint16_t mbdf) +{ +struct pci_dev *pdev; +int ret = -ENODEV ; + +if ( !iommu_found () || !iommu_enabled || !iommuv2_enabled ) +return ret; + +spin_lock (&pcidevs_lock); + +for_each_pdev ( d, pdev ) + { +if ( (pdev->seg != mseg) || (pdev->bus !=PCI_BUS (mbdf) ) || + (pdev->devfn !=PCI_DEVFN2 (mbdf)) ) +continue ; + + pdev->gseg = gseg; + pdev->gbdf = gbdf; + ret =0 ; + } + +spin_unlock (&pcidevs_lock);
Quoted 8 lines
xen/drivers/passthrough/amd/iommu_guest.c const struct hvm_mmio_handler iommu_mmio · line 966
Quoted 6 lines
xen/drivers/passthrough/amd/iommu_guest.c +6
-0+return ret; +} + +void iommu_set_msi (struct domain * d,uint16_t vector,uint16_t dest, +uint16_t dest_mode,uint16_t delivery_mode, +uint16_t trig_mode)Why are these all
uint16_t?
uint8_t might better... I will change it.
Quoted 30 lines
Quoted 30 lines
xen/drivers/passthrough/amd/iommu_guest.c +11
-0+{ +struct guest_iommu *iommu =domain_iommu (d); + +if ( !iommu ) +return ; + + iommu->msi.vector = vector; + iommu->msi.dest = dest; + iommu->msi.dest_mode = dest_mode; + iommu->msi.trig_mode = trig_mode; +}diff -r
593deed8f62d-r9cf24ad61936xen/drivers/passthrough/iommu.cxen/drivers/passthrough/iommu.c +10
-0@@ -648,6 +648,40 @@ int iommu_do_domctl(put_domain (d);break ; +case XEN_DOMCTL_guest_iommu_op: + { +xen_domctl_guest_iommu_op_t * guest_op; + +if (unlikely ((d =get_domain_by_id (domctl->domain)) ==NULL ) ) + { +gdprintk (XENLOG_ERR , +"XEN_DOMCTL_guest_iommu_op: get_domain_by_id() failed\n"); + ret = -EINVAL ; +break ;
Quoted 8 lines
xen/drivers/passthrough/iommu.c int iommu_do_domctl( · line 666
Quoted 6 lines
xen/drivers/passthrough/iommu.c +6
-0+ } + + guest_op =&(domctl->u.guest_iommu_op); +switch ( guest_op->op ) + { +case XEN_DOMCTL_GUEST_IOMMU_OP_SET_MSI :Indentation.
can be fixed.
Thanks,
Wei
Quoted 65 lines
Quoted 33 lines
xen/drivers/passthrough/iommu.c +18
-0+iommu_set_msi (d, guest_op->u.msi.vector, + guest_op->u.msi.dest, + guest_op->u.msi.dest_mode, + guest_op->u.msi.delivery_mode, + guest_op->u.msi.trig_mode); + ret =0 ; +break ; +case XEN_DOMCTL_GUEST_IOMMU_OP_BIND_BDF : + ret =iommu_bind_bdf (d, guest_op->u.bdf_bind.g_seg, + guest_op->u.bdf_bind.g_bdf, + guest_op->u.bdf_bind.m_seg, + guest_op->u.bdf_bind.m_bdf); +break ; + } +put_domain (d); +break ; + } +default : ret = -ENOSYS ;break;diff -r
593deed8f62d-r9cf24ad61936xen/include/public/domctl.hxen/include/public/domctl.h +3
-0@@ -871,6 +871,31 @@ struct xen_domctl_set_access_required {typedef struct xen_domctl_set_access_required xen_domctl_set_access_required_t ;DEFINE_XEN_GUEST_HANDLE (xen_domctl_set_access_required_t); +/* Support for guest iommu emulation */ +struct xen_domctl_guest_iommu_op { +/* XEN_DOMCTL_GUEST_IOMMU_OP_* */ xen/include/public/domctl.h struct xen_domctl_set_access_required { · line 887
Quoted 10 lines
xen/include/public/domctl.h +10
-0+#define XEN_DOMCTL_GUEST_IOMMU_OP_SET_MSI 0 +#define XEN_DOMCTL_GUEST_IOMMU_OP_BIND_BDF 1 +uint8_t op; +union { +struct iommu_msi { +uint8_t vector; +uint8_t dest; +uint8_t dest_mode; +uint8_t delivery_mode; +uint8_t trig_mode;Indentation again.
Jan
Quoted 15 lines
xen/include/public/domctl.h +12
-0+ } msi; +struct bdf_bind { +uint16_t g_seg; +uint16_t g_bdf; +uint16_t m_seg; +uint16_t m_bdf; + } bdf_bind; + } u; +}; +typedef struct xen_domctl_guest_iommu_op xen_domctl_guest_iommu_op_t ; +DEFINE_XEN_GUEST_HANDLE (xen_domctl_guest_iommu_op_t); +struct xen_domctl {uint32_t cmd;#define XEN_DOMCTL_createdomain 1
PATCH v5 1/1 amd iommu: Add a hypercall for hvmloader
In reply to Wei Wang# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1328885355 -3600
# Node ID 3c47f70c84e23b96e766c062a4bbae5bcf4f6dbe # Parent 9cf24ad61936e5d9a6acac9de1dc1fac6694c31e amd iommu: Add a hypercall for hvmloader.
IOMMU MMIO base address is dynamically allocated by firmware. This patch allows hvmloader to notify hypervisor where the iommu mmio pages are.
xen/arch/x86/hvm/hvm.c +4 -0
@@ -65,6 +65,7 @@#include <public/memory.h> #include <asm/mem_event.h> #include <public/mem_event.h> +#include <asm/hvm/svm/amd-iommu-proto.h> bool_t __read_mostly hvm_enabled;
@@ -3775,6 +3776,9 @@ long do_hvm_op(unsigned long op, XEN_GUEcase HVM_PARAM_BUFIOREQ_EVTCHN : rc = -EINVAL ;break ; +case HVM_PARAM_IOMMU_BASE : + rc =guest_iommu_set_base (d, a.value); +break ; }if ( rc ==0 )
xen/include/public/hvm/params.h +2 -1
@@ -141,7 +141,8 @@/* Boolean: Enable nestedhvm (hvm only) */ #define HVM_PARAM_NESTEDHVM 24 +#define HVM_PARAM_IOMMU_BASE 27 -#define HVM_NR_PARAMS 27 +#define HVM_NR_PARAMS 28#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
PATCH v5 1/1 hvmloader: Build IVRS table
In reply to Wei Wang# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1328885357 -3600
# Node ID 16974b6159e13262126ad1e719727592184e5bea
# Parent 3c47f70c84e23b96e766c062a4bbae5bcf4f6dbe
hvmloader: Build IVRS table.
There are 32 ivrs padding entries allocated at the beginning. If a passthru device has been found from qemu bus, a padding entry will be replaced by the real device entry. Patch has been tested with both Rombios and Seabios
tools/firmware/hvmloader/acpi/acpi2_0.h +54 -0
@@ -389,6 +389,60 @@ struct acpi_20_madt_intsrcovr {#define ACPI_2_0_WAET_REVISION 0x01#define ACPI_1_0_FADT_REVISION 0x01 +#define IVRS_SIGNATURE ASCII32('I','V','R','S') +#define IVRS_REVISION 1 +#define IVRS_VASIZE 64 +#define IVRS_PASIZE 52 +#define IVRS_GVASIZE 64 + +#define IVHD_BLOCK_TYPE 0x10 +#define IVHD_FLAG_HTTUNEN (1 << 0) +#define IVHD_FLAG_PASSPW (1 << 1) +#define IVHD_FLAG_RESPASSPW (1 << 2) +#define IVHD_FLAG_ISOC (1 << 3) +#define IVHD_FLAG_IOTLBSUP (1 << 4) +#define IVHD_FLAG_COHERENT (1 << 5) +#define IVHD_FLAG_PREFSUP (1 << 6) +#define IVHD_FLAG_PPRSUP (1 << 7) + +#define IVHD_EFR_GTSUP (1 << 2) +#define IVHD_EFR_IASUP (1 << 5) + +#define IVHD_SELECT_4_BYTE 0x2 + +struct ivrs_ivhd_block +{ +uint8_t type; +uint8_t flags; +uint16_t length; +uint16_t devid; +uint16_t cap_offset; +uint64_t iommu_base_addr; +uint16_t pci_segment; +uint16_t iommu_info; +uint32_t reserved; +}; + +/* IVHD 4-byte device entries */ +struct ivrs_ivhd_device +{ +uint8_t type; +uint16_t dev_id; +uint8_t flags; +}; + +#define PT_DEV_MAX_NR 32 +#define IOMMU_CAP_OFFSET 0x40 +struct acpi_40_ivrs +{ +struct acpi_header header; +uint32_t iv_info; +uint32_t reserved[2 ]; +struct ivrs_ivhd_block ivhd_block; +struct ivrs_ivhd_device ivhd_device[PT_DEV_MAX_NR ]; +}; + +#pragma pack ()struct acpi_config {
tools/firmware/hvmloader/acpi/build.c +91 -0
115 lines not on this page · raw message
tools/firmware/hvmloader/pci.c +29 -1
@@ -34,11 +34,17 @@ unsigned long pci_mem_end = PCI_MEM_END;enum virtual_vga virtual_vga = VGA_none;unsigned long igd_opregion_pgbase =0 ; +/* support up to 32 passthrough devices */ +#define PT_DEV_MAX_NR 32 +uint32_t ptdev_bdf[PT_DEV_MAX_NR ]; +uint32_t ptdev_nr; +uint32_t iommu_bdf =0 ; +void pci_setup (void ) {uint32_t base, devfn, bar_reg, bar_data, bar_sz, cmd, mmio_total =0 ;uint32_t vga_devfn =256 ; -uint16_t class, vendor_id, device_id; +uint16_t class, vendor_id, device_id, sub_vendor_id;unsigned int bar, pin, link, isa_irq;/* Resources assignable to PCI devices via BARs. */
@@ -72,12 +78,34 @@ void pci_setup(void) class =pci_readw (devfn,PCI_CLASS_DEVICE ); vendor_id =pci_readw (devfn,PCI_VENDOR_ID ); device_id =pci_readw (devfn,PCI_DEVICE_ID ); + sub_vendor_id =pci_readw (devfn,PCI_SUBSYSTEM_VENDOR_ID ); +if ( (vendor_id ==0xffff ) && (device_id ==0xffff ) )continue ;ASSERT ((devfn !=PCI_ISA_DEVFN ) || ((vendor_id ==0x8086 ) && (device_id ==0x7000 ))); +/* Found amd iommu device. */ +if ( class ==0x0806 && vendor_id ==0x1022 ) + { + iommu_bdf = devfn; +continue ; + } +/* IVRS: Detecting passthrough devices. +* sub_vendor_id != citrix && sub_vendor_id != qemu */ +if ( sub_vendor_id !=0x5853 && sub_vendor_id !=0x1af4 ) + { +/* found amd iommu device */ +if ( ptdev_nr <PT_DEV_MAX_NR ) + { + ptdev_bdf[ptdev_nr] = devfn; + ptdev_nr++; + } +else +printf ("Number of passthru devices > PT_DEV_MAX_NR \n" ); + } +switch ( class ) {case 0x0300 :
PATCH v5 1/1 libxc: add wrappers for new hypercalls
In reply to Wei Wang# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1328885358 -3600
# Node ID db10bcca843c65260426800f9e05da8359faf439 # Parent 16974b6159e13262126ad1e719727592184e5bea
libxc: add wrappers for new hypercalls Please see patch 1 for hypercall description.
tools/libxc/xc_domain.c +53 -0
@@ -1352,6 +1352,59 @@ int xc_domain_bind_pt_isa_irq( PT_IRQ_TYPE_ISA, 0, 0, 0, machine_irq)); } +int xc_domain_update_iommu_msi ( +xc_interface *xch, +uint32_t domid, +uint8_t vector, +uint8_t dest, +uint8_t dest_mode, +uint8_t delivery_mode, +uint8_t trig_mode) +{ +int rc; +DECLARE_DOMCTL ; +xen_domctl_guest_iommu_op_t * iommu_op; + + domctl.cmd = XEN_DOMCTL_guest_iommu_op; + domctl.domain = (domid_t )domid; + + iommu_op = &(domctl.u.guest_iommu_op); + iommu_op->op =XEN_DOMCTL_GUEST_IOMMU_OP_SET_MSI ; + iommu_op->u.msi.vector = vector; + iommu_op->u.msi.dest = dest; + iommu_op->u.msi.dest_mode = dest_mode; + iommu_op->u.msi.delivery_mode = delivery_mode; + iommu_op->u.msi.trig_mode = trig_mode; + + rc =do_domctl (xch, &domctl); +return rc; +} + +int xc_domain_bind_pt_bdf (xc_interface *xch, +uint32_t domid, +uint16_t gseg, +uint16_t gbdf, +uint16_t mseg, +uint16_t mbdf) +{ +int rc; +DECLARE_DOMCTL ; +xen_domctl_guest_iommu_op_t * guest_op; + + domctl.cmd = XEN_DOMCTL_guest_iommu_op; + domctl.domain = (domid_t )domid; + + guest_op = &(domctl.u.guest_iommu_op); + guest_op->op =XEN_DOMCTL_GUEST_IOMMU_OP_BIND_BDF ; + guest_op->u.bdf_bind.g_seg = gseg; + guest_op->u.bdf_bind.g_bdf = gbdf; + guest_op->u.bdf_bind.m_seg = mseg; + guest_op->u.bdf_bind.m_bdf = mbdf; + + rc =do_domctl (xch, &domctl); +return rc; +} + int xc_domain_memory_mapping( xc_interface *xch, uint32_t domid,
tools/libxc/xenctrl.h +15 -0
@@ -1725,6 +1725,21 @@ int xc_domain_bind_pt_isa_irq(xc_interfauint32_t domid, uint8_t machine_irq); +int xc_domain_bind_pt_bdf (xc_interface *xch, +uint32_t domid, +uint16_t gseg, +uint16_t gbdf, +uint16_t mseg, +uint16_t mbdf); + +int xc_domain_update_iommu_msi (xc_interface *xch, +uint32_t domid, +uint8_t vector, +uint8_t dest, +uint8_t dest_mode, +uint8_t delivery_mode, +uint8_t trig_mode); +int xc_domain_set_machine_address_size (xc_interface *xch,uint32_t domid,unsigned int width);
PATCH v5 1/1 libxl: bind virtual bdf to physical bdf after device assignment
In reply to Wei Wang# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1328885359 -3600
# Node ID c39f5736e36429091839a8db10179deeb6b0c622
# Parent db10bcca843c65260426800f9e05da8359faf439
libxl: bind virtual bdf to physical bdf after device assignment
tools/libxl/libxl_pci.c +7 -0
@@ -721,6 +721,13 @@ out:LIBXL__LOG_ERRNOVAL (ctx,LIBXL__LOG_ERROR , rc,"xc_assign_device failed" );return ERROR_FAIL ; } +if (LIBXL__DOMAIN_IS_TYPE (gc, domid,HVM )) { + rc =xc_domain_bind_pt_bdf (ctx->xch, domid,0 , pcidev->vdevfn, pcidev->domain,pcidev_encode_bdf (pcidev)); +if ( rc ) { +LIBXL__LOG_ERRNOVAL (ctx,LIBXL__LOG_ERROR , rc,"xc_domain_bind_pt_bdf failed" ); +return ERROR_FAIL ; + } + } }if (!starting)
PATCH v5 1/1 libxl: Introduce a new guest config file parameter
In reply to Wei Wang# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1328885360 -3600
# Node ID 09721a5ff84451b5a95d6cdc445867fa158dd449
# Parent c39f5736e36429091839a8db10179deeb6b0c622
libxl: Introduce a new guest config file parameter
Use guest_iommu = {1,0} to enable or disable guest iommu emulation. Default value is 0. Regression tests have been done to make sure it does not break non-iommuv2 systems.
docs/man/xl.cfg.pod.5 +4 -0
@@ -820,6 +820,10 @@ certainly belong in a more appropriate s Enable graphics device PCI passthrough. XXX which device is passed through ? +=item B<guest_iommu=BOOLEAN> + +Enable virtual iommu device for hvm guest. It should be enabled to passthrough AMD GPGPU. + =item B<nomigrate=BOOLEAN> Disable migration of this domain. This enables certain other features
tools/libxl/libxl_create.c +4 -1
@@ -100,6 +100,7 @@ int libxl_init_build_info(libxl_ctx *ctx b_info->u.hvm.vpt_align =1 ; b_info->u.hvm.timer_mode =1 ; b_info->u.hvm.nested_hvm =0 ; + b_info->u.hvm.guest_iommu =0 ; b_info->u.hvm.no_incr_generationid =0 ; b_info->u.hvm.stdvga =0 ;
@@ -169,13 +170,15 @@ int libxl__domain_build(libxl__gc *gc, vments[4 ] ="start_time" ; vments[5 ] =libxl__sprintf (gc,"%lu.%02d" , start_time.tv_sec,(int )start_time.tv_usec/10000 ); - localents =libxl__calloc (gc,7 ,sizeof (char *)); + localents =libxl__calloc (gc,9 ,sizeof (char *)); localents[0 ] ="platform/acpi" ; localents[1 ] = (info->u.hvm.acpi) ?"1" :"0" ; localents[2 ] ="platform/acpi_s3" ; localents[3 ] = (info->u.hvm.acpi_s3) ?"1" :"0" ; localents[4 ] ="platform/acpi_s4" ; localents[5 ] = (info->u.hvm.acpi_s4) ?"1" :"0" ; + localents[6 ] ="guest_iommu" ; + localents[7 ] = (info->u.hvm.guest_iommu) ?"1" :"0" ;break ;case LIBXL_DOMAIN_TYPE_PV :
tools/libxl/libxl_types.idl +1 -0
@@ -239,6 +239,7 @@ libxl_domain_build_info = Struct("domain ("vpt_align", bool), ("timer_mode", libxl_timer_mode), ("nested_hvm", bool), + ("guest_iommu", bool), ("no_incr_generationid", bool), ("nographic", bool), ("stdvga", bool),
tools/libxl/xl_cmdimpl.c +2 -0
@@ -748,6 +748,8 @@ static void parse_config_data(const charif (!xlu_cfg_get_long (config,"nestedhvm" , &l,0 )) b_info->u.hvm.nested_hvm = l; +if (!xlu_cfg_get_long (config,"guest_iommu" , &l,0 )) + b_info->u.hvm.guest_iommu = l;break ;case LIBXL_DOMAIN_TYPE_PV : {
Wei Wang writes ("[PATCH 0 of 6 V5] amd iommu: support ats/gpgpu passthru on iommuv2 systems"):
Quoted 1 line
This is patch set v5. It includes all pending patches that are needed to enable gpgpu passthrough and heterogeneous computing in guest OSes. Basically, this patch set gives guest VM the same capability of running openCL applications on amd platforms as native OSes. Upstream Linux 3.3 rc2 with amd iommuv2 kernel driver has been tested well as guest OS, and since last submission, lots of regression tests have been done to make sure this does not break non-iommuv2 systems. Please review it, feedbacks are appreciated.
Thanks. I'm not qualified to review the hypervisor parts, but the explanation seems to make sense and the tools parts look OK.
So as for these three:
[PATCH 4 of 6 V5] libxc: add wrappers for new hypercalls [PATCH 5 of 6 V5] libxl: bind virtual bdf to physical bdf ... [PATCH 6 of 6 V5] libxl: Introduce a new guest config file parameter
I do have a couple of minor niggles which you might like to address if you repost:
Quoted 4 lines
libxl: Introduce a new guest config file parameter
Useguest_iommu= {1,0} to enable or disable guest iommu emulation. Default value is 0. Regression tests have been done to make sure it does not break non-iommuv2 systems.
It's conventional to leave a blank line between the summary line and the bulk of the description.
Quoted 4 lines
diff -r
c39f5736e364-r09721a5ff844docs/man/xl.cfg.pod.5docs/man/xl.cfg.pod.5 +0
-0@@ -820,6 +820,10 @@ certainly belong in a more appropriate s
...
docs/man/xl.cfg.pod.5
Quoted 4 lines
+=item B<guest_iommu=BOOLEAN>
docs/man/xl.cfg.pod.5 +3
-0+ +Enable virtual iommu device for hvm guest. It should be enabled to passthrough AMD GPGPU. +
It would be nice for that line to be wrapped to fit within 75-80 columns.
Thanks,
Ian.
Quoted 6 lines · Ian Jackson
Wei Wang writes ("[PATCH 0 of 6 V5] amd iommu: support ats/gpgpu passthru on iommuv2 systems"):
Quoted 1 line
This is patch set v5. It includes all pending patches that are needed to enable gpgpu passthrough and heterogeneous computing in guest OSes. Basically, this patch set gives guest VM the same capability of running openCL applications on amd platforms as native OSes. Upstream Linux 3.3 rc2 with amd iommuv2 kernel driver has been tested well as guest OS, and since last submission, lots of regression tests have been done to make sure this does not break non-iommuv2 systems. Please review it, feedbacks are appreciated.
Thanks. I'm not qualified to review the hypervisor parts, but the explanation seems to make sense and the tools parts look OK.
Quoted 8 lines
So as for these three:
[PATCH 4 of 6 V5] libxc: add wrappers for new hypercalls [PATCH 5 of 6 V5] libxl: bind virtual bdf to physical bdf ... [PATCH 6 of 6 V5] libxl: Introduce a new guest config file parameter
Acked-by Ian Jackson<[email protected]>
Cool! thanks a lot for reviewing it and moving this forward. Issues you mentioned will be fixed in my next post.
Thanks,
Wei
Quoted 27 lines
I do have a couple of minor niggles which you might like to address if you repost:
Quoted 4 lines
libxl: Introduce a new guest config file parameter
Useguest_iommu= {1,0} to enable or disable guest iommu emulation. Default value is 0. Regression tests have been done to make sure it does not break non-iommuv2 systems.It's conventional to leave a blank line between the summary line and the bulk of the description.
Quoted 4 lines
diff -r
c39f5736e364-r09721a5ff844docs/man/xl.cfg.pod.5docs/man/xl.cfg.pod.5 +0
-0@@ -820,6 +820,10 @@ certainly belong in a more appropriate s...
docs/man/xl.cfg.pod.5
Quoted 4 lines
+=item B<guest_iommu=BOOLEAN>
docs/man/xl.cfg.pod.5 +3
-0+ +Enable virtual iommu device for hvm guest. It should be enabled to passthrough AMD GPGPU. +It would be nice for that line to be wrapped to fit within 75-80 columns.
Thanks,
Ian.