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

Reply via email to