diff --git a/xen/drivers/passthrough/amd/iommu_intr.c b/xen/drivers/passthrough/amd/iommu_intr.c index 7fc796dec2..f07fd9e3d9 100644 --- a/xen/drivers/passthrough/amd/iommu_intr.c +++ b/xen/drivers/passthrough/amd/iommu_intr.c @@ -649,6 +649,19 @@ bool __init cf_check iov_supports_xt(void) if ( !iommu_enable || !iommu_intremap ) return false; + if ( unlikely(!cpu_has_cx16) ) + { + AMD_IOMMU_ERROR("no CMPXCHG16B support, disabling IOMMU\n"); + /* + * Disable IOMMU support at once: there's no reason to check for CX16 + * yet again when attempting to initialize IOMMU DMA remapping + * functionality or interrupt remapping without x2APIC support. + */ + iommu_enable = false; + iommu_intremap = iommu_intremap_off; + return false; + } + if ( amd_iommu_prepare(true) ) return false; diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index 73dcc4a2dd..f96f59440b 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -309,6 +309,12 @@ static int __init cf_check iov_detect(void) if ( !iommu_enable && !iommu_intremap ) return 0; + if ( unlikely(!cpu_has_cx16) ) + { + AMD_IOMMU_ERROR("no CMPXCHG16B support, disabling IOMMU\n"); + return -ENODEV; + } + if ( (init_done ? amd_iommu_init_late() : amd_iommu_init(false)) != 0 ) { diff --git a/xen/drivers/passthrough/vtd/intremap.c b/xen/drivers/passthrough/vtd/intremap.c index c504852eb8..233db5cb64 100644 --- a/xen/drivers/passthrough/vtd/intremap.c +++ b/xen/drivers/passthrough/vtd/intremap.c @@ -150,6 +150,19 @@ bool __init cf_check intel_iommu_supports_eim(void) if ( !iommu_qinval || !iommu_intremap || list_empty(&acpi_drhd_units) ) return false; + if ( unlikely(!cpu_has_cx16) ) + { + printk(XENLOG_ERR VTDPREFIX "no CMPXCHG16B support, disabling IOMMU\n"); + /* + * Disable IOMMU support at once: there's no reason to check for CX16 + * yet again when attempting to initialize IOMMU DMA remapping + * functionality or interrupt remapping without x2APIC support. + */ + iommu_enable = false; + iommu_intremap = iommu_intremap_off; + return false; + } + /* We MUST have a DRHD unit for each IOAPIC. */ for ( apic = 0; apic < nr_ioapics; apic++ ) if ( !ioapic_to_drhd(IO_APIC_ID(apic)) ) diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index 27a4d16401..3daedc4f55 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -2633,6 +2633,13 @@ static int __init cf_check vtd_setup(void) int ret; bool reg_inval_supported = true; + if ( unlikely(!cpu_has_cx16) ) + { + printk(XENLOG_ERR VTDPREFIX "no CMPXCHG16B support, disabling IOMMU\n"); + ret = -ENODEV; + goto error; + } + if ( list_empty(&acpi_drhd_units) ) { ret = -ENODEV;