From a6800cefb1d6bd23366ecfff35bd12112e5d6b6e Mon Sep 17 00:00:00 2001 From: Dong Wang Date: Sun, 18 Jul 2021 12:41:29 +0800 Subject: [PATCH] x86/cache: fix issues in arch dcache flush function Correct the wrong operand of clflush instruction. The old operand points to a location inside stack and doesn't work. The new one works well by taking linux kernel code as reference. End address instead of size should get round up Add Kconfig option to disable the usage of mfence intruction for SoC that has clfulsh but no mfence supported. Signed-off-by: Dong Wang --- arch/x86/core/Kconfig.ia32 | 8 ++++++++ arch/x86/core/cache.c | 14 +++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/arch/x86/core/Kconfig.ia32 b/arch/x86/core/Kconfig.ia32 index b408ec43068..8532535f2d6 100644 --- a/arch/x86/core/Kconfig.ia32 +++ b/arch/x86/core/Kconfig.ia32 @@ -170,4 +170,12 @@ config X86_USE_THREAD_LOCAL_STORAGE help Internal config to enable thread local storage. +config X86_MFENCE_INSTRUCTION_SUPPORTED + bool "X86 MFENCE instruction supported" + default y + depends on CACHE_MANAGEMENT + help + Set n to disable the use of MFENCE instruction in arch_dcache_flush() + for X86 CPUs have CLFLUSH instruction but no MFENCE + endif # !X86_64 diff --git a/arch/x86/core/cache.c b/arch/x86/core/cache.c index ca049504288..0d6322247cb 100644 --- a/arch/x86/core/cache.c +++ b/arch/x86/core/cache.c @@ -33,20 +33,24 @@ static void arch_dcache_flush(void *start_addr, size_t size) { size_t line_size = sys_cache_data_line_size_get(); uintptr_t start = (uintptr_t)start_addr; - uintptr_t end; + uintptr_t end = start + size; if (line_size == 0U) { return; } - size = ROUND_UP(size, line_size); - end = start + size; + end = ROUND_UP(end, line_size); for (; start < end; start += line_size) { - __asm__ volatile("clflush %0;\n\t" : : "m"(start)); + __asm__ volatile("clflush %0;\n\t" : + "+m"(*(volatile char *)start)); } - __asm__ volatile("mfence;\n\t"); +#if defined(CONFIG_X86_MFENCE_INSTRUCTION_SUPPORTED) + __asm__ volatile("mfence;\n\t":::"memory"); +#else + __asm__ volatile("lock; addl $0,-4(%%esp);\n\t":::"memory", "cc"); +#endif } int arch_dcache_range(void *addr, size_t size, int op)