@@ -135,6 +135,9 @@ struct page_info *__must_check iommu_alloc_pgtable(struct domain_iommu *hd,
uint64_t contig_mask);
void iommu_queue_free_pgtable(struct domain_iommu *hd, struct page_info *pg);
+/* Check [start, end) unity map range for correctness. */
+bool iommu_unity_region_ok(mfn_t start, mfn_t end);
+
#endif /* !__ARCH_X86_IOMMU_H__ */
/*
* Local variables:
@@ -405,41 +405,9 @@ static int __init parse_ivmd_block(const struct acpi_ivrs_memory *ivmd_block)
return 0;
}
- if ( !e820_all_mapped(base, limit + PAGE_SIZE, E820_RESERVED) )
- {
- paddr_t addr;
-
- AMD_IOMMU_WARN("IVMD: [%lx,%lx) is not (entirely) in reserved memory\n",
- base, limit + PAGE_SIZE);
-
- for ( addr = base; addr <= limit; addr += PAGE_SIZE )
- {
- unsigned int type = page_get_ram_type(maddr_to_mfn(addr));
-
- if ( type == RAM_TYPE_UNKNOWN )
- {
- if ( e820_add_range(addr, addr + PAGE_SIZE,
- E820_RESERVED) )
- continue;
- AMD_IOMMU_ERROR("IVMD: page at %lx couldn't be reserved\n",
- addr);
- return -EIO;
- }
-
- /*
- * Types which aren't RAM are considered good enough.
- * Note that a page being partially RESERVED, ACPI or UNUSABLE will
- * force Xen into assuming the whole page as having that type in
- * practice.
- */
- if ( type & (RAM_TYPE_RESERVED | RAM_TYPE_ACPI |
- RAM_TYPE_UNUSABLE) )
- continue;
-
- AMD_IOMMU_ERROR("IVMD: page at %lx can't be converted\n", addr);
- return -EIO;
- }
- }
+ if ( !iommu_unity_region_ok(maddr_to_mfn(base),
+ maddr_to_mfn(limit + PAGE_SIZE)) )
+ return -EIO;
if ( ivmd_block->header.flags & ACPI_IVMD_EXCLUSION_RANGE )
exclusion = true;
@@ -792,6 +792,52 @@ static int __init cf_check adjust_irq_affinities(void)
}
__initcall(adjust_irq_affinities);
+bool __init iommu_unity_region_ok(mfn_t start, mfn_t end)
+{
+ mfn_t addr;
+
+ if ( e820_all_mapped(mfn_to_maddr(start), mfn_to_maddr(end),
+ E820_RESERVED) )
+ return true;
+
+ printk(XENLOG_WARNING "IOMMU: [%#" PRI_mfn " ,%#" PRI_mfn
+ ") is not (entirely) in reserved memory\n",
+ mfn_x(start), mfn_x(end));
+
+ for ( addr = start; !mfn_eq(addr, end); mfn_add(addr, 1) )
+ {
+ unsigned int type = page_get_ram_type(addr);
+
+ if ( type == RAM_TYPE_UNKNOWN )
+ {
+ if ( e820_add_range(mfn_to_maddr(addr),
+ mfn_to_maddr(addr) + PAGE_SIZE, E820_RESERVED) )
+ continue;
+ printk(XENLOG_WARNING
+ "IOMMU: page at %#" PRI_mfn " couldn't be reserved\n",
+ mfn_x(addr));
+ return false;
+ }
+
+ /*
+ * Types which aren't RAM are considered good enough.
+ * Note that a page being partially RESERVED, ACPI or UNUSABLE will
+ * force Xen into assuming the whole page as having that type in
+ * practice.
+ */
+ if ( type & (RAM_TYPE_RESERVED | RAM_TYPE_ACPI |
+ RAM_TYPE_UNUSABLE) )
+ continue;
+
+ printk(XENLOG_WARNING
+ "IOMMU: page at %#" PRI_mfn " can't be converted\n",
+ mfn_x(addr));
+ return false;
+ }
+
+ return true;
+}
+
/*
* Local variables:
* mode: C
IVMD and RMRR ranges are functionally equivalent, and as so could use the same validity checker. Move the IVMD to x86 common IOMMU code and adjust the function to take a pair of [start, end) mfn parameters. So far only the AMD-Vi side is adjusted to use the newly introduced helper, the VT-d side will be adjusted in a further change. No functional change intended. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> --- xen/arch/x86/include/asm/iommu.h | 3 ++ xen/drivers/passthrough/amd/iommu_acpi.c | 38 ++------------------ xen/drivers/passthrough/x86/iommu.c | 46 ++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 35 deletions(-)