Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cache: Introduce device cache support #34607

Merged
merged 2 commits into from
May 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
/drivers/adc/ @anangl
/drivers/adc/adc_stm32.c @cybertale
/drivers/bluetooth/ @joerchan @jhedberg @Vudentz
/drivers/cache/ @carlocaione
/drivers/can/ @alexanderwachter
/drivers/can/*mcp2515* @karstenkoenig
/drivers/clock_control/*nrf* @nordic-krch
Expand Down
17 changes: 17 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,23 @@ config ICACHE_LINE_SIZE

Detect automatically at runtime by selecting ICACHE_LINE_SIZE_DETECT.

choice
prompt "Cache type"
depends on CACHE_MANAGEMENT
default HAS_ARCH_CACHE

config HAS_ARCH_CACHE
bool "Integrated cache controller"
help
"Integrade on-core cache controller"

config HAS_EXTERNAL_CACHE
bool "External cache controller"
help
"External cache controller or cache management system"

endchoice

endmenu

config ARCH
Expand Down
4 changes: 2 additions & 2 deletions arch/arc/core/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ void arch_dcache_enable(void)

static void arch_dcache_flush(void *start_addr_ptr, size_t size)
{
size_t line_size = sys_dcache_line_size_get();
size_t line_size = sys_cache_data_line_size_get();
uintptr_t start_addr = (uintptr_t)start_addr_ptr;
uintptr_t end_addr;
unsigned int key;
Expand Down Expand Up @@ -99,7 +99,7 @@ static void arch_dcache_flush(void *start_addr_ptr, size_t size)

static void arch_dcache_invd(void *start_addr_ptr, size_t size)
{
size_t line_size = sys_dcache_line_size_get();
size_t line_size = sys_cache_data_line_size_get();
uintptr_t start_addr = (uintptr_t)start_addr_ptr;
uintptr_t end_addr;
unsigned int key;
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/core/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ static void enable_mmu_el1(struct arm_mmu_ptables *ptables, unsigned int flags)
isb();

/* Invalidate all data caches before enable them */
sys_dcache_all(K_CACHE_INVD);
sys_cache_data_all(K_CACHE_INVD);

/* Enable the MMU and data cache */
val = read_sctlr_el1();
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/core/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
*/
static void arch_dcache_flush(void *start_addr, size_t size)
{
size_t line_size = sys_dcache_line_size_get();
size_t line_size = sys_cache_data_line_size_get();
uintptr_t start = (uintptr_t)start_addr;
uintptr_t end;

Expand Down
1 change: 1 addition & 0 deletions drivers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ add_subdirectory_ifdef(CONFIG_SYS_CLOCK_EXISTS timer)
add_subdirectory_ifdef(CONFIG_NEURAL_NET_ACCEL neural_net)
add_subdirectory_ifdef(CONFIG_PTP_CLOCK ptp_clock)
add_subdirectory_ifdef(CONFIG_EDAC edac)
add_subdirectory_ifdef(CONFIG_CACHE_MANAGEMENT cache)
2 changes: 2 additions & 0 deletions drivers/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,6 @@ source "drivers/misc/Kconfig"

source "drivers/disk/Kconfig"

source "drivers/cache/Kconfig"

endmenu
1 change: 1 addition & 0 deletions drivers/cache/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# SPDX-License-Identifier: Apache-2.0
ioannisg marked this conversation as resolved.
Show resolved Hide resolved
18 changes: 18 additions & 0 deletions drivers/cache/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright (c) 2021 Carlo Caione <ccaione@baylibre.com>
# SPDX-License-Identifier: Apache-2.0

menuconfig CACHE
bool "External cache controllers drivers"
help
Enable support for external cache controllers drivers

if CACHE

module = CACHE
module-str = cache
source "subsys/logging/Kconfig.template.log_config"

config CACHE_HAS_DRIVER
bool

endif # CACHE
187 changes: 64 additions & 123 deletions include/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define ZEPHYR_INCLUDE_CACHE_H_

#include <kernel.h>
#include <kernel_structs.h>

#ifdef __cplusplus
extern "C" {
Expand All @@ -22,156 +23,96 @@ extern "C" {
* 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)

/**
*
* @brief Enable d-cache
*
* Enable the d-cache.
*
* @return N/A
*/
void arch_dcache_enable(void);
#if defined(CONFIG_HAS_EXTERNAL_CACHE)

/**
*
* @brief Disable d-cache
*
* Disable the d-cache.
*
* @return N/A
*/
void arch_dcache_disable(void);
/* Driver interface mirrored in include/drivers/cache.h */

/**
*
* @brief Enable i-cache
*
* Enable the i-cache.
*
* @return N/A
*/
void arch_icache_enable(void);
/* Enable d-cache */
extern void cache_data_enable(void);

/**
*
* @brief Disable i-cache
*
* Disable the i-cache.
*
* @return N/A
*/
void arch_icache_disable(void);
/* Disable d-cache */
extern void cache_data_disable(void);

/**
*
* @brief Write-back / Invalidate / Write-back + Invalidate all d-cache
*
* Write-back, Invalidate or Write-back + Invalidate the whole d-cache.
*
* @param op Operation to perform (one of the K_CACHE_* operations)
*
* @retval 0 On success
* @retval -ENOTSUP If the operation is not supported
*/
int arch_dcache_all(int op);
/* Enable i-cache */
extern void cache_instr_enable(void);

/**
*
* @brief Write-back / Invalidate / Write-back + Invalidate d-cache lines
*
* No alignment is required for either addr or size, but since
* arch_dcache_range() 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_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 arch_dcache_range(void *addr, size_t size, int op);
/* Disable i-cache */
extern void cache_instr_disable(void);

/**
*
* @brief Write-back / Invalidate / Write-back + Invalidate all i-cache
*
* Write-back, Invalidate or Write-back + Invalidate the whole i-cache.
*
* @param op Operation to perform (one of the K_CACHE_* operations)
*
* @retval 0 On success
* @retval -ENOTSUP If the operation is not supported
*/
int arch_icache_all(int op);
/* Write-back / Invalidate / Write-back + Invalidate all d-cache */
extern int cache_data_all(int op);

/**
*
* @brief Write-back / Invalidate / Write-back + Invalidate i-cache lines
*
* No alignment is required for either addr or size, but since
* arch_icache_range() iterates on the i-cache lines, an i-cache line alignment
* for both is optimal.
*
* 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 arch_icache_range(void *addr, size_t size, int op);
/* Write-back / Invalidate / Write-back + Invalidate d-cache lines */
extern int cache_data_range(void *addr, size_t size, int op);

/* Write-back / Invalidate / Write-back + Invalidate all i-cache */
extern int cache_instr_all(int op);

/* Write-back / Invalidate / Write-back + Invalidate i-cache lines */
extern int cache_instr_range(void *addr, size_t size, int op);

#else

/* Hooks into arch code */

__syscall int sys_dcache_all(int op);
static inline int z_impl_sys_dcache_all(int op)
#define cache_data_enable arch_dcache_enable
#define cache_data_disable arch_dcache_disable
#define cache_instr_enable arch_icache_enable
#define cache_instr_disable arch_icache_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_instr_all(op) arch_icache_all(op)
#define cache_instr_range(addr, size, op) arch_icache_range(addr, size, op)
#define cache_data_line_size_get arch_dcache_line_size_get
#define cache_instr_line_size_get arch_icache_line_size_get

#endif

__syscall int sys_cache_data_all(int op);
static inline int z_impl_sys_cache_data_all(int op)
{
if (IS_ENABLED(CONFIG_CACHE_MANAGEMENT)) {
return arch_dcache_all(op);
}
#if defined(CONFIG_CACHE_MANAGEMENT)
return cache_data_all(op);
#endif
return -ENOTSUP;
}

__syscall int sys_dcache_range(void *addr, size_t size, int op);
static inline int z_impl_sys_dcache_range(void *addr, size_t size, int op)
__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)
{
if (IS_ENABLED(CONFIG_CACHE_MANAGEMENT)) {
return arch_dcache_range(addr, size, op);
}
#if defined(CONFIG_CACHE_MANAGEMENT)
return cache_data_range(addr, size, op);
#endif
return -ENOTSUP;
}

__syscall int sys_icache_all(int op);
static inline int z_impl_sys_icache_all(int op)
__syscall int sys_cache_instr_all(int op);
static inline int z_impl_sys_cache_instr_all(int op)
{
if (IS_ENABLED(CONFIG_CACHE_MANAGEMENT)) {
return arch_icache_all(op);
}
#if defined(CONFIG_CACHE_MANAGEMENT)
return cache_instr_all(op);
#endif
return -ENOTSUP;
}

__syscall int sys_icache_range(void *addr, size_t size, int op);
static inline int z_impl_sys_icache_range(void *addr, size_t size, int op)
__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 (IS_ENABLED(CONFIG_CACHE_MANAGEMENT)) {
return arch_icache_range(addr, size, op);
}
#if defined(CONFIG_CACHE_MANAGEMENT)
return cache_instr_range(addr, size, op);
#endif
return -ENOTSUP;
}

#ifdef CONFIG_LIBMETAL
static inline void sys_cache_flush(void *addr, size_t size)
{
sys_dcache_range(addr, size, K_CACHE_WB);
sys_cache_data_range(addr, size, K_CACHE_WB);
}
#endif

Expand All @@ -185,10 +126,10 @@ static inline void sys_cache_flush(void *addr, size_t size)
*
* @return size of the d-cache line or 0 if the d-cache is not enabled.
*/
static inline size_t sys_dcache_line_size_get(void)
static inline size_t sys_cache_data_line_size_get(void)
{
#ifdef CONFIG_DCACHE_LINE_SIZE_DETECT
return arch_dcache_line_size_get();
return cache_data_line_size_get();
#elif (CONFIG_DCACHE_LINE_SIZE != 0)
return CONFIG_DCACHE_LINE_SIZE;
#else
Expand All @@ -204,10 +145,10 @@ static inline size_t sys_dcache_line_size_get(void)
*
* @return size of the i-cache line or 0 if the i-cache is not enabled.
*/
static inline size_t sys_icache_line_size_get(void)
static inline size_t sys_cache_instr_line_size_get(void)
{
#ifdef CONFIG_ICACHE_LINE_SIZE_DETECT
return arch_icache_line_size_get();
return cache_instr_line_size_get();
#elif (CONFIG_ICACHE_LINE_SIZE != 0)
return CONFIG_ICACHE_LINE_SIZE;
#else
Expand Down
Loading