diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index 3430e39a29..8cbbd7c6c9 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -746,6 +746,7 @@ static void cf_check amd_dump_page_tables(struct domain *d) } static const struct iommu_ops __initconst_cf_clobber _iommu_ops = { + .page_sizes = PAGE_SIZE_4K, .init = amd_iommu_domain_init, .hwdom_init = amd_iommu_hwdom_init, .quarantine_init = amd_iommu_quarantine_init, diff --git a/xen/drivers/passthrough/arm/ipmmu-vmsa.c b/xen/drivers/passthrough/arm/ipmmu-vmsa.c index d2572bcd30..5a7b332bcc 100644 --- a/xen/drivers/passthrough/arm/ipmmu-vmsa.c +++ b/xen/drivers/passthrough/arm/ipmmu-vmsa.c @@ -1355,6 +1355,7 @@ static void ipmmu_iommu_domain_teardown(struct domain *d) static const struct iommu_ops ipmmu_iommu_ops = { + .page_sizes = PAGE_SIZE_4K, .init = ipmmu_iommu_domain_init, .hwdom_init = arch_iommu_hwdom_init, .teardown = ipmmu_iommu_domain_teardown, diff --git a/xen/drivers/passthrough/arm/smmu-v3.c b/xen/drivers/passthrough/arm/smmu-v3.c index 71b022fe7f..2822ffe05f 100644 --- a/xen/drivers/passthrough/arm/smmu-v3.c +++ b/xen/drivers/passthrough/arm/smmu-v3.c @@ -3411,7 +3411,8 @@ static void arm_smmu_iommu_xen_domain_teardown(struct domain *d) } static const struct iommu_ops arm_smmu_iommu_ops = { - .init = arm_smmu_iommu_xen_domain_init, + .page_sizes = PAGE_SIZE_4K, + .init = arm_smmu_iommu_xen_domain_init, .hwdom_init = arch_iommu_hwdom_init, .teardown = arm_smmu_iommu_xen_domain_teardown, .iotlb_flush = arm_smmu_iotlb_flush, diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c index b186c28dff..5cacb2dd99 100644 --- a/xen/drivers/passthrough/arm/smmu.c +++ b/xen/drivers/passthrough/arm/smmu.c @@ -2858,6 +2858,7 @@ static void arm_smmu_iommu_domain_teardown(struct domain *d) } static const struct iommu_ops arm_smmu_iommu_ops = { + .page_sizes = PAGE_SIZE_4K, .init = arm_smmu_iommu_domain_init, .hwdom_init = arch_iommu_hwdom_init, .add_device = arm_smmu_dt_add_device_generic, diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index 73a7da71cd..1109a86532 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -494,7 +494,17 @@ int __init iommu_setup(void) if ( iommu_enable ) { + const struct iommu_ops *ops = NULL; + rc = iommu_hardware_setup(); + if ( !rc ) + ops = iommu_get_ops(); + if ( ops && (ops->page_sizes & -ops->page_sizes) != PAGE_SIZE ) + { + printk(XENLOG_ERR "IOMMU: page size mask %lx unsupported\n", + ops->page_sizes); + rc = ops->page_sizes ? -EPERM : -ENODATA; + } iommu_enabled = (rc == 0); } diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index f68d960d75..cff37c0c31 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -3127,6 +3127,7 @@ static int cf_check intel_iommu_quarantine_init(struct pci_dev *pdev, } static const struct iommu_ops __initconst_cf_clobber vtd_ops = { + .page_sizes = PAGE_SIZE_4K, .init = intel_iommu_domain_init, .hwdom_init = intel_iommu_hwdom_init, .quarantine_init = intel_iommu_quarantine_init, diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h index 3a83981464..f7e8d5f287 100644 --- a/xen/include/xen/iommu.h +++ b/xen/include/xen/iommu.h @@ -231,6 +231,7 @@ struct page_info; typedef int iommu_grdm_t(xen_pfn_t start, xen_ulong_t nr, u32 id, void *ctxt); struct iommu_ops { + unsigned long page_sizes; int (*init)(struct domain *d); void (*hwdom_init)(struct domain *d); int (*quarantine_init)(device_t *dev, bool scratch_page);