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>
65 lines
1.4 KiB
C
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;
|
|
}
|