Michael Niewöhner has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/35902 )
Change subject: soc/intel/apl,skl,cnl,icl: implement a PRMRR size selection algorithm ......................................................................
soc/intel/apl,skl,cnl,icl: implement a PRMRR size selection algorithm
This change reworks the PRMRR size selection and implements an algorithm for PRMRR size selection which will be needed in a follow-up change to make the maximum PRMRR size user-selectable via Kconfig.
Currently, PRMRR size must be set in the devicetree, while the value has to be verified to be working with the CPU. The selection of a valid PRMRR size is now done by an algorithm that tries to find a supported PRMRR size within a possibly specified limit by looking at MSR_PRMRR_VALID_CONFIG and trying to select the highest possible value at runtime withing a possibly specified limit.
That (hopefully) prevents setting a wrong, unsupported static value.
The limit can be set via the devicetree setting PrmrrSize, that will be replaced by Kconfig in the follow-up change. When a too strict limit was set, coreboot will die, printing an error message.
Further, this change does some restructuring of memmap.c (for the listed platforms) to a) integrate the previously described functionality and b) to align common functionality for later move to the common section.
Before this reunification can happen, some more details about PRMRR, its influence on SGX-enabled and -disabled systems have to be investigated and understood. This is being worked on.
Signed-off-by: Michael Niewöhner foss@mniewoehner.de Change-Id: I8a773362f8d09c8a33ff0dfac357edc6ea3564e0 --- M src/soc/intel/apollolake/chip.h M src/soc/intel/apollolake/memmap.c M src/soc/intel/apollolake/romstage.c M src/soc/intel/cannonlake/chip.h M src/soc/intel/cannonlake/memmap.c M src/soc/intel/cannonlake/romstage/fsp_params.c M src/soc/intel/common/block/cpu/cpulib.c M src/soc/intel/common/block/include/intelblocks/cpulib.h M src/soc/intel/common/block/include/intelblocks/msr.h M src/soc/intel/icelake/chip.h M src/soc/intel/icelake/memmap.c M src/soc/intel/icelake/romstage/fsp_params.c M src/soc/intel/skylake/chip.h M src/soc/intel/skylake/memmap.c M src/soc/intel/skylake/romstage/romstage_fsp20.c 15 files changed, 128 insertions(+), 62 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/02/35902/1
diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h index 85cfff9..0e2a5f5 100644 --- a/src/soc/intel/apollolake/chip.h +++ b/src/soc/intel/apollolake/chip.h @@ -198,4 +198,6 @@
typedef struct soc_intel_apollolake_config config_t;
+size_t get_prmrr_size(void); + #endif /* _SOC_APOLLOLAKE_CHIP_H_ */ diff --git a/src/soc/intel/apollolake/memmap.c b/src/soc/intel/apollolake/memmap.c index 77711eb..9885724 100644 --- a/src/soc/intel/apollolake/memmap.c +++ b/src/soc/intel/apollolake/memmap.c @@ -22,11 +22,24 @@ #include <cpu/x86/mtrr.h> #include <cpu/x86/smm.h> #include <device/pci.h> +#include <intelblocks/cpulib.h> #include <soc/systemagent.h> #include <soc/pci_devs.h>
#include "chip.h"
+/* Calculate PRMRR size based on user input PRMRR size and config */ +size_t get_prmrr_size(void) +{ + size_t prmrr_size = 0; + const config_t *config = config_of_soc(); + + if (config->sgx_enable) + prmrr_size = get_max_prmrr_size(config->PrmrrSize); + + return prmrr_size; +} + void *cbmem_top(void) { const config_t *config; @@ -35,11 +48,12 @@ if (!CONFIG(SOC_INTEL_GLK)) return tolum;
- config = config_of_soc(); - - /* FSP allocates 2x PRMRR Size Memory for alignment */ - if (config->sgx_enable) - tolum -= config->PrmrrSize * 2; + /* + * FSP-M allocates 2x PRMRR Size Memory for alignment + * As long as the PRMRR base is not set and locked via MSRs, this region is just + * regular ram. Currently, PRMRR only gets enabled when SGX is enabled. + */ + tolum -= get_prmrr_size() * 2;
return tolum; } diff --git a/src/soc/intel/apollolake/romstage.c b/src/soc/intel/apollolake/romstage.c index 8418919..258f4ff 100644 --- a/src/soc/intel/apollolake/romstage.c +++ b/src/soc/intel/apollolake/romstage.c @@ -269,9 +269,7 @@ /* Only for GLK */ FSP_M_CONFIG *m_cfg = &mupd->FspmConfig;
- const config_t *config = config_of_soc(); - - m_cfg->PrmrrSize = config->PrmrrSize; + m_cfg->PrmrrSize = get_prmrr_size();
/* * CpuMemoryTest in FSP tests 0 to 1M of the RAM after MRC init. diff --git a/src/soc/intel/cannonlake/chip.h b/src/soc/intel/cannonlake/chip.h index b937699..933f859 100644 --- a/src/soc/intel/cannonlake/chip.h +++ b/src/soc/intel/cannonlake/chip.h @@ -433,4 +433,6 @@
typedef struct soc_intel_cannonlake_config config_t;
+size_t get_prmrr_size(const struct soc_intel_cannonlake_config *config); + #endif diff --git a/src/soc/intel/cannonlake/memmap.c b/src/soc/intel/cannonlake/memmap.c index f3286cc..a4c9738 100644 --- a/src/soc/intel/cannonlake/memmap.c +++ b/src/soc/intel/cannonlake/memmap.c @@ -23,6 +23,7 @@ #include <device/device.h> #include <device/pci.h> #include <fsp/util.h> +#include <intelblocks/cpulib.h> #include <intelblocks/ebda.h> #include <intelblocks/systemagent.h> #include <soc/pci_devs.h> @@ -48,30 +49,32 @@ return imr_size; }
+/* Calculate PRMRR size based on user input PRMRR size and config */ +size_t get_prmrr_size(const struct soc_intel_cannonlake_config *config) +{ + size_t prmrr_size = 0; + + /* Allocate at least 1 MiB PRMRR memory for C6DRAM */ + if (config->enable_c6dram) + prmrr_size = 1*MiB; + + if (config->sgx_enable) + prmrr_size = get_max_prmrr_size(config->PrmrrSize); + + return prmrr_size; +} + /* Calculate PRMRR size based on user input PRMRR size and alignment */ -static size_t get_prmrr_size(uintptr_t dram_base, +static size_t get_aligned_prmrr_size(uintptr_t dram_base, const struct soc_intel_cannonlake_config *config) { uintptr_t prmrr_base = dram_base; size_t prmrr_size;
- prmrr_size = config->PrmrrSize; + prmrr_size = get_prmrr_size(config);
- /* Allocate PRMRR memory for C6DRAM */ - if (!prmrr_size) { - if (config->enable_c6dram) - prmrr_size = 1*MiB; - else - return 0; - } - - /* - * PRMRR Sizes that are > 1MB and < 32MB are - * not supported and will fail out. - */ - if ((prmrr_size > 1*MiB) && (prmrr_size < 32*MiB)) - die("PRMRR Sizes that are > 1MB and < 32MB are not" - "supported!\n"); + if (!prmrr_size) + return 0;
prmrr_base -= prmrr_size; if (prmrr_size >= 32*MiB) @@ -125,7 +128,7 @@ config = config_of(dev);
/* Get PRMRR size */ - reserve_mem_base -= get_prmrr_size(reserve_mem_base, config); + reserve_mem_base -= get_aligned_prmrr_size(reserve_mem_base, config);
/* Get Tracehub size */ reserve_mem_base -= get_imr_size(); diff --git a/src/soc/intel/cannonlake/romstage/fsp_params.c b/src/soc/intel/cannonlake/romstage/fsp_params.c index 3ba997d..4031382 100644 --- a/src/soc/intel/cannonlake/romstage/fsp_params.c +++ b/src/soc/intel/cannonlake/romstage/fsp_params.c @@ -48,8 +48,10 @@ mask |= (1 << i); } m_cfg->PcieRpEnableMask = mask; - m_cfg->PrmrrSize = config->PrmrrSize; + m_cfg->EnableC6Dram = config->enable_c6dram; + m_cfg->PrmrrSize = get_prmrr_size(config); + #if CONFIG(SOC_INTEL_COMETLAKE) m_cfg->SerialIoUartDebugControllerNumber = CONFIG_UART_FOR_CONSOLE; #else diff --git a/src/soc/intel/common/block/cpu/cpulib.c b/src/soc/intel/common/block/cpu/cpulib.c index 75e7112..008770e 100644 --- a/src/soc/intel/common/block/cpu/cpulib.c +++ b/src/soc/intel/common/block/cpu/cpulib.c @@ -320,3 +320,29 @@ (msr_t) {.lo = 0xffffffff, .hi = 0xffffffff}); } } + +size_t get_max_prmrr_size(size_t limit) +{ + msr_t msr; + int i; + size_t valid; + + msr = rdmsr(MSR_PRMRR_VALID_CONFIG); + + /* find the greatest valid value within a possibly specified limit */ + for (i = 8; i >= 0; i--) { + valid = msr.lo & (1<<i); + if ((!limit && valid) || (limit && valid <= limit)) + break; + else if (i == 0) + valid = 0; + } + + /* die if we could not find a valid size within the limit */ + if (!valid) + die("Unsupported PRMRR size limit!") + + printk(BIOS_DEBUG, "PRMRR size set to %li MiB\n", valid/MiB); + + return valid; +} diff --git a/src/soc/intel/common/block/include/intelblocks/cpulib.h b/src/soc/intel/common/block/include/intelblocks/cpulib.h index 8630fd1..a99e532 100644 --- a/src/soc/intel/common/block/include/intelblocks/cpulib.h +++ b/src/soc/intel/common/block/include/intelblocks/cpulib.h @@ -18,6 +18,7 @@ #define SOC_INTEL_COMMON_BLOCK_CPULIB_H
#include <stdint.h> +#include <stddef.h>
/* * Set PERF_CTL MSR (0x199) P_Req with @@ -161,4 +162,7 @@ /* Configure Machine Check Architecture support */ void mca_configure(void);
+/* Get the maximum valid PRMRR size with respect to the specified limits */ +size_t get_max_prmrr_size(size_t limit); + #endif /* SOC_INTEL_COMMON_BLOCK_CPULIB_H */ diff --git a/src/soc/intel/common/block/include/intelblocks/msr.h b/src/soc/intel/common/block/include/intelblocks/msr.h index 6fdf26e..fbc43e7 100644 --- a/src/soc/intel/common/block/include/intelblocks/msr.h +++ b/src/soc/intel/common/block/include/intelblocks/msr.h @@ -64,6 +64,7 @@ #define MSR_PRMRR_PHYS_MASK 0x1f5 #define PRMRR_PHYS_MASK_LOCK (1 << 10) #define PRMRR_PHYS_MASK_VALID (1 << 11) +#define MSR_PRMRR_VALID_CONFIG 0x1fb #define MSR_POWER_CTL 0x1fc #define POWER_CTL_C1E_MASK (1 << 1) #define MSR_EVICT_CTL 0x2e0 diff --git a/src/soc/intel/icelake/chip.h b/src/soc/intel/icelake/chip.h index fc9341c..47c49ec 100644 --- a/src/soc/intel/icelake/chip.h +++ b/src/soc/intel/icelake/chip.h @@ -281,4 +281,6 @@
typedef struct soc_intel_icelake_config config_t;
+size_t get_prmrr_size(const struct soc_intel_icelake_config *config); + #endif diff --git a/src/soc/intel/icelake/memmap.c b/src/soc/intel/icelake/memmap.c index 20c4e6f..b1e7d53 100644 --- a/src/soc/intel/icelake/memmap.c +++ b/src/soc/intel/icelake/memmap.c @@ -22,6 +22,7 @@ #include <device/device.h> #include <device/pci.h> #include <fsp/util.h> +#include <intelblocks/cpulib.h> #include <intelblocks/ebda.h> #include <intelblocks/systemagent.h> #include <soc/pci_devs.h> @@ -46,30 +47,32 @@ return imr_size; }
+/* Calculate PRMRR size based on user input PRMRR size and config */ +size_t get_prmrr_size(const struct soc_intel_icelake_config *config) +{ + size_t prmrr_size = 0; + + /* Allocate at least 1 MiB PRMRR memory for C6DRAM */ + if (config->enable_c6dram) + prmrr_size = 1*MiB; + + if (config->sgx_enable) + prmrr_size = get_max_prmrr_size(config->PrmrrSize); + + return prmrr_size; +} + /* Calculate PRMRR size based on user input PRMRR size and alignment */ -static size_t get_prmrr_size(uintptr_t dram_base, +static size_t get_aligned_prmrr_size(uintptr_t dram_base, const struct soc_intel_icelake_config *config) { uintptr_t prmrr_base = dram_base; size_t prmrr_size;
- prmrr_size = config->PrmrrSize; + prmrr_size = get_prmrr_size(config);
- /* Allocate PRMRR memory for C6DRAM */ - if (!prmrr_size) { - if (config->enable_c6dram) - prmrr_size = 1*MiB; - else - return 0; - } - - /* - * PRMRR Sizes that are > 1MB and < 32MB are - * not supported and will fail out. - */ - if ((prmrr_size > 1*MiB) && (prmrr_size < 32*MiB)) - die("PRMRR Sizes that are > 1MB and < 32MB are not" - "supported!\n"); + if (!prmrr_size) + return 0;
prmrr_base -= prmrr_size; if (prmrr_size >= 32*MiB) @@ -123,7 +126,7 @@ config = config_of(dev);
/* Get PRMRR size */ - reserve_mem_base -= get_prmrr_size(reserve_mem_base, config); + reserve_mem_base -= get_aligned_prmrr_size(reserve_mem_base, config);
/* Get Tracehub size */ reserve_mem_base -= get_imr_size(); diff --git a/src/soc/intel/icelake/romstage/fsp_params.c b/src/soc/intel/icelake/romstage/fsp_params.c index 5bf3421..d504d9e 100644 --- a/src/soc/intel/icelake/romstage/fsp_params.c +++ b/src/soc/intel/icelake/romstage/fsp_params.c @@ -60,8 +60,10 @@ mask |= (1 << i); } m_cfg->PcieRpEnableMask = mask; - m_cfg->PrmrrSize = config->PrmrrSize; + m_cfg->EnableC6Dram = config->enable_c6dram; + m_cfg->PrmrrSize = get_prmrr_size(config); + /* Disable BIOS Guard */ m_cfg->BiosGuard = 0; /* Disable Cpu Ratio Override temporary. */ diff --git a/src/soc/intel/skylake/chip.h b/src/soc/intel/skylake/chip.h index 944315b..fb92a5d 100644 --- a/src/soc/intel/skylake/chip.h +++ b/src/soc/intel/skylake/chip.h @@ -602,4 +602,6 @@
typedef struct soc_intel_skylake_config config_t;
+size_t get_prmrr_size(void); + #endif diff --git a/src/soc/intel/skylake/memmap.c b/src/soc/intel/skylake/memmap.c index 29f2517..0073cf7 100644 --- a/src/soc/intel/skylake/memmap.c +++ b/src/soc/intel/skylake/memmap.c @@ -23,6 +23,7 @@ #include <cpu/x86/smm.h> #include <device/device.h> #include <device/pci.h> +#include <intelblocks/cpulib.h> #include <intelblocks/ebda.h> #include <intelblocks/systemagent.h> #include <soc/msr.h> @@ -79,29 +80,32 @@ return tracehub_size; }
+/* Calculate PRMRR size based on user input PRMRR size and config */ +size_t get_prmrr_size(void) +{ + size_t prmrr_size = 0; + const config_t *config = config_of_soc(); + + if (CONFIG(PLATFORM_USES_FSP1_1)) + prmrr_size = 1*MiB; + + else if (config->sgx_enable) + prmrr_size = get_max_prmrr_size(config->PrmrrSize); + + return prmrr_size; +} + /* Calculate PRMRR size based on user input PRMRR size and alignment */ -static size_t get_prmrr_size(uintptr_t dram_base, - const struct soc_intel_skylake_config *config) +static size_t get_aligned_prmrr_size(uintptr_t dram_base) { uintptr_t prmrr_base = dram_base; size_t prmrr_size;
- if (CONFIG(PLATFORM_USES_FSP1_1)) - prmrr_size = 1*MiB; - else - prmrr_size = config->PrmrrSize; + prmrr_size = get_prmrr_size();
if (!prmrr_size) return 0;
- /* - * PRMRR Sizes that are > 1MB and < 32MB are - * not supported and will fail out. - */ - if ((prmrr_size > 1*MiB) && (prmrr_size < 32*MiB)) - die("PRMRR Sizes that are > 1MB and < 32MB are not" - "supported!\n"); - prmrr_base -= prmrr_size; if (prmrr_size >= 32*MiB) prmrr_base = ALIGN_DOWN(prmrr_base, 128*MiB); @@ -153,7 +157,7 @@ config = config_of(dev);
/* Get PRMRR size */ - reserve_mem_base -= get_prmrr_size(reserve_mem_base, config); + reserve_mem_base -= get_aligned_prmrr_size(reserve_mem_base);
/* Get Tracehub size */ reserve_mem_base -= get_tracehub_size(reserve_mem_base, config); diff --git a/src/soc/intel/skylake/romstage/romstage_fsp20.c b/src/soc/intel/skylake/romstage/romstage_fsp20.c index af89441..c7028b9 100644 --- a/src/soc/intel/skylake/romstage/romstage_fsp20.c +++ b/src/soc/intel/skylake/romstage/romstage_fsp20.c @@ -237,7 +237,8 @@ m_cfg->CmdTriStateDis = config->CmdTriStateDis; m_cfg->DdrFreqLimit = config->DdrFreqLimit; m_cfg->VmxEnable = CONFIG(ENABLE_VMX); - m_cfg->PrmrrSize = config->PrmrrSize; + m_cfg->PrmrrSize = get_prmrr_size(); + for (i = 0; i < ARRAY_SIZE(config->PcieRpEnable); i++) { if (config->PcieRpEnable[i]) mask |= (1<<i);