The IVRS ACPI table specifies maximum address sizes for i/o virtual addresses that can be handled by the IOMMUs in the system. Parse that data from the IVRS header so that it can be considered in limiting the IO aperture (in subsequent patches).
Based on prior work by Marius Hillenbrand. Link: https://www.amd.com/system/files/TechDocs/48882_IOMMU_3.05_PUB.pdf Signed-off-by: Sebastian Ott <seb...@amazon.de> Cc: Benjamin Serebrin <sereb...@amazon.com> Cc: Filippo Sironi <sir...@amazon.de> CR: https://code.amazon.com/reviews/CR-26408321 --- drivers/iommu/amd/amd_iommu_types.h | 3 +++ drivers/iommu/amd/init.c | 26 ++++++++++++++++++++++++++ drivers/iommu/amd/iommu.c | 1 + 3 files changed, 30 insertions(+) diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h index 30a5d412255a..0946638306d6 100644 --- a/drivers/iommu/amd/amd_iommu_types.h +++ b/drivers/iommu/amd/amd_iommu_types.h @@ -754,6 +754,9 @@ extern bool amd_iommu_force_isolation; /* Max levels of glxval supported */ extern int amd_iommu_max_glx_val; +/* Maximum virtual address supported */ +extern u64 amd_iommu_max_va; + /* * This function flushes all internal caches of * the IOMMU used by this driver. diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 6ebd4825e320..ab9d226b4215 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -11,6 +11,7 @@ #include <linux/pci.h> #include <linux/acpi.h> #include <linux/list.h> +#include <linux/bitfield.h> #include <linux/bitmap.h> #include <linux/slab.h> #include <linux/syscore_ops.h> @@ -39,6 +40,7 @@ * definitions for the ACPI scanning code */ #define IVRS_HEADER_LENGTH 48 +#define IVRS_HEADER_IVINFO_OFFSET 36 #define ACPI_IVHD_TYPE_MAX_SUPPORTED 0x40 #define ACPI_IVMD_TYPE_ALL 0x20 @@ -2490,6 +2492,27 @@ static void __init free_dma_resources(void) free_unity_maps(); } +static void __init get_ivrs_ivinfo(struct acpi_table_header *ivrs) +{ + u32 *ivinfo = (u32 *)((u8 *)ivrs + IVRS_HEADER_IVINFO_OFFSET); + u8 va_size = FIELD_GET(GENMASK(21, 15), *ivinfo); + u8 valid_va_sizes[] = {32, 40, 48, 64}; + int i; + + for (i = 0; i < ARRAY_SIZE(valid_va_sizes); i++) { + if (va_size == valid_va_sizes[i]) { + amd_iommu_max_va = DMA_BIT_MASK(va_size); + break; + } + } + + if (!amd_iommu_max_va) { + pr_warn("Invalid virtual address size %u in IVRS header, use most restrictive %u\n", + va_size, valid_va_sizes[0]); + amd_iommu_max_va = DMA_BIT_MASK(valid_va_sizes[0]); + } +} + /* * This is the hardware init function for AMD IOMMU in the system. * This function is called either from amd_iommu_init or from the interrupt @@ -2544,6 +2567,9 @@ static int __init early_amd_iommu_init(void) if (ret) goto out; + get_ivrs_ivinfo(ivrs_base); + DUMP_printk("IVRS vasize=%llx\n", amd_iommu_max_va); + amd_iommu_target_ivhd_type = get_highest_supported_ivhd_type(ivrs_base); DUMP_printk("Using IVHD type %#x\n", amd_iommu_target_ivhd_type); diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 74cca1757172..acab35220d98 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -88,6 +88,7 @@ const struct iommu_ops amd_iommu_ops; static ATOMIC_NOTIFIER_HEAD(ppr_notifier); int amd_iommu_max_glx_val = -1; +u64 amd_iommu_max_va; /* * general struct to manage commands send to an IOMMU -- 2.17.1 Amazon Development Center Germany GmbH Krausenstr. 38 10117 Berlin Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B Sitz: Berlin Ust-ID: DE 289 237 879 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu