cache: Rework cache API

The cache operations must be quick, optimized and possibly inlined. The
current API is clunky, functions are not inlined and passing parameters
around that are basically always known at compile time.

In this patch we rework the cache functions to allow us to get rid of
useless parameters and make inlining easier.

In particular this changeset is doing three things:

1. `CONFIG_HAS_ARCH_CACHE` is now `CONFIG_ARCH_CACHE` and
   `CONFIG_HAS_EXTERNAL_CACHE` is now `CONFIG_EXTERNAL_CACHE`

2. The cache API has been reworked.

3. Comments are added.

Signed-off-by: Carlo Caione <ccaione@baylibre.com>
This commit is contained in:
Carlo Caione 2022-10-05 10:08:29 +02:00 committed by Anas Nashif
commit 189cd1f4a2
10 changed files with 720 additions and 197 deletions

View file

@ -841,8 +841,8 @@ config CACHE_MANAGEMENT
bool "Cache management features" bool "Cache management features"
depends on DCACHE || ICACHE depends on DCACHE || ICACHE
help help
This links in the cache management functions (for d-cache and i-cache This option enables the cache management functions backed by arch or
where possible). driver code.
config DCACHE_LINE_SIZE_DETECT config DCACHE_LINE_SIZE_DETECT
bool "Detect d-cache line size at runtime" bool "Detect d-cache line size at runtime"
@ -892,17 +892,17 @@ config ICACHE_LINE_SIZE
choice CACHE_TYPE choice CACHE_TYPE
prompt "Cache type" prompt "Cache type"
depends on CACHE_MANAGEMENT depends on CACHE_MANAGEMENT
default HAS_ARCH_CACHE default ARCH_CACHE
config HAS_ARCH_CACHE config ARCH_CACHE
bool "Integrated cache controller" bool "Integrated cache controller"
help help
"Integrated on-core cache controller" Integrated on-core cache controller
config HAS_EXTERNAL_CACHE config EXTERNAL_CACHE
bool "External cache controller" bool "External cache controller"
help help
"External cache controller or cache management system" External cache controller
endchoice endchoice

View file

@ -19,7 +19,7 @@ zephyr_library_sources(
vector_table.c vector_table.c
) )
zephyr_library_sources_ifdef(CONFIG_CACHE_MANAGEMENT cache.c) zephyr_library_sources_ifdef(CONFIG_ARCH_CACHE cache.c)
zephyr_library_sources_ifdef(CONFIG_ARC_FIRQ fast_irq.S) zephyr_library_sources_ifdef(CONFIG_ARC_FIRQ fast_irq.S)
zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c) zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c)

View file

@ -21,9 +21,7 @@ zephyr_library_sources_ifdef(CONFIG_SW_VECTOR_RELAY irq_relay.S)
zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE ../common/tls.c) zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE ../common/tls.c)
zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S) zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S)
if(CONFIG_HAS_ARCH_CACHE) zephyr_library_sources_ifdef(CONFIG_ARCH_CACHE cache.c)
zephyr_library_sources_ifdef(CONFIG_CACHE_MANAGEMENT cache.c)
endif()
add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M cortex_m) add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M cortex_m)
add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M_HAS_CMSE cortex_m/cmse) add_subdirectory_ifdef(CONFIG_CPU_CORTEX_M_HAS_CMSE cortex_m/cmse)

View file

@ -36,7 +36,7 @@ zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c)
zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c) zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c)
zephyr_library_sources_ifdef(CONFIG_HAS_ARM_SMCCC smccc-call.S) zephyr_library_sources_ifdef(CONFIG_HAS_ARM_SMCCC smccc-call.S)
zephyr_library_sources_ifdef(CONFIG_AARCH64_IMAGE_HEADER header.S) zephyr_library_sources_ifdef(CONFIG_AARCH64_IMAGE_HEADER header.S)
zephyr_library_sources_ifdef(CONFIG_CACHE_MANAGEMENT cache.c) zephyr_library_sources_ifdef(CONFIG_ARCH_CACHE cache.c)
zephyr_library_sources_ifdef(CONFIG_SEMIHOST semihost.c) zephyr_library_sources_ifdef(CONFIG_SEMIHOST semihost.c)
if ((CONFIG_MP_MAX_NUM_CPUS GREATER 1) OR (CONFIG_SMP)) if ((CONFIG_MP_MAX_NUM_CPUS GREATER 1) OR (CONFIG_SMP))
zephyr_library_sources(smp.c) zephyr_library_sources(smp.c)

View file

@ -18,7 +18,7 @@ zephyr_library_sources_ifdef(CONFIG_X86_EFI efi.c)
zephyr_library_sources_ifdef(CONFIG_ACPI acpi.c) zephyr_library_sources_ifdef(CONFIG_ACPI acpi.c)
zephyr_library_sources_ifdef(CONFIG_X86_MMU x86_mmu.c) zephyr_library_sources_ifdef(CONFIG_X86_MMU x86_mmu.c)
zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.c)
zephyr_library_sources_ifdef(CONFIG_CACHE_MANAGEMENT cache.c) zephyr_library_sources_ifdef(CONFIG_ARCH_CACHE cache.c)
zephyr_library_sources_ifdef(CONFIG_X86_VERY_EARLY_CONSOLE early_serial.c) zephyr_library_sources_ifdef(CONFIG_X86_VERY_EARLY_CONSOLE early_serial.c)

View file

@ -7,30 +7,26 @@
#include <zephyr/cache.h> #include <zephyr/cache.h>
#include <zephyr/syscall_handler.h> #include <zephyr/syscall_handler.h>
static inline int z_vrfy_sys_cache_data_all(int op) static inline int z_vrfy_sys_cache_data_flush_range(void *addr, size_t size)
{
return z_impl_sys_cache_data_all(op);
}
#include <syscalls/sys_cache_data_all_mrsh.c>
static inline int z_vrfy_sys_cache_data_range(void *addr, size_t size, int op)
{ {
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(addr, size)); Z_OOPS(Z_SYSCALL_MEMORY_WRITE(addr, size));
return z_impl_sys_cache_data_range(addr, size, op); return z_impl_sys_cache_data_flush_range(addr, size);
} }
#include <syscalls/sys_cache_data_range_mrsh.c> #include <syscalls/sys_cache_data_flush_range_mrsh.c>
static inline int z_vrfy_sys_cache_instr_all(int op) static inline int z_vrfy_sys_cache_data_invd_range(void *addr, size_t size)
{
return z_impl_sys_cache_instr_all(op);
}
#include <syscalls/sys_cache_instr_all_mrsh.c>
static inline int z_vrfy_sys_cache_instr_range(void *addr, size_t size, int op)
{ {
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(addr, size)); Z_OOPS(Z_SYSCALL_MEMORY_WRITE(addr, size));
return z_impl_sys_cache_instr_range(addr, size, op); return z_impl_sys_cache_data_invd_range(addr, size);
} }
#include <syscalls/sys_cache_instr_range_mrsh.c> #include <syscalls/sys_cache_data_invd_range_mrsh.c>
static inline int z_vrfy_sys_cache_data_flush_and_invd_range(void *addr, size_t size)
{
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(addr, size));
return z_impl_sys_cache_data_flush_and_invd_range(addr, size);
}
#include <syscalls/sys_cache_data_flush_and_invd_range_mrsh.c>

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2015 Wind River Systems, Inc. * Copyright (c) 2015 Wind River Systems, Inc.
* Copyright (c) 2022 Carlo Caione <ccaione@baylibre.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -7,74 +8,87 @@
#ifndef ZEPHYR_INCLUDE_CACHE_H_ #ifndef ZEPHYR_INCLUDE_CACHE_H_
#define ZEPHYR_INCLUDE_CACHE_H_ #define ZEPHYR_INCLUDE_CACHE_H_
/**
* @file
* @brief cache API interface
*/
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <zephyr/kernel_structs.h> #include <zephyr/arch/cpu.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/** #if defined(CONFIG_EXTERNAL_CACHE)
* Common operations for the caches
* /*
* WB means write-back and intends to transfer dirty cache lines to memory in a * External cache API driver interface mirrored in
* copy-back cache policy. May be a no-op in write-back cache policy. * include/zephyr/drivers/cache.h
*
* INVD means invalidate and will mark cache lines as not valid. A future
* access to the associated address is guaranteed to generate a memory fetch.
*/ */
#define K_CACHE_WB BIT(0)
#define K_CACHE_INVD BIT(1)
#define K_CACHE_WB_INVD (K_CACHE_WB | K_CACHE_INVD)
#if defined(CONFIG_HAS_EXTERNAL_CACHE)
/* Driver interface mirrored in include/drivers/cache.h */
#if defined(CONFIG_DCACHE) #if defined(CONFIG_DCACHE)
/* Enable d-cache */
extern void cache_data_enable(void); extern void cache_data_enable(void);
/* Disable d-cache */
extern void cache_data_disable(void); extern void cache_data_disable(void);
/* Write-back / Invalidate / Write-back + Invalidate all d-cache */ extern int cache_data_flush_all(void);
extern int cache_data_all(int op); extern int cache_data_invd_all(void);
extern int cache_data_flush_and_invd_all(void);
/* Write-back / Invalidate / Write-back + Invalidate d-cache lines */ extern int cache_data_flush_range(void *addr, size_t size);
extern int cache_data_range(void *addr, size_t size, int op); extern int cache_data_invd_range(void *addr, size_t size);
extern int cache_data_flush_and_invd_range(void *addr, size_t size);
#if defined(CONFIG_DCACHE_LINE_SIZE_DETECT)
extern size_t cache_data_line_size_get(void);
#endif /* CONFIG_DCACHE_LINE_SIZE_DETECT */
#endif /* CONFIG_DCACHE */ #endif /* CONFIG_DCACHE */
#if defined(CONFIG_ICACHE) #if defined(CONFIG_ICACHE)
/* Enable i-cache */
extern void cache_instr_enable(void); extern void cache_instr_enable(void);
/* Disable i-cache */
extern void cache_instr_disable(void); extern void cache_instr_disable(void);
/* Write-back / Invalidate / Write-back + Invalidate all i-cache */ extern int cache_instr_flush_all(void);
extern int cache_instr_all(int op); extern int cache_instr_invd_all(void);
extern int cache_instr_flush_and_invd_all(void);
/* Write-back / Invalidate / Write-back + Invalidate i-cache lines */ extern int cache_instr_flush_range(void *addr, size_t size);
extern int cache_instr_range(void *addr, size_t size, int op); extern int cache_instr_invd_range(void *addr, size_t size);
extern int cache_instr_flush_and_invd_range(void *addr, size_t size);
#if defined(CONFIG_ICACHE_LINE_SIZE_DETECT)
extern size_t cache_instr_line_size_get(void);
#endif /* CONFIG_ICACHE_LINE_SIZE_DETECT */
#endif /* CONFIG_ICACHE */ #endif /* CONFIG_ICACHE */
#else #else /* CONFIG_ARCH_CACHE */
/* Hooks into arch code */ /*
* Arch cache API interface mirrored in
* include/zephyr/sys/arch_interface.h
*/
#if defined(CONFIG_DCACHE) #if defined(CONFIG_DCACHE)
#define cache_data_enable arch_dcache_enable #define cache_data_enable arch_dcache_enable
#define cache_data_disable arch_dcache_disable #define cache_data_disable arch_dcache_disable
#define cache_data_all(op) arch_dcache_all(op)
#define cache_data_range(addr, size, op) arch_dcache_range(addr, size, op) #define cache_data_flush_all arch_dcache_flush_all
#define cache_data_invd_all arch_dcache_invd_all
#define cache_data_flush_and_invd_all arch_dcache_flush_and_invd_all
#define cache_data_flush_range(addr, size) arch_dcache_flush_range(addr, size)
#define cache_data_invd_range(addr, size) arch_dcache_invd_range(addr, size)
#define cache_data_flush_and_invd_range(addr, size) \
arch_dcache_flush_and_invd_range(addr, size)
#if defined(CONFIG_DCACHE_LINE_SIZE_DETECT)
#define cache_data_line_size_get arch_dcache_line_size_get #define cache_data_line_size_get arch_dcache_line_size_get
#endif /* CONFIG_DCACHE_LINE_SIZE_DETECT */
#endif /* CONFIG_DCACHE */ #endif /* CONFIG_DCACHE */
@ -82,78 +96,335 @@ extern int cache_instr_range(void *addr, size_t size, int op);
#define cache_instr_enable arch_icache_enable #define cache_instr_enable arch_icache_enable
#define cache_instr_disable arch_icache_disable #define cache_instr_disable arch_icache_disable
#define cache_instr_all(op) arch_icache_all(op)
#define cache_instr_range(addr, size, op) arch_icache_range(addr, size, op) #define cache_instr_flush_all arch_icache_flush_all
#define cache_instr_invd_all arch_icache_invd_all
#define cache_instr_flush_and_invd_all arch_icache_flush_and_invd_all
#define cache_instr_flush_range(addr, size) arch_icache_flush_range(addr, size)
#define cache_instr_invd_range(addr, size) arch_icache_invd_range(addr, size)
#define cache_instr_flush_and_invd_range(addr, size) \
arch_icache_flush_and_invd_range(addr, size)
#if defined(CONFIG_ICACHE_LINE_SIZE_DETECT)
#define cache_instr_line_size_get arch_icache_line_size_get #define cache_instr_line_size_get arch_icache_line_size_get
#endif /* CONFIG_ICACHE_LINE_SIZE_DETECT */
#endif /* CONFIG_ICACHE */ #endif /* CONFIG_ICACHE */
#endif /* CONFIG_EXTERNAL_CACHE */
#endif /* CONFIG_HAS_EXTERNAL_CACHE */ /**
* @brief Enable the d-cache
*
* Enable the data cache
*
*/
static inline void sys_cache_data_enable(void)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
cache_data_enable();
#endif
}
__syscall int sys_cache_data_all(int op); /**
static inline int z_impl_sys_cache_data_all(int op) * @brief Disable the d-cache
*
* Disable the data cache
*
*/
static inline void sys_cache_data_disable(void)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
cache_data_disable();
#endif
}
/**
* @brief Enable the i-cache
*
* Enable the instruction cache
*
*/
static inline void sys_cache_instr_enable(void)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
cache_instr_enable();
#endif
}
/**
* @brief Disable the i-cache
*
* Disable the instruction cache
*
*/
static inline void sys_cache_instr_disable(void)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
cache_instr_disable();
#endif
}
/**
* @brief Flush the d-cache
*
* Flush the whole data cache.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
static inline int sys_cache_data_flush_all(void)
{ {
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE) #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
return cache_data_all(op); return cache_data_flush_all();
#endif #endif
ARG_UNUSED(op);
return -ENOTSUP; return -ENOTSUP;
} }
__syscall int sys_cache_data_range(void *addr, size_t size, int op); /**
static inline int z_impl_sys_cache_data_range(void *addr, size_t size, int op) * @brief Flush the i-cache
*
* Flush the whole instruction cache.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
static inline int sys_cache_instr_flush_all(void)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
return cache_instr_flush_all();
#endif
return -ENOTSUP;
}
/**
* @brief Invalidate the d-cache
*
* Invalidate the whole data cache.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
static inline int sys_cache_data_invd_all(void)
{ {
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE) #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
return cache_data_range(addr, size, op); return cache_data_invd_all();
#endif
return -ENOTSUP;
}
/**
* @brief Invalidate the i-cache
*
* Invalidate the whole instruction cache.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
static inline int sys_cache_instr_invd_all(void)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
return cache_instr_invd_all();
#endif
return -ENOTSUP;
}
/**
* @brief Flush and Invalidate the d-cache
*
* Flush and Invalidate the whole data cache.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
static inline int sys_cache_data_flush_and_invd_all(void)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
return cache_data_flush_and_invd_all();
#endif
return -ENOTSUP;
}
/**
* @brief Flush and Invalidate the i-cache
*
* Flush and Invalidate the whole instruction cache.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
static inline int sys_cache_instr_flush_and_invd_all(void)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
return cache_instr_flush_and_invd_all();
#endif
return -ENOTSUP;
}
/**
* @brief Flush an address range in the d-cache
*
* Flush the specified address range of the data cache.
*
* @param addr Starting address to flush.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
__syscall int sys_cache_data_flush_range(void *addr, size_t size);
static inline int z_impl_sys_cache_data_flush_range(void *addr, size_t size)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
return cache_data_flush_range(addr, size);
#endif #endif
ARG_UNUSED(addr); ARG_UNUSED(addr);
ARG_UNUSED(size); ARG_UNUSED(size);
ARG_UNUSED(op);
return -ENOTSUP; return -ENOTSUP;
} }
__syscall int sys_cache_instr_all(int op); /**
static inline int z_impl_sys_cache_instr_all(int op) * @brief Flush an address range in the i-cache
*
* Flush the specified address range of the instruction cache.
*
* @param addr Starting address to flush.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
static inline int sys_cache_instr_flush_range(void *addr, size_t size)
{ {
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE) #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
return cache_instr_all(op); return cache_instr_flush_range(addr, size);
#endif
ARG_UNUSED(op);
return -ENOTSUP;
}
__syscall int sys_cache_instr_range(void *addr, size_t size, int op);
static inline int z_impl_sys_cache_instr_range(void *addr, size_t size, int op)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
return cache_instr_range(addr, size, op);
#endif #endif
ARG_UNUSED(addr); ARG_UNUSED(addr);
ARG_UNUSED(size); ARG_UNUSED(size);
ARG_UNUSED(op);
return -ENOTSUP; return -ENOTSUP;
} }
#ifdef CONFIG_LIBMETAL /**
static inline void sys_cache_flush(void *addr, size_t size) * @brief Invalidate an address range in the d-cache
*
* Invalidate the specified address range of the data cache.
*
* @param addr Starting address to invalidate.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
__syscall int sys_cache_data_invd_range(void *addr, size_t size);
static inline int z_impl_sys_cache_data_invd_range(void *addr, size_t size)
{ {
sys_cache_data_range(addr, size, K_CACHE_WB); #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
} return cache_data_invd_range(addr, size);
#endif #endif
ARG_UNUSED(addr);
ARG_UNUSED(size);
return -ENOTSUP;
}
/**
* @brief Invalidate an address range in the i-cache
*
* Invalidate the specified address range of the instruction cache.
*
* @param addr Starting address to invalidate.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
static inline int sys_cache_instr_invd_range(void *addr, size_t size)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
return cache_instr_invd_range(addr, size);
#endif
ARG_UNUSED(addr);
ARG_UNUSED(size);
return -ENOTSUP;
}
/**
* @brief Flush and Invalidate an address range in the d-cache
*
* Flush and Invalidate the specified address range of the data cache.
*
* @param addr Starting address to flush and invalidate.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
__syscall int sys_cache_data_flush_and_invd_range(void *addr, size_t size);
static inline int z_impl_sys_cache_data_flush_and_invd_range(void *addr, size_t size)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
return cache_data_flush_and_invd_range(addr, size);
#endif
ARG_UNUSED(addr);
ARG_UNUSED(size);
return -ENOTSUP;
}
/**
* @brief Flush and Invalidate an address range in the i-cache
*
* Flush and Invalidate the specified address range of the instruction cache.
*
* @param addr Starting address to flush and invalidate.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
static inline int sys_cache_instr_flush_and_invd_range(void *addr, size_t size)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
return cache_instr_flush_and_invd_range(addr, size);
#endif
ARG_UNUSED(addr);
ARG_UNUSED(size);
return -ENOTSUP;
}
#define CPU DT_PATH(cpus, cpu_0) #define CPU DT_PATH(cpus, cpu_0)
/** /**
* *
* @brief Get the d-cache line size. * @brief Get the the d-cache line size.
* *
* The API is provided to get the d-cache line size. * The API is provided to get the data cache line.
* *
* @return size of the d-cache line or 0 if the d-cache is not enabled. * The cache line size is calculated (in order of priority):
*
* - At run-time when CONFIG_DCACHE_LINE_SIZE_DETECT is set.
* - At compile time using the value set in CONFIG_DCACHE_LINE_SIZE.
* - At compile time using the `d-cache-line-size` CPU0 property of the DT.
* - 0 otherwise
*
* @retval size Size of the d-cache line.
* @retval 0 If the d-cache is not enabled.
*/ */
static inline size_t sys_cache_data_line_size_get(void) static inline size_t sys_cache_data_line_size_get(void)
{ {
@ -166,13 +437,21 @@ static inline size_t sys_cache_data_line_size_get(void)
#endif #endif
} }
/* /**
* *
* @brief Get the i-cache line size. * @brief Get the the i-cache line size.
* *
* The API is provided to get the i-cache line size. * The API is provided to get the instruction cache line.
* *
* @return size of the i-cache line or 0 if the i-cache is not enabled. * The cache line size is calculated (in order of priority):
*
* - At run-time when CONFIG_ICACHE_LINE_SIZE_DETECT is set.
* - At compile time using the value set in CONFIG_ICACHE_LINE_SIZE.
* - At compile time using the `i-cache-line-size` CPU0 property of the DT.
* - 0 otherwise
*
* @retval size Size of the d-cache line.
* @retval 0 If the d-cache is not enabled.
*/ */
static inline size_t sys_cache_instr_line_size_get(void) static inline size_t sys_cache_instr_line_size_get(void)
{ {
@ -185,6 +464,13 @@ static inline size_t sys_cache_instr_line_size_get(void)
#endif #endif
} }
#ifdef CONFIG_LIBMETAL
static inline void sys_cache_flush(void *addr, size_t size)
{
sys_cache_data_flush_range(addr, size);
}
#endif
#include <syscalls/cache.h> #include <syscalls/cache.h>
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -4,68 +4,131 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
/**
* @file
* Public APIs for external cache controller drivers
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_CACHE_H_ #ifndef ZEPHYR_INCLUDE_DRIVERS_CACHE_H_
#define ZEPHYR_INCLUDE_DRIVERS_CACHE_H_ #define ZEPHYR_INCLUDE_DRIVERS_CACHE_H_
/**
* @brief External Cache Controller Interface
* @defgroup cache_interface External Cache Controller Interface
* @ingroup io_interfaces
* @{
*/
#include <zephyr/cache.h> #include <zephyr/cache.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(CONFIG_DCACHE) #if defined(CONFIG_DCACHE)
/** /**
* @brief Enable d-cache * @brief Enable the d-cache
* *
* Enable the d-cache. * Enable the data cache.
*/ */
void cache_data_enable(void); void cache_data_enable(void);
/** /**
* @brief Disable d-cache * @brief Disable the d-cache
* *
* Disable the d-cache. * Disable the data cache.
*/ */
void cache_data_disable(void); void cache_data_disable(void);
/** /**
* @brief Flush the d-cache
* *
* @brief Write-back / Invalidate / Write-back + Invalidate all d-cache * Flush the whole data cache.
* *
* Write-back, Invalidate or Write-back + Invalidate the whole d-cache. * @retval 0 If succeeded.
* * @retval -ENOTSUP If not supported.
* @param op Operation to perform (one of the K_CACHE_* operations) * @retval -errno Negative errno for other failures.
*
* @retval 0 On success
* @retval -ENOTSUP If the operation is not supported
*/ */
int cache_data_all(int op); int cache_data_flush_all(void);
/** /**
* @brief Invalidate the d-cache
* *
* @brief Write-back / Invalidate / Write-back + Invalidate d-cache lines * Invalidate the whole data cache.
* *
* No alignment is required for either addr or size, but since * @retval 0 If succeeded.
* arch_dcache_range() iterates on the d-cache lines, a d-cache line alignment * @retval -ENOTSUP If not supported.
* for both is optimal. * @retval -errno Negative errno for other failures.
*
* The d-cache line size is specified either via the CONFIG_DCACHE_LINE_SIZE
* kconfig option or it is detected at runtime.
*
* @param addr The pointer to start the multi-line operation
* @param size The number of bytes that are to be acted on
* @param op Operation to perform (one of the K_CACHE_* operations)
*
* @retval 0 On success
* @retval -ENOTSUP If the operation is not supported
*/ */
int cache_data_range(void *addr, size_t size, int op); int cache_data_invd_all(void);
/**
* @brief Flush and Invalidate the d-cache
*
* Flush and Invalidate the whole data cache.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int cache_data_flush_and_invd_all(void);
/**
* @brief Flush an address range in the d-cache
*
* Flush the specified address range of the data cache.
*
* @param addr Starting address to flush.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int cache_data_flush_range(void *addr, size_t size);
/**
* @brief Invalidate an address range in the d-cache
*
* Invalidate the specified address range of the data cache.
*
* @param addr Starting address to invalidate.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int cache_data_invd_range(void *addr, size_t size);
/**
* @brief Flush and Invalidate an address range in the d-cache
*
* Flush and Invalidate the specified address range of the data cache.
*
* @param addr Starting address to flush and invalidate.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int cache_data_flush_and_invd_range(void *addr, size_t size);
#if defined(CONFIG_DCACHE_LINE_SIZE_DETECT) #if defined(CONFIG_DCACHE_LINE_SIZE_DETECT)
/** /**
* *
* @brief Get the i-cache line size. * @brief Get the d-cache line size.
* *
* The API is provided to get the i-cache line size. * The API is provided to dynamically detect the data cache line size at run
* time.
* *
* @return size of the i-cache line or 0 if the i-cache is not enabled. * The function must be implemented only when CONFIG_DCACHE_LINE_SIZE_DETECT is
* defined.
*
* @retval size Size of the d-cache line.
* @retval 0 If the d-cache is not enabled.
*/ */
size_t cache_data_line_size_get(void); size_t cache_data_line_size_get(void);
@ -74,61 +137,109 @@ size_t cache_data_line_size_get(void);
#endif /* CONFIG_DCACHE */ #endif /* CONFIG_DCACHE */
#if defined(CONFIG_ICACHE) #if defined(CONFIG_ICACHE)
/** /**
* @brief Enable i-cache * @brief Enable the i-cache
* *
* Enable the i-cache. * Enable the instruction cache.
*/ */
void cache_instr_enable(void); void cache_instr_enable(void);
/** /**
* @brief Disable i-cache * @brief Disable the i-cache
* *
* Disable the i-cache. * Disable the instruction cache.
*/ */
void cache_instr_disable(void); void cache_instr_disable(void);
/** /**
* @brief Flush the i-cache
* *
* @brief Write-back / Invalidate / Write-back + Invalidate all i-cache * Flush the whole instruction cache.
* *
* Write-back, Invalidate or Write-back + Invalidate the whole i-cache. * @retval 0 If succeeded.
* * @retval -ENOTSUP If not supported.
* @param op Operation to perform (one of the K_CACHE_* operations) * @retval -errno Negative errno for other failures.
*
* @retval 0 On success
* @retval -ENOTSUP If the operation is not supported
*/ */
int cache_instr_all(int op); int cache_instr_flush_all(void);
/** /**
* @brief Invalidate the i-cache
* *
* @brief Write-back / Invalidate / Write-back + Invalidate i-cache lines * Invalidate the whole instruction cache.
* *
* No alignment is required for either addr or size, but since * @retval 0 If succeeded.
* arch_icache_range() iterates on the i-cache lines, an i-cache line alignment * @retval -ENOTSUP If not supported.
* for both is optimal. * @retval -errno Negative errno for other failures.
*
* The i-cache line size is specified either via the CONFIG_ICACHE_LINE_SIZE
* kconfig option or it is detected at runtime.
*
* @param addr The pointer to start the multi-line operation
* @param size The number of bytes that are to be acted on
* @param op Operation to perform (one of the K_CACHE_* operations)
*
* @retval 0 On success
* @retval -ENOTSUP If the operation is not supported
*/ */
int cache_instr_range(void *addr, size_t size, int op); int cache_instr_invd_all(void);
/**
* @brief Flush and Invalidate the i-cache
*
* Flush and Invalidate the whole instruction cache.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int cache_instr_flush_and_invd_all(void);
/**
* @brief Flush an address range in the i-cache
*
* Flush the specified address range of the instruction cache.
*
* @param addr Starting address to flush.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int cache_instr_flush_range(void *addr, size_t size);
/**
* @brief Invalidate an address range in the i-cache
*
* Invalidate the specified address range of the instruction cache.
*
* @param addr Starting address to invalidate.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int cache_instr_invd_range(void *addr, size_t size);
/**
* @brief Flush and Invalidate an address range in the i-cache
*
* Flush and Invalidate the specified address range of the instruction cache.
*
* @param addr Starting address to flush and invalidate.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int cache_instr_flush_and_invd_range(void *addr, size_t size);
#ifdef CONFIG_ICACHE_LINE_SIZE_DETECT #ifdef CONFIG_ICACHE_LINE_SIZE_DETECT
/** /**
* *
* @brief Get the i-cache line size. * @brief Get the i-cache line size.
* *
* The API is provided to get the i-cache line size. * The API is provided to dynamically detect the instruction cache line size at
* run time.
* *
* @return size of the i-cache line or 0 if the i-cache is not enabled. * The function must be implemented only when CONFIG_ICACHE_LINE_SIZE_DETECT is
* defined.
*
* @retval size Size of the d-cache line.
* @retval 0 If the d-cache is not enabled.
*/ */
size_t cache_instr_line_size_get(void); size_t cache_instr_line_size_get(void);
@ -136,4 +247,12 @@ size_t cache_instr_line_size_get(void);
#endif /* CONFIG_ICACHE */ #endif /* CONFIG_ICACHE */
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#endif /* ZEPHYR_INCLUDE_DRIVERS_CACHE_H_ */ #endif /* ZEPHYR_INCLUDE_DRIVERS_CACHE_H_ */

View file

@ -1020,48 +1020,112 @@ int arch_gdb_remove_breakpoint(struct gdb_ctx *ctx, uint8_t type,
* @{ * @{
*/ */
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_HAS_ARCH_CACHE) #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ARCH_CACHE)
#if defined(CONFIG_DCACHE) #if defined(CONFIG_DCACHE)
/** /**
* @brief Enable the d-cache
* *
* @brief Enable d-cache * Enable the data cache.
*
* @see arch_dcache_enable
*/ */
void arch_dcache_enable(void); void arch_dcache_enable(void);
/** /**
* @brief Disable the d-cache
* *
* @brief Disable d-cache * Disable the data cache.
*
* @see arch_dcache_disable
*/ */
void arch_dcache_disable(void); void arch_dcache_disable(void);
/** /**
* @brief Flush the d-cache
* *
* @brief Write-back / Invalidate / Write-back + Invalidate all d-cache * Flush the whole data cache.
* *
* @see arch_dcache_all * @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/ */
int arch_dcache_all(int op); int arch_dcache_flush_all(void);
/** /**
* @brief Invalidate the d-cache
* *
* @brief Write-back / Invalidate / Write-back + Invalidate d-cache lines * Invalidate the whole data cache.
* *
* @see arch_dcache_range * @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/ */
int arch_dcache_range(void *addr, size_t size, int op); int arch_dcache_invd_all(void);
/**
* @brief Flush and Invalidate the d-cache
*
* Flush and Invalidate the whole data cache.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int arch_dcache_flush_and_invd_all(void);
/**
* @brief Flush an address range in the d-cache
*
* Flush the specified address range of the data cache.
*
* @param addr Starting address to flush.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int arch_dcache_flush_range(void *addr, size_t size);
/**
* @brief Invalidate an address range in the d-cache
*
* Invalidate the specified address range of the data cache.
*
* @param addr Starting address to invalidate.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int arch_dcache_invd_range(void *addr, size_t size);
/**
* @brief Flush and Invalidate an address range in the d-cache
*
* Flush and Invalidate the specified address range of the data cache.
*
* @param addr Starting address to flush and invalidate.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int arch_dcache_flush_and_invd_range(void *addr, size_t size);
#if defined(CONFIG_DCACHE_LINE_SIZE_DETECT) #if defined(CONFIG_DCACHE_LINE_SIZE_DETECT)
/** /**
* *
* @brief Get d-cache line size * @brief Get the the d-cache line size.
* *
* @see sys_cache_data_line_size_get * The API is provided to dynamically detect the data cache line size at run
* time.
*
* The function must be implemented only when CONFIG_DCACHE_LINE_SIZE_DETECT is
* defined.
*
* @retval size Size of the d-cache line.
* @retval 0 If the d-cache is not enabled.
*/ */
size_t arch_dcache_line_size_get(void); size_t arch_dcache_line_size_get(void);
#endif /* CONFIG_DCACHE_LINE_SIZE_DETECT */ #endif /* CONFIG_DCACHE_LINE_SIZE_DETECT */
@ -1069,54 +1133,114 @@ size_t arch_dcache_line_size_get(void);
#endif /* CONFIG_DCACHE */ #endif /* CONFIG_DCACHE */
#if defined(CONFIG_ICACHE) #if defined(CONFIG_ICACHE)
/** /**
* @brief Enable the i-cache
* *
* @brief Enable i-cache * Enable the instruction cache.
*
* @see arch_icache_enable
*/ */
void arch_icache_enable(void); void arch_icache_enable(void);
/** /**
* @brief Disable the i-cache
* *
* @brief Enable i-cache * Disable the instruction cache.
*
* @see arch_icache_disable
*/ */
void arch_icache_disable(void); void arch_icache_disable(void);
/**
* @brief Flush the i-cache
*
* Flush the whole instruction cache.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int arch_icache_flush_all(void);
/** /**
* @brief Invalidate the i-cache
* *
* @brief Write-back / Invalidate / Write-back + Invalidate all i-cache * Invalidate the whole instruction cache.
* *
* @see arch_icache_all * @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/ */
int arch_icache_all(int op); int arch_icache_invd_all(void);
/** /**
* @brief Flush and Invalidate the i-cache
* *
* @brief Write-back / Invalidate / Write-back + Invalidate i-cache lines * Flush and Invalidate the whole instruction cache.
* *
* @see arch_icache_range * @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/ */
int arch_icache_range(void *addr, size_t size, int op); int arch_icache_flush_and_invd_all(void);
/**
* @brief Flush an address range in the i-cache
*
* Flush the specified address range of the instruction cache.
*
* @param addr Starting address to flush.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int arch_icache_flush_range(void *addr, size_t size);
/**
* @brief Invalidate an address range in the i-cache
*
* Invalidate the specified address range of the instruction cache.
*
* @param addr Starting address to invalidate.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int arch_icache_invd_range(void *addr, size_t size);
/**
* @brief Flush and Invalidate an address range in the i-cache
*
* Flush and Invalidate the specified address range of the instruction cache.
*
* @param addr Starting address to flush and invalidate.
* @param size Range size.
*
* @retval 0 If succeeded.
* @retval -ENOTSUP If not supported.
* @retval -errno Negative errno for other failures.
*/
int arch_icache_flush_and_invd_range(void *addr, size_t size);
#if defined(CONFIG_ICACHE_LINE_SIZE_DETECT) #if defined(CONFIG_ICACHE_LINE_SIZE_DETECT)
/** /**
* *
* @brief Get i-cache line size * @brief Get the the i-cache line size.
* *
* @see sys_cache_instr_line_size_get * The API is provided to dynamically detect the instruction cache line size at
* run time.
*
* The function must be implemented only when CONFIG_ICACHE_LINE_SIZE_DETECT is
* defined.
*
* @retval size Size of the d-cache line.
* @retval 0 If the d-cache is not enabled.
*/ */
size_t arch_icache_line_size_get(void); size_t arch_icache_line_size_get(void);
#endif /* CONFIG_ICACHE_LINE_SIZE_DETECT */ #endif /* CONFIG_ICACHE_LINE_SIZE_DETECT */
#endif /* CONFIG_ICACHE */ #endif /* CONFIG_ICACHE */
#endif /* CONFIG_CACHE_MANAGEMENT && CONFIG_ARCH_CACHE */
#endif /* CONFIG_CACHE_MANAGEMENT && CONFIG_HAS_ARCH_CACHE */
/** @} */ /** @} */

View file

@ -16,7 +16,7 @@ config DCACHE_LINE_SIZE
default 32 default 32
choice CACHE_TYPE choice CACHE_TYPE
default HAS_EXTERNAL_CACHE default EXTERNAL_CACHE
endchoice endchoice
endif # SOC_SERIES_AST10X0 endif # SOC_SERIES_AST10X0