]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iommu/amd: Use maximum PPR log buffer size when SNP is enabled on Family 0x19
authorVasant Hegde <vasant.hegde@amd.com>
Mon, 20 Apr 2026 08:42:04 +0000 (08:42 +0000)
committerJoerg Roedel <joerg.roedel@amd.com>
Mon, 27 Apr 2026 11:49:36 +0000 (13:49 +0200)
Due to CVE-2023-20585, the PPR log buffer must use the maximum supported
size (512K) on Genoa (Family 0x19, model >= 0x10) systems when SNP is
enabled, to mitigate a potential security vulnerability. Note that Family
0x19 models below 0x10 (Milan) do not support PPR when SNP is enabled.
Hence the PPR log size increase is only applied for model >= 0x10.
All other systems continue to use the default PPR log buffer size (8K).

Apply the errata fix by making the following changes:

- Introduce global new variable (amd_iommu_pprlog_size) to have PPR log buffer
  size. Adjust variable size for Genoa family.

- Extend 'amd_iommu_apply_erratum_snp()' to also set the PPR log buffer
  size to maximum for Family 0x19 model >= 0x10 when SNP is enabled.

- Rename PPR_* macros to make it more readable.

Link: https://www.amd.com/en/resources/product-security/bulletin/amd-sb-3016.html
Cc: Borislav Petkov <bp@alien8.de>
Cc: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Cc: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Tested-by: Dheeraj Kumar Srivastava <dheerajkumar.srivastava@amd.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
drivers/iommu/amd/amd_iommu.h
drivers/iommu/amd/amd_iommu_types.h
drivers/iommu/amd/init.c
drivers/iommu/amd/ppr.c

index f1c486dcf0f3848a58233108cc7c6ce1222372a1..834d8fabfba3873ce00b96547f9eb06bbf435080 100644 (file)
@@ -12,6 +12,7 @@
 #include "amd_iommu_types.h"
 
 extern int amd_iommu_evtlog_size;
+extern int amd_iommu_pprlog_size;
 
 irqreturn_t amd_iommu_int_thread(int irq, void *data);
 irqreturn_t amd_iommu_int_thread_evtlog(int irq, void *data);
index c3430c09bc5c97eb7751fd439c29573afb60310f..f9f7180878930341e92a42b318cb61de6d569637 100644 (file)
 #define EVTLOG_LEN_MASK_MAX    (0xFULL << EVTLOG_SIZE_SHIFT)
 
 /* Constants for PPR Log handling */
-#define PPR_LOG_ENTRIES                512
-#define PPR_LOG_SIZE_SHIFT     56
-#define PPR_LOG_SIZE_512       (0x9ULL << PPR_LOG_SIZE_SHIFT)
-#define PPR_ENTRY_SIZE         16
-#define PPR_LOG_SIZE           (PPR_ENTRY_SIZE * PPR_LOG_ENTRIES)
+#define PPRLOG_ENTRY_SIZE      0x10
+#define PPRLOG_SIZE_SHIFT      56
+#define PPRLOG_SIZE_DEF                SZ_8K   /* 512 entries */
+#define PPRLOG_LEN_MASK_DEF    (0x9ULL << PPRLOG_SIZE_SHIFT)
+#define PPRLOG_SIZE_MAX                SZ_512K /* 32K entries */
+#define PPRLOG_LEN_MASK_MAX    (0xFULL << PPRLOG_SIZE_SHIFT)
 
 /* PAGE_SERVICE_REQUEST PPR Log Buffer Entry flags */
 #define PPR_FLAG_EXEC          0x002   /* Execute permission requested */
index d8dc5c6db29d69e3d8d66df0210906e2e3bcac49..3bdb380d23e9a93c9ab9399afe7872645964b2bd 100644 (file)
@@ -133,6 +133,7 @@ struct ivhd_entry {
 } __attribute__((packed));
 
 int amd_iommu_evtlog_size = EVTLOG_SIZE_DEF;
+int amd_iommu_pprlog_size = PPRLOG_SIZE_DEF;
 
 /*
  * An AMD IOMMU memory definition structure. It defines things like exclusion
@@ -3423,6 +3424,16 @@ static void amd_iommu_apply_erratum_snp(void)
        amd_iommu_evtlog_size = EVTLOG_SIZE_MAX;
        pr_info("Applying erratum: Increase Event log size to 0x%x\n",
                amd_iommu_evtlog_size);
+
+       /*
+        * Set PPR log buffer size to max.
+        * (Family 0x19, model < 0x10 doesn't support PPR when SNP is enabled).
+        */
+       if (boot_cpu_data.x86_model >= 0x10) {
+               amd_iommu_pprlog_size = PPRLOG_SIZE_MAX;
+               pr_info("Applying erratum: Increase PPR log size to 0x%x\n",
+                       amd_iommu_pprlog_size);
+       }
 #endif
 }
 
@@ -4083,7 +4094,7 @@ int amd_iommu_snp_disable(void)
                if (ret)
                        return ret;
 
-               ret = iommu_make_shared(iommu->ppr_log, PPR_LOG_SIZE);
+               ret = iommu_make_shared(iommu->ppr_log, amd_iommu_pprlog_size);
                if (ret)
                        return ret;
 
index e6767c057d01fa1ca780a0aec2f2c1a568cd2a76..1f8d2823bea42c492cf21c531f167357bfdea19c 100644 (file)
@@ -20,7 +20,7 @@
 int __init amd_iommu_alloc_ppr_log(struct amd_iommu *iommu)
 {
        iommu->ppr_log = iommu_alloc_4k_pages(iommu, GFP_KERNEL | __GFP_ZERO,
-                                             PPR_LOG_SIZE);
+                                             amd_iommu_pprlog_size);
        return iommu->ppr_log ? 0 : -ENOMEM;
 }
 
@@ -33,7 +33,9 @@ void amd_iommu_enable_ppr_log(struct amd_iommu *iommu)
 
        iommu_feature_enable(iommu, CONTROL_PPR_EN);
 
-       entry = iommu_virt_to_phys(iommu->ppr_log) | PPR_LOG_SIZE_512;
+       entry = iommu_virt_to_phys(iommu->ppr_log);
+       entry |= (amd_iommu_pprlog_size == PPRLOG_SIZE_DEF) ?
+                       PPRLOG_LEN_MASK_DEF : PPRLOG_LEN_MASK_MAX;
 
        memcpy_toio(iommu->mmio_base + MMIO_PPR_LOG_OFFSET,
                    &entry, sizeof(entry));
@@ -201,7 +203,7 @@ void amd_iommu_poll_ppr_log(struct amd_iommu *iommu)
                        raw[0] = raw[1] = 0UL;
 
                /* Update head pointer of hardware ring-buffer */
-               head = (head + PPR_ENTRY_SIZE) % PPR_LOG_SIZE;
+               head = (head + PPRLOG_ENTRY_SIZE) % amd_iommu_pprlog_size;
                writel(head, iommu->mmio_base + MMIO_PPR_HEAD_OFFSET);
 
                /* Handle PPR entry */