include: Implement API's for cache flush and cache invalidate

arch: arc: core: Add Cache Implementation function & prototype for arc

Signed-off-by: Aastha Grover <aastha.grover@intel.com>
This commit is contained in:
Aastha Grover 2020-04-28 13:14:54 -07:00 committed by Andrew Boie
commit 97ecad69f0
5 changed files with 144 additions and 76 deletions

View file

@ -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 <start_addr> or <size>, 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 <virt> 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 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);

View file

@ -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);

View file

@ -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_ */

View file

@ -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
}

View file

@ -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 */