Commit 1f44aab7 authored by Vasant Hegde's avatar Vasant Hegde Committed by Joerg Roedel
Browse files

iommu/amd: Use maximum PPR log buffer size when SNP is enabled on Family 0x19

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: default avatarVasant Hegde <vasant.hegde@amd.com>
Tested-by: default avatarDheeraj Kumar Srivastava <dheerajkumar.srivastava@amd.com>
Signed-off-by: default avatarJoerg Roedel <joerg.roedel@amd.com>
parent 58c0ac61
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+6 −5
Original line number Diff line number Diff line
@@ -267,11 +267,12 @@
#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 */
+12 −1
Original line number Diff line number Diff line
@@ -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;

+5 −3
Original line number Diff line number Diff line
@@ -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 */