From 3134a8152590f6d93232f6e56ab08fd87ebe1a0d Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Mon, 25 Nov 2019 12:20:01 +0100 Subject: cpu/x86/cache: CLFLUSH programs to memory before running When cbmem is initialized in romstage and postcar placed in the stage cache + cbmem where it is run, the assumption is made that these are all in UC memory such that calling INVD in postcar is OK. For performance reasons (e.g. postcar decompression) it is desirable to cache cbmem and the stage cache during romstage. Another reason is that AGESA sets up MTRR during romstage to cache all dram, which is currently worked around by using additional MTRR's to make that UC. TESTED on asus/p5ql-em, up/squared on both regular and S3 resume bootpath. Sometimes there are minimal performance improvements when cbmem is cached (few ms). Change-Id: I7ff2a57aee620908b71829457ea0f5a0c410ec5b Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/37196 Reviewed-by: Lean Sheng Tan Reviewed-by: Kapil Porwal Tested-by: build bot (Jenkins) --- src/cpu/x86/Kconfig | 5 ++++ src/cpu/x86/Makefile.inc | 1 + src/cpu/x86/cache/Makefile.inc | 2 ++ src/cpu/x86/cache/cache.c | 58 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 src/cpu/x86/cache/Makefile.inc create mode 100644 src/cpu/x86/cache/cache.c (limited to 'src/cpu/x86') diff --git a/src/cpu/x86/Kconfig b/src/cpu/x86/Kconfig index 50766cdac1..c85eace851 100644 --- a/src/cpu/x86/Kconfig +++ b/src/cpu/x86/Kconfig @@ -126,6 +126,11 @@ config SETUP_XIP_CACHE non-eviction mode and therefore need to be careful to avoid eviction. +config X86_CLFLUSH_CAR + bool + help + Select this on platforms that allow CLFLUSH while operating in CAR. + config HAVE_SMI_HANDLER bool default n diff --git a/src/cpu/x86/Makefile.inc b/src/cpu/x86/Makefile.inc index dffc2b1cb9..3ef3a90313 100644 --- a/src/cpu/x86/Makefile.inc +++ b/src/cpu/x86/Makefile.inc @@ -5,6 +5,7 @@ subdirs-$(CONFIG_HAVE_SMI_HANDLER) += smm subdirs-$(CONFIG_UDELAY_TSC) += tsc # Use ARCH_BOOTBLOCK_X86_64 as a proxy for knowing if 64bit is going to be used subdirs-$(CONFIG_ARCH_BOOTBLOCK_X86_64) += 64bit +subdirs-y += cache subdirs-$(CONFIG_PARALLEL_MP) += name ramstage-$(CONFIG_PARALLEL_MP) += mp_init.c diff --git a/src/cpu/x86/cache/Makefile.inc b/src/cpu/x86/cache/Makefile.inc new file mode 100644 index 0000000000..759488ec7e --- /dev/null +++ b/src/cpu/x86/cache/Makefile.inc @@ -0,0 +1,2 @@ +romstage-y += cache.c +ramstage-y += cache.c diff --git a/src/cpu/x86/cache/cache.c b/src/cpu/x86/cache/cache.c new file mode 100644 index 0000000000..d02d6d4427 --- /dev/null +++ b/src/cpu/x86/cache/cache.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include + +bool clflush_supported(void) +{ + return (cpuid_edx(1) >> CPUID_FEATURE_CLFLUSH_BIT) & 1; +} + +static void clflush_region(const uintptr_t start, const size_t size) +{ + uintptr_t addr; + const size_t cl_size = ((cpuid_ebx(1) >> 8) & 0xff) * 8; + + if (!clflush_supported()) { + printk(BIOS_DEBUG, "Not flushing cache to RAM, CLFLUSH not supported\n"); + return; + } + + printk(BIOS_SPEW, "CLFLUSH [0x%lx, 0x%lx]\n", start, start + size); + + for (addr = ALIGN_DOWN(start, cl_size); addr < start + size; addr += cl_size) + clflush((void *)addr); +} + +/* + * For each segment of a program loaded this function is called + * to invalidate caches for the addresses of the loaded segment + */ +void arch_segment_loaded(uintptr_t start, size_t size, int flags) +{ + /* INVD is only called in postcar stage so we only need + to make sure that our code hits dram during romstage. */ + if (!ENV_CACHE_AS_RAM) + return; + if (!ENV_ROMSTAGE) + return; + if (!CONFIG(POSTCAR_STAGE)) + return; + if (!CONFIG(X86_CLFLUSH_CAR)) + return; + if (flags != SEG_FINAL) + return; + + /* + * The assumption is made here that DRAM is only ready after cbmem + * is initialized, to avoid flushing when loading earlier things (e.g. FSP, ...) + */ + if (!cbmem_online()) + return; + + clflush_region(start, size); +} -- cgit v1.2.3