diff --git a/arch/arc/core/cache.c b/arch/arc/core/cache.c index a59886dc1c1..2196fe4d7cd 100644 --- a/arch/arc/core/cache.c +++ b/arch/arc/core/cache.c @@ -67,34 +67,19 @@ static void dcache_enable(void) dcache_dc_ctrl(DC_CTRL_DC_ENABLE); } - -/** - * - * @brief Flush multiple d-cache lines to memory - * - * No alignment is required for either or , but since - * dcache_flush_mlines() iterates on the d-cache lines, a cache line - * alignment for both is optimal. - * - * The d-cache line size is specified either via the CONFIG_CACHE_LINE_SIZE - * kconfig option or it is detected at runtime. - * - * @param start_addr the pointer to start the multi-line flush - * @param size the number of bytes that are to be flushed - * - * @return N/A - */ -static void dcache_flush_mlines(uint32_t start_addr, uint32_t size) +void arch_dcache_flush(void *start_addr_ptr, size_t size) { - uint32_t end_addr; + uintptr_t start_addr = (uintptr_t)start_addr_ptr; + uintptr_t end_addr; unsigned int key; if (!dcache_available() || (size == 0U)) { return; } - end_addr = start_addr + size - 1; - start_addr &= (uint32_t)(~(DCACHE_LINE_SIZE - 1)); + end_addr = start_addr + size; + + start_addr = ROUND_DOWN(start_addr, DCACHE_LINE_SIZE); key = arch_irq_lock(); /* --enter critical section-- */ @@ -111,35 +96,35 @@ static void dcache_flush_mlines(uint32_t start_addr, uint32_t size) } } while (1); start_addr += DCACHE_LINE_SIZE; - } while (start_addr <= end_addr); + } while (start_addr < end_addr); arch_irq_unlock(key); /* --exit critical section-- */ } - -/** - * - * @brief Flush d-cache lines to main memory - * - * No alignment is required for either or , but since - * sys_cache_flush() iterates on the d-cache lines, a d-cache line alignment for - * both is optimal. - * - * The d-cache line size is specified either via the CONFIG_CACHE_LINE_SIZE - * kconfig option or it is detected at runtime. - * - * @param start_addr the pointer to start the multi-line flush - * @param size the number of bytes that are to be flushed - * - * @return N/A - */ - -void sys_cache_flush(vaddr_t start_addr, size_t size) +void arch_dcache_invd(void *start_addr_ptr, size_t size) { - dcache_flush_mlines((uint32_t)start_addr, (uint32_t)size); -} + uintptr_t start_addr = (uintptr_t)start_addr_ptr; + uintptr_t end_addr; + unsigned int key; + if (!dcache_available() || (size == 0U)) { + return; + } + end_addr = start_addr + size; + start_addr = ROUND_DOWN(start_addr, DCACHE_LINE_SIZE); + + key = arch_irq_lock(); /* -enter critical section- */ + + do { + z_arc_v2_aux_reg_write(_ARC_V2_DC_IVDL, start_addr); + __asm__ volatile("nop_s"); + __asm__ volatile("nop_s"); + __asm__ volatile("nop_s"); + start_addr += DCACHE_LINE_SIZE; + } while (start_addr < end_addr); + irq_unlock(key); /* -exit critical section- */ +} #if defined(CONFIG_CACHE_LINE_SIZE_DETECT) size_t sys_cache_line_size; @@ -155,6 +140,15 @@ static void init_dcache_line_size(void) } #endif +size_t arch_cache_line_size_get(void) +{ +#if defined(CONFIG_CACHE_LINE_SIZE_DETECT) + return sys_cache_line_size; +#else + return 0; +#endif +} + static int init_dcache(struct device *unused) { ARG_UNUSED(unused); diff --git a/arch/x86/core/ia32/cache.c b/arch/x86/core/ia32/cache.c index b04290d8a13..414fcd49d4c 100644 --- a/arch/x86/core/ia32/cache.c +++ b/arch/x86/core/ia32/cache.c @@ -97,6 +97,15 @@ static void init_cache_line_size(void) #define init_cache_line_size() do { } while ((0)) #endif +size_t arch_cache_line_size_get(void) +{ +#if defined(CONFIG_CACHE_LINE_SIZE_DETECT) + return sys_cache_line_size; +#else + return 0; +#endif +} + static int init_cache(struct device *unused) { ARG_UNUSED(unused); diff --git a/include/arch/common/addr_types.h b/include/arch/common/addr_types.h index 898fd058fb0..1abc5824258 100644 --- a/include/arch/common/addr_types.h +++ b/include/arch/common/addr_types.h @@ -10,8 +10,8 @@ #define ZEPHYR_INCLUDE_ARCH_X86_ADDR_TYPES_H_ #ifndef _ASMLANGUAGE -typedef unsigned int paddr_t; -typedef unsigned int vaddr_t; +typedef uintptr_t paddr_t; +typedef void *vaddr_t; #endif #endif /* ZEPHYR_INCLUDE_ARCH_X86_ADDR_TYPES_H_ */ diff --git a/include/cache.h b/include/cache.h index 5158730d8f2..65686440ae8 100644 --- a/include/cache.h +++ b/include/cache.h @@ -13,45 +13,75 @@ extern "C" { #endif -#define _sys_cache_flush_sig(x) void (x)(vaddr_t virt, size_t size) +void arch_dcache_flush(void *addr, size_t size); +void arch_dcache_invd(void *addr, size_t size); -#if defined(CONFIG_CACHE_FLUSHING) - -#if defined(CONFIG_ARCH_CACHE_FLUSH_DETECT) - typedef _sys_cache_flush_sig(_sys_cache_flush_t); - extern _sys_cache_flush_t *sys_cache_flush; -#else - extern _sys_cache_flush_sig(sys_cache_flush); -#endif - -#else - -/* - * Provide NOP APIs for systems that do not have caches. +/** * - * An example is the Cortex-M chips. However, the functions are provided so - * that code that need to manipulate caches can be written in an - * architecture-agnostic manner. The functions do nothing. The cache line size - * value is always 0. + * @brief Flush d-cache lines to main memory + * + * No alignment is required for either addr or size, but since + * sys_cache_flush() iterates on the d-cache lines, a d-cache line alignment for + * both is optimal. + * + * The d-cache line size is specified either via the CONFIG_CACHE_LINE_SIZE + * kconfig option or it is detected at runtime. + * + * @param addr the pointer to start the multi-line flush + * @param size the number of bytes that are to be flushed + * + * @return N/A */ - -static inline _sys_cache_flush_sig(sys_cache_flush) +static inline void sys_cache_flush(void *addr, size_t size) { - ARG_UNUSED(virt); - ARG_UNUSED(size); - - /* do nothing */ + if (IS_ENABLED(CONFIG_CACHE_FLUSHING)) { + arch_dcache_flush(addr, size); + } } -#endif /* CACHE_FLUSHING */ +/** + * + * @brief Invalidate d-cache lines + * + * No alignment is required for either addr or size, but since + * sys_cache_invd() iterates on the d-cache lines, a d-cache line alignment for + * both is optimal. + * + * The d-cache line size is specified either via the CONFIG_CACHE_LINE_SIZE + * kconfig option or it is detected at runtime. + * + * @param addr the pointer to start address + * @param size the number of bytes that are to be invalidated + * + * @return N/A + */ +static inline void sys_cache_invd(void *addr, size_t size) +{ + if (IS_ENABLED(CONFIG_CACHE_FLUSHING)) { + arch_dcache_invd(addr, size); + } +} -#if defined(CONFIG_CACHE_LINE_SIZE_DETECT) - extern size_t sys_cache_line_size; -#elif defined(CONFIG_CACHE_LINE_SIZE) - #define sys_cache_line_size CONFIG_CACHE_LINE_SIZE +/** + * + * @brief Get the d-cache line size. + * + * The API is provided to get the cache line size. + * + * @return size of the cache line or 0 if the cache is not enabled. + */ +static inline size_t sys_cache_line_size_get(void) +{ +#ifdef CONFIG_CACHE_FLUSHING +#ifdef CONFIG_CACHE_LINE_SIZE + return CONFIG_CACHE_LINE_SIZE; #else - #define sys_cache_line_size 0 -#endif + return arch_cache_line_size_get(); +#endif /* CONFIG_CACHE_LINE_SIZE */ +#else + return 0; +#endif /* CONFIG_CACHE_FLUSHING */ +} #ifdef __cplusplus } diff --git a/include/sys/arch_interface.h b/include/sys/arch_interface.h index 9ceeef73b79..3aa8fc1d7e9 100644 --- a/include/sys/arch_interface.h +++ b/include/sys/arch_interface.h @@ -675,6 +675,41 @@ extern uint64_t arch_timing_value_swap_temp; /** @} */ +/** + * @defgroup arch_cache Architecture-specific cache functions + * @ingroup arch-interface + * @{ + */ + +#ifdef CONFIG_CACHE_FLUSHING +/** + * + * @brief Flush d-cache lines to main memory + * + * @see sys_cache_flush + */ +void arch_dcache_flush(void *addr, size_t size); + +/** + * + * @brief Invalidate d-cache lines + * + * @see sys_cache_invd + */ +void arch_dcache_invd(void *addr, size_t size); + +#ifndef CONFIG_CACHE_LINE_SIZE +/** + * + * @brief Get d-cache line size + * + * @see sys_cache_line_size_get + */ +size_t arch_cache_line_size_get(void); +#endif +#endif +/** @} */ + #ifdef __cplusplus } #endif /* __cplusplus */