@@ -629,6 +629,7 @@ static void amd_dump_page_tables(struct
}
static const struct iommu_ops __initconstrel _iommu_ops = {
+ .page_sizes = PAGE_SIZE_4K,
.init = amd_iommu_domain_init,
.hwdom_init = amd_iommu_hwdom_init,
.quarantine_init = amd_iommu_quarantine_init,
@@ -1298,6 +1298,7 @@ static void ipmmu_iommu_domain_teardown(
static const struct iommu_ops ipmmu_iommu_ops =
{
+ .page_sizes = PAGE_SIZE_4K,
.init = ipmmu_iommu_domain_init,
.hwdom_init = ipmmu_iommu_hwdom_init,
.teardown = ipmmu_iommu_domain_teardown,
@@ -2873,6 +2873,7 @@ static void arm_smmu_iommu_domain_teardo
}
static const struct iommu_ops arm_smmu_iommu_ops = {
+ .page_sizes = PAGE_SIZE_4K,
.init = arm_smmu_iommu_domain_init,
.hwdom_init = arm_smmu_iommu_hwdom_init,
.add_device = arm_smmu_dt_add_device_generic,
@@ -3426,7 +3426,8 @@ static void arm_smmu_iommu_xen_domain_te
}
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 = arm_smmu_iommu_hwdom_init,
.teardown = arm_smmu_iommu_xen_domain_teardown,
.iotlb_flush = arm_smmu_iotlb_flush,
@@ -470,7 +470,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);
}
@@ -2891,6 +2891,7 @@ static int __init intel_iommu_quarantine
}
static struct iommu_ops __initdata vtd_ops = {
+ .page_sizes = PAGE_SIZE_4K,
.init = intel_iommu_domain_init,
.hwdom_init = intel_iommu_hwdom_init,
.quarantine_init = intel_iommu_quarantine_init,
@@ -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)(struct domain *d);