iommu/amd: Add kernel parameters to limit V1 page-sizes
authorJoerg Roedel <jroedel@suse.de>
Thu, 5 Sep 2024 07:22:40 +0000 (09:22 +0200)
committerJoerg Roedel <jroedel@suse.de>
Tue, 10 Sep 2024 09:48:57 +0000 (11:48 +0200)
Add two new kernel command line parameters to limit the page-sizes
used for v1 page-tables:

nohugepages     - Limits page-sizes to 4KiB

v2_pgsizes_only - Limits page-sizes to 4Kib/2Mib/1GiB; The
                  same as the sizes used with v2 page-tables

This is needed for multiple scenarios. When assigning devices to
SEV-SNP guests the IOMMU page-sizes need to match the sizes in the RMP
table, otherwise the device will not be able to access all shared
memory.

Also, some ATS devices do not work properly with arbitrary IO
page-sizes as supported by AMD-Vi, so limiting the sizes used by the
driver is a suitable workaround.

All-in-all, these parameters are only workarounds until the IOMMU core
and related APIs gather the ability to negotiate the page-sizes in a
better way.

Signed-off-by: Joerg Roedel <jroedel@suse.de>
Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>
Link: https://lore.kernel.org/r/20240905072240.253313-1-joro@8bytes.org
Documentation/admin-guide/kernel-parameters.txt
drivers/iommu/amd/amd_iommu.h
drivers/iommu/amd/amd_iommu_types.h
drivers/iommu/amd/init.c
drivers/iommu/amd/io_pgtable.c

index 09126bb8cc9ffb140280c56895754a0e2c602f25..6d6630aec46cff3fbe3b89555828f2b0dd444ca9 100644 (file)
                                          allowed anymore to lift isolation
                                          requirements as needed. This option
                                          does not override iommu=pt
-                       force_enable - Force enable the IOMMU on platforms known
-                                      to be buggy with IOMMU enabled. Use this
-                                      option with care.
-                       pgtbl_v1     - Use v1 page table for DMA-API (Default).
-                       pgtbl_v2     - Use v2 page table for DMA-API.
-                       irtcachedis  - Disable Interrupt Remapping Table (IRT) caching.
+                       force_enable    - Force enable the IOMMU on platforms known
+                                         to be buggy with IOMMU enabled. Use this
+                                         option with care.
+                       pgtbl_v1        - Use v1 page table for DMA-API (Default).
+                       pgtbl_v2        - Use v2 page table for DMA-API.
+                       irtcachedis     - Disable Interrupt Remapping Table (IRT) caching.
+                       nohugepages     - Limit page-sizes used for v1 page-tables
+                                         to 4 KiB.
+                       v2_pgsizes_only - Limit page-sizes used for v1 page-tables
+                                         to 4KiB/2Mib/1GiB.
+
 
        amd_iommu_dump= [HW,X86-64]
                        Enable AMD IOMMU driver option to dump the ACPI table
index 29e6e71f7f9a0b33afe9f8e624a268bdc4850441..6386fa4556d9b8060544264d98b6af30c8d4de46 100644 (file)
@@ -43,6 +43,7 @@ int amd_iommu_enable_faulting(unsigned int cpu);
 extern int amd_iommu_guest_ir;
 extern enum io_pgtable_fmt amd_iommu_pgtable;
 extern int amd_iommu_gpt_level;
+extern unsigned long amd_iommu_pgsize_bitmap;
 
 /* Protection domain ops */
 struct protection_domain *protection_domain_alloc(unsigned int type, int nid);
index 35aa4ff020f506e8c750b830a3276330d0031439..601fb4ee69009ee2c3fc394161043b00d2b6a613 100644 (file)
  * Page sizes >= the 52 bit max physical address of the CPU are not supported.
  */
 #define AMD_IOMMU_PGSIZES      (GENMASK_ULL(51, 12) ^ SZ_512G)
+
+/* Special mode where page-sizes are limited to 4 KiB */
+#define AMD_IOMMU_PGSIZES_4K   (PAGE_SIZE)
+
 /* 4K, 2MB, 1G page sizes are supported */
 #define AMD_IOMMU_PGSIZES_V2   (PAGE_SIZE | (1ULL << 21) | (1ULL << 30))
 
index 6b15ce09e78ddc72567c3d0490659d942724d9f4..43131c3a21726f3360de6ba843ed30048343cbbf 100644 (file)
@@ -192,6 +192,8 @@ bool amdr_ivrs_remap_support __read_mostly;
 
 bool amd_iommu_force_isolation __read_mostly;
 
+unsigned long amd_iommu_pgsize_bitmap __ro_after_init = AMD_IOMMU_PGSIZES;
+
 /*
  * AMD IOMMU allows up to 2^16 different protection domains. This is a bitmap
  * to know which ones are already in use.
@@ -3492,6 +3494,12 @@ static int __init parse_amd_iommu_options(char *str)
                        amd_iommu_pgtable = AMD_IOMMU_V2;
                } else if (strncmp(str, "irtcachedis", 11) == 0) {
                        amd_iommu_irtcachedis = true;
+               } else if (strncmp(str, "nohugepages", 11) == 0) {
+                       pr_info("Restricting V1 page-sizes to 4KiB");
+                       amd_iommu_pgsize_bitmap = AMD_IOMMU_PGSIZES_4K;
+               } else if (strncmp(str, "v2_pgsizes_only", 15) == 0) {
+                       pr_info("Restricting V1 page-sizes to 4KiB/2MiB/1GiB");
+                       amd_iommu_pgsize_bitmap = AMD_IOMMU_PGSIZES_V2;
                } else {
                        pr_notice("Unknown option - '%s'\n", str);
                }
index 14f62c420e4a9c9e034635121eaf4abd3ff35071..804b788f3f167d45175e2858cbaaa4ebc63c898f 100644 (file)
@@ -548,7 +548,7 @@ static struct io_pgtable *v1_alloc_pgtable(struct io_pgtable_cfg *cfg, void *coo
                return NULL;
        pgtable->mode = PAGE_MODE_3_LEVEL;
 
-       cfg->pgsize_bitmap  = AMD_IOMMU_PGSIZES;
+       cfg->pgsize_bitmap  = amd_iommu_pgsize_bitmap;
        cfg->ias            = IOMMU_IN_ADDR_BIT_SIZE;
        cfg->oas            = IOMMU_OUT_ADDR_BIT_SIZE;