/* 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; } 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; 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; if (clflush_supported()) clflush_region(start, size); else printk(BIOS_DEBUG, "Not flushing cache to RAM, CLFLUSH not supported\n"); }