diff options
Diffstat (limited to 'src/soc/amd/stoneyridge')
-rw-r--r-- | src/soc/amd/stoneyridge/Kconfig | 3 | ||||
-rw-r--r-- | src/soc/amd/stoneyridge/ramtop.c | 34 |
2 files changed, 36 insertions, 1 deletions
diff --git a/src/soc/amd/stoneyridge/Kconfig b/src/soc/amd/stoneyridge/Kconfig index 148ca3ff04..79755239d8 100644 --- a/src/soc/amd/stoneyridge/Kconfig +++ b/src/soc/amd/stoneyridge/Kconfig @@ -55,6 +55,7 @@ config CPU_SPECIFIC_OPTIONS select BOOTBLOCK_CONSOLE select BOOT_DEVICE_SUPPORTS_WRITES if BOOT_DEVICE_SPI_FLASH select RELOCATABLE_MODULES + select CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM select PARALLEL_MP select PARALLEL_MP_AP_WORK select HAVE_SMI_HANDLER @@ -295,7 +296,7 @@ config SMM_TSEG_SIZE config SMM_RESERVED_SIZE hex - default 0x100000 + default 0x140000 config ACPI_CPU_STRING string diff --git a/src/soc/amd/stoneyridge/ramtop.c b/src/soc/amd/stoneyridge/ramtop.c index e676465ce7..24386edba3 100644 --- a/src/soc/amd/stoneyridge/ramtop.c +++ b/src/soc/amd/stoneyridge/ramtop.c @@ -20,7 +20,9 @@ #include <arch/io.h> #include <cpu/x86/msr.h> #include <cpu/amd/mtrr.h> +#include <cpu/amd/amdfam15.h> #include <cbmem.h> +#include <stage_cache.h> #include <soc/northbridge.h> #include <soc/southbridge.h> @@ -56,12 +58,43 @@ static size_t smm_region_size(void) return CONFIG_SMM_TSEG_SIZE; } +void stage_cache_external_region(void **base, size_t *size) +{ + if (smm_subregion(SMM_SUBREGION_CACHE, base, size)) { + printk(BIOS_ERR, "ERROR: No cache SMM subregion.\n"); + *base = NULL; + *size = 0; + } +} + void smm_region_info(void **start, size_t *size) { *start = (void *)smm_region_start(); *size = smm_region_size(); } +/* + * For data stored in TSEG, ensure TValid is clear so R/W access can reach + * the DRAM when not in SMM. + */ +static void clear_tvalid(void) +{ + msr_t hwcr = rdmsr(HWCR_MSR); + msr_t mask = rdmsr(MSR_SMM_MASK); + int tvalid = !!(mask.lo & SMM_TSEG_VALID); + + if (hwcr.lo & SMM_LOCK) { + if (!tvalid) /* not valid but locked means still accessible */ + return; + + printk(BIOS_ERR, "Error: can't clear TValid, already locked\n"); + return; + } + + mask.lo &= ~SMM_TSEG_VALID; + wrmsr(MSR_SMM_MASK, mask); +} + int smm_subregion(int sub, void **start, size_t *size) { uintptr_t sub_base; @@ -82,6 +115,7 @@ int smm_subregion(int sub, void **start, size_t *size) /* External cache is in the middle of TSEG. */ sub_base += sub_size - cache_size; sub_size = cache_size; + clear_tvalid(); break; default: return -1; |