zephyr/arch/x86/core/cache.c
Dong Wang a6800cefb1 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 <dong.d.wang@intel.com>
2021-07-23 16:22:07 -04:00

65 lines
1.4 KiB
C

/*
* Copyright (c) 2013-2014 Wind River Systems, Inc.
* Copyright (c) 2021 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Cache manipulation
*
* This module contains functions for manipulation caches.
*/
#include <kernel.h>
#include <arch/cpu.h>
#include <sys/util.h>
#include <toolchain.h>
#include <cache.h>
#include <stdbool.h>
/**
* @brief Flush cache lines to main memory
*
* No alignment is required for either <virt> or <size>, but since
* sys_cache_flush() iterates on the cache lines, a cache line alignment for
* both is optimal.
*
* The cache line size is specified via the d-cache-line-size DTS property.
*
* @return N/A
*/
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 = start + size;
if (line_size == 0U) {
return;
}
end = ROUND_UP(end, line_size);
for (; start < end; start += line_size) {
__asm__ volatile("clflush %0;\n\t" :
"+m"(*(volatile char *)start));
}
#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)
{
if (op & K_CACHE_WB) {
arch_dcache_flush(addr, size);
return 0;
}
return -ENOTSUP;
}