diff options
Diffstat (limited to 'src/cpu/x86')
-rw-r--r-- | src/cpu/x86/Kconfig | 5 | ||||
-rw-r--r-- | src/cpu/x86/Makefile.inc | 1 | ||||
-rw-r--r-- | src/cpu/x86/cache/Makefile.inc | 2 | ||||
-rw-r--r-- | src/cpu/x86/cache/cache.c | 58 |
4 files changed, 66 insertions, 0 deletions
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 <arch/cpu.h> +#include <cbmem.h> +#include <console/console.h> +#include <cpu/x86/cache.h> +#include <program_loading.h> +#include <types.h> + +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); +} |