Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/85829?usp=email )
Change subject: soc/intel/xeon_sp: Add fix for DPR silicon bug ......................................................................
soc/intel/xeon_sp: Add fix for DPR silicon bug
On first batch of Intel Xeon-SP 10nm CPU the DPR register is affected by a silicon bug, where the TOP bits read as 0, which isn't possible according to the EDS. Currently the code also assumes that it's never zero and calculates the DPR size using the assigned address. By using 0 as TOP address it overflows and breaks boot due to an overly large MMIO window.
On previous CPUs and newer CPUs the assumption is still correct and the DPR TOP bits never read as 0.
Add a check for the silicon bug and use TSEG base like it's already done on snowridge, which is also a 10nm Xeon CPU affected by the same bug.
Fixes negative size being calculated for DPR.
Change-Id: Ia090013721053ae85001a3e7d47ad2b1ec9a3203 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/soc/intel/snowridge/systemagent.c M src/soc/intel/xeon_sp/uncore.c 2 files changed, 21 insertions(+), 2 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/29/85829/1
diff --git a/src/soc/intel/snowridge/systemagent.c b/src/soc/intel/snowridge/systemagent.c index 2663dc0..f35ba9e 100644 --- a/src/soc/intel/snowridge/systemagent.c +++ b/src/soc/intel/snowridge/systemagent.c @@ -38,7 +38,11 @@ { union dpr_register dpr = { .raw = pci_read_config32(dev, DPR) }; *size = dpr.size * MiB; - /* DPR base is read as 0s so it is calculated based on the assumption that DPR is below TSEG. */ + /* + * Silicon bug: + * DPR top is read as 0s so it is calculated based on the assumption + * that DPR is below TSEG. + */ *base = sa_server_get_tseg_base() - *size; return true; } diff --git a/src/soc/intel/xeon_sp/uncore.c b/src/soc/intel/xeon_sp/uncore.c index 85e45db..d4e4b08 100644 --- a/src/soc/intel/xeon_sp/uncore.c +++ b/src/soc/intel/xeon_sp/uncore.c @@ -5,6 +5,7 @@ #include <console/console.h> #include <cpu/x86/lapic_def.h> #include <cpu/x86/mtrr.h> +#include <cpu/x86/smm.h> #include <device/pci.h> #include <device/pci_ids.h> #include <intelblocks/msr.h> @@ -144,13 +145,27 @@ { const uintptr_t cbmem_top_mb = ALIGN_UP(cbmem_top(), MiB) / MiB; union dpr_register dpr = { .raw = pci_read_config32(dev, VTD_LTDPR) }; + uintptr_t base; + size_t size;
/* The DPR lock bit has to be set sufficiently early. It looks like * it cannot be set anymore after FSP-S. */ dpr.lock = 1; dpr.epm = 1; - dpr.size = dpr.top - cbmem_top_mb; + + /* + * Silicon bug on 1st gen 10nm Xeon-SP: + * DPR top is read as 0s so it is calculated based on the assumption + * that DPR is below TSEG. + */ + if (!dpr.top) { + smm_region(&base, &size); + + dpr.size = base - cbmem_top_mb; + } else { + dpr.size = dpr.top - cbmem_top_mb; + } pci_write_config32(dev, VTD_LTDPR, dpr.raw); }