blob: 11524e65db3439c5d379b585f5dcd60a97246bfa [file] [log] [blame]
Arthur Heymans3134a812019-11-25 12:20:01 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <arch/cpu.h>
4#include <cbmem.h>
5#include <console/console.h>
6#include <cpu/x86/cache.h>
7#include <program_loading.h>
8#include <types.h>
9
10bool clflush_supported(void)
11{
12 return (cpuid_edx(1) >> CPUID_FEATURE_CLFLUSH_BIT) & 1;
13}
14
Jeremy Compostella4a2ce022023-05-22 17:38:10 -070015void clflush_region(const uintptr_t start, const size_t size)
Arthur Heymans3134a812019-11-25 12:20:01 +010016{
17 uintptr_t addr;
18 const size_t cl_size = ((cpuid_ebx(1) >> 8) & 0xff) * 8;
19
Arthur Heymans3134a812019-11-25 12:20:01 +010020 printk(BIOS_SPEW, "CLFLUSH [0x%lx, 0x%lx]\n", start, start + size);
21
22 for (addr = ALIGN_DOWN(start, cl_size); addr < start + size; addr += cl_size)
23 clflush((void *)addr);
24}
25
26/*
27 * For each segment of a program loaded this function is called
28 * to invalidate caches for the addresses of the loaded segment
29 */
30void arch_segment_loaded(uintptr_t start, size_t size, int flags)
31{
32 /* INVD is only called in postcar stage so we only need
33 to make sure that our code hits dram during romstage. */
34 if (!ENV_CACHE_AS_RAM)
35 return;
Arthur Heymansa2bc2542021-05-29 08:10:49 +020036 if (!ENV_RAMINIT)
Arthur Heymans3134a812019-11-25 12:20:01 +010037 return;
38 if (!CONFIG(POSTCAR_STAGE))
39 return;
40 if (!CONFIG(X86_CLFLUSH_CAR))
41 return;
42 if (flags != SEG_FINAL)
43 return;
44
45 /*
46 * The assumption is made here that DRAM is only ready after cbmem
47 * is initialized, to avoid flushing when loading earlier things (e.g. FSP, ...)
48 */
49 if (!cbmem_online())
50 return;
51
Jeremy Compostella4a2ce022023-05-22 17:38:10 -070052 if (clflush_supported())
53 clflush_region(start, size);
54 else
55 printk(BIOS_DEBUG, "Not flushing cache to RAM, CLFLUSH not supported\n");
Arthur Heymans3134a812019-11-25 12:20:01 +010056}