From bb281eedfa8bd8b87ac58d8b55405695a3ea6455 Mon Sep 17 00:00:00 2001 From: ligd Date: Tue, 7 Feb 2023 17:31:01 +0800 Subject: [PATCH] cache: add up_get_xcache_linesize() support Signed-off-by: ligd --- arch/arm/src/arm/arm_cache.S | 16 ++++ arch/arm/src/armv7-a/arm_cache.c | 73 +++++++++++++++++ arch/arm/src/armv7-a/arm_l2cc_pl310.c | 19 +++++ arch/arm/src/armv7-a/cp15_cacheops.c | 5 ++ arch/arm/src/armv7-a/cp15_cacheops.h | 16 ++++ arch/arm/src/armv7-a/l2cc.h | 17 ++++ arch/arm/src/armv7-m/arm_cache.c | 111 ++++++++++++++++++++------ arch/arm/src/armv7-r/arm_cache.c | 73 +++++++++++++++++ arch/arm/src/armv7-r/arm_l2cc_pl310.c | 19 +++++ arch/arm/src/armv7-r/cp15_cacheops.c | 5 ++ arch/arm/src/armv7-r/cp15_cacheops.h | 16 ++++ arch/arm/src/armv7-r/l2cc.h | 17 ++++ arch/arm/src/armv8-m/arm_cache.c | 111 ++++++++++++++++++++------ arch/arm64/src/common/arm64_cache.c | 38 +++++++++ arch/xtensa/src/common/xtensa_cache.c | 42 ++++++++++ include/nuttx/cache.h | 40 ++++++++++ 16 files changed, 566 insertions(+), 52 deletions(-) diff --git a/arch/arm/src/arm/arm_cache.S b/arch/arm/src/arm/arm_cache.S index 8b871365f0..02db4cf3ac 100644 --- a/arch/arm/src/arm/arm_cache.S +++ b/arch/arm/src/arm/arm_cache.S @@ -72,6 +72,22 @@ * the corresponding I-Cache lines. */ + .globl up_get_dcache_linesize + .type up_get_dcache_linesize, function + +up_get_dcache_linesize: + mov r0, #CACHE_DLINESIZE + mov pc, lr + .size up_get_dcache_linesize, .-up_get_dcache_linesize + + .globl up_get_icache_linesize + .type up_get_icache_linesize, function + +up_get_icache_linesize: + mov r0, #CACHE_DLINESIZE + mov pc, lr + .size up_get_icache_linesize, .-up_get_icache_linesize + .globl up_coherent_dcache .type up_coherent_dcache, function diff --git a/arch/arm/src/armv7-a/arm_cache.c b/arch/arm/src/armv7-a/arm_cache.c index e5ae5ca323..95eb5ebae3 100644 --- a/arch/arm/src/armv7-a/arm_cache.c +++ b/arch/arm/src/armv7-a/arm_cache.c @@ -25,17 +25,71 @@ #include #include #include +#include #include "cp15_cacheops.h" #include "barriers.h" #include "l2cc.h" +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if defined(CONFIG_ARCH_ICACHE) || defined(CONFIG_ARCH_DCACHE) + +/**************************************************************************** + * Name: up_get_cache_linesize + * + * Description: + * Get cache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +static size_t up_get_cache_linesize(void) +{ + static uint32_t clsize; + + if (clsize == 0) + { + clsize = MAX(cp15_cache_linesize(), l2cc_get_linesize()); + } + + return clsize; +} + +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ #ifdef CONFIG_ARCH_ICACHE +/**************************************************************************** + * Name: up_get_icache_linesize + * + * Description: + * Get icache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +size_t up_get_icache_linesize(void) +{ + return up_get_cache_linesize(); +} + /**************************************************************************** * Name: up_invalidate_icache_all * @@ -119,6 +173,25 @@ void up_disable_icache(void) #ifdef CONFIG_ARCH_DCACHE +/**************************************************************************** + * Name: up_get_dcache_linesize + * + * Description: + * Get dcache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +size_t up_get_dcache_linesize(void) +{ + return up_get_cache_linesize(); +} + /**************************************************************************** * Name: up_invalidate_dcache * diff --git a/arch/arm/src/armv7-a/arm_l2cc_pl310.c b/arch/arm/src/armv7-a/arm_l2cc_pl310.c index 1dba68fc14..4b4d105070 100644 --- a/arch/arm/src/armv7-a/arm_l2cc_pl310.c +++ b/arch/arm/src/armv7-a/arm_l2cc_pl310.c @@ -396,6 +396,25 @@ void arm_l2ccinitialize(void) PL310_NWAYS, PL310_WAYSIZE, PL310_CACHE_SIZE); } +/**************************************************************************** + * Name: l2cc_get_linesize + * + * Description: + * Get L2CC-P310 L2 cache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * L2 cache linesize + * + ****************************************************************************/ + +uint32_t l2cc_get_linesize(void) +{ + return PL310_CACHE_LINE_SIZE; +} + /**************************************************************************** * Name: l2cc_enable * diff --git a/arch/arm/src/armv7-a/cp15_cacheops.c b/arch/arm/src/armv7-a/cp15_cacheops.c index a1d1f1dc5e..084e46df0c 100644 --- a/arch/arm/src/armv7-a/cp15_cacheops.c +++ b/arch/arm/src/armv7-a/cp15_cacheops.c @@ -269,3 +269,8 @@ uint32_t cp15_cache_size(void) return sets * ways * line; } + +uint32_t cp15_cache_linesize(void) +{ + return cp15_cache_get_info(NULL, NULL); +} diff --git a/arch/arm/src/armv7-a/cp15_cacheops.h b/arch/arm/src/armv7-a/cp15_cacheops.h index 0ef581bf80..a680c4b5a9 100644 --- a/arch/arm/src/armv7-a/cp15_cacheops.h +++ b/arch/arm/src/armv7-a/cp15_cacheops.h @@ -1106,6 +1106,22 @@ void cp15_flush_dcache_all(void); uint32_t cp15_cache_size(void); +/**************************************************************************** + * Name: cp15_cache_linesize + * + * Description: + * Get cp15 cache linesize in byte + * + * Input Parameters: + * None + * + * Returned Value: + * Cache linesize in byte + * + ****************************************************************************/ + +uint32_t cp15_cache_linesize(void); + #undef EXTERN #ifdef __cplusplus } diff --git a/arch/arm/src/armv7-a/l2cc.h b/arch/arm/src/armv7-a/l2cc.h index ad820c3e47..eee2e80c73 100644 --- a/arch/arm/src/armv7-a/l2cc.h +++ b/arch/arm/src/armv7-a/l2cc.h @@ -70,6 +70,22 @@ extern "C" void arm_l2ccinitialize(void); #endif +/**************************************************************************** + * Name: l2cc_get_linesize + * + * Description: + * Get L2 cache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * L2 cache linesize + * + ****************************************************************************/ + +uint32_t l2cc_get_linesize(void); + /**************************************************************************** * Name: l2cc_enable * @@ -229,6 +245,7 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr); * compilation in one place. */ +# define l2cc_get_linesize() 0 # define l2cc_enable() # define l2cc_disable() # define l2cc_sync() diff --git a/arch/arm/src/armv7-m/arm_cache.c b/arch/arm/src/armv7-m/arm_cache.c index 6dd5d0aed1..34ee70441b 100644 --- a/arch/arm/src/armv7-m/arm_cache.c +++ b/arch/arm/src/armv7-m/arm_cache.c @@ -100,10 +100,68 @@ static inline uint32_t arm_clz(unsigned int value) } #endif +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_get_cache_linesize + * + * Description: + * Get cache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +#if defined(CONFIG_ARMV7M_ICACHE) || defined(CONFIG_ARMV7M_DCACHE) +static size_t up_get_cache_linesize(void) +{ + static uint32_t clsize; + + if (clsize == 0) + { + uint32_t ccsidr; + uint32_t sshift; + + ccsidr = getreg32(NVIC_CCSIDR); + sshift = CCSIDR_LSSHIFT(ccsidr) + 4; /* log2(cache-line-size-in-bytes) */ + clsize = 1 << sshift; + } + + return clsize; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: up_get_icache_linesize + * + * Description: + * Get icache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +#ifdef CONFIG_ARMV7M_ICACHE +size_t up_get_icache_linesize(void) +{ + return up_get_cache_linesize(); +} +#endif + /**************************************************************************** * Name: up_enable_icache * @@ -196,20 +254,10 @@ void up_disable_icache(void) #ifdef CONFIG_ARMV7M_ICACHE void up_invalidate_icache(uintptr_t start, uintptr_t end) { - uint32_t ccsidr; - uint32_t sshift; - uint32_t ssize; + uint32_t ssize = up_get_icache_linesize(); - /* Get the characteristics of the I-Cache */ - - ccsidr = getreg32(NVIC_CCSIDR); - sshift = CCSIDR_LSSHIFT(ccsidr) + 4; /* log2(cache-line-size-in-bytes) */ - - /* Invalidate the I-Cache containing this range of addresses */ - - ssize = (1 << sshift); - - /* Round down the start address to the nearest cache line boundary. + /* Invalidate the I-Cache containing this range of addresses. + * Round down the start address to the nearest cache line boundary. * * sshift = 5 : Offset to the beginning of the set field * (ssize - 1) = 0x007f : Mask of the set field @@ -279,6 +327,27 @@ void up_invalidate_icache_all(void) } #endif +/**************************************************************************** + * Name: up_get_dcache_linesize + * + * Description: + * Get dcache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +#ifdef CONFIG_ARMV7M_DCACHE +size_t up_get_dcache_linesize(void) +{ + return up_get_cache_linesize(); +} +#endif + /**************************************************************************** * Name: up_enable_dcache * @@ -459,20 +528,10 @@ void up_disable_dcache(void) #ifdef CONFIG_ARMV7M_DCACHE void up_invalidate_dcache(uintptr_t start, uintptr_t end) { - uint32_t ccsidr; - uint32_t sshift; - uint32_t ssize; + uint32_t ssize = up_get_dcache_linesize(); - /* Get the characteristics of the D-Cache */ - - ccsidr = getreg32(NVIC_CCSIDR); - sshift = CCSIDR_LSSHIFT(ccsidr) + 4; /* log2(cache-line-size-in-bytes) */ - - /* Invalidate the D-Cache containing this range of addresses */ - - ssize = (1 << sshift); - - /* Round down the start address to the nearest cache line boundary. + /* Invalidate the D-Cache containing this range of addresses + * Round down the start address to the nearest cache line boundary. * * sshift = 5 : Offset to the beginning of the set field * (ssize - 1) = 0x007f : Mask of the set field diff --git a/arch/arm/src/armv7-r/arm_cache.c b/arch/arm/src/armv7-r/arm_cache.c index 91e5a241c1..0163f176cb 100644 --- a/arch/arm/src/armv7-r/arm_cache.c +++ b/arch/arm/src/armv7-r/arm_cache.c @@ -25,17 +25,71 @@ #include #include #include +#include #include "cp15_cacheops.h" #include "barriers.h" #include "l2cc.h" +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if defined(CONFIG_ARCH_ICACHE) || defined(CONFIG_ARCH_DCACHE) + +/**************************************************************************** + * Name: up_get_cache_linesize + * + * Description: + * Get cache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +static size_t up_get_cache_linesize(void) +{ + static uint32_t clsize; + + if (clsize == 0) + { + clsize = MAX(cp15_cache_linesize(), l2cc_get_linesize()); + } + + return clsize; +} + +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ #ifdef CONFIG_ARCH_ICACHE +/**************************************************************************** + * Name: up_get_icache_linesize + * + * Description: + * Get icache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +size_t up_get_icache_linesize(void) +{ + return up_get_cache_linesize(); +} + /**************************************************************************** * Name: up_invalidate_icache_all * @@ -119,6 +173,25 @@ void up_disable_icache(void) #ifdef CONFIG_ARCH_DCACHE +/**************************************************************************** + * Name: up_get_dcache_linesize + * + * Description: + * Get dcache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +size_t up_get_dcache_linesize(void) +{ + return up_get_cache_linesize(); +} + /**************************************************************************** * Name: up_invalidate_dcache * diff --git a/arch/arm/src/armv7-r/arm_l2cc_pl310.c b/arch/arm/src/armv7-r/arm_l2cc_pl310.c index fb1bd8d4a8..2de729ce09 100644 --- a/arch/arm/src/armv7-r/arm_l2cc_pl310.c +++ b/arch/arm/src/armv7-r/arm_l2cc_pl310.c @@ -396,6 +396,25 @@ void arm_l2ccinitialize(void) PL310_NWAYS, PL310_WAYSIZE, PL310_CACHE_SIZE); } +/**************************************************************************** + * Name: l2cc_get_linesize + * + * Description: + * Get L2CC-P310 L2 cache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * L2 cache linesize + * + ****************************************************************************/ + +uint32_t l2cc_get_linesize(void) +{ + return PL310_CACHE_LINE_SIZE; +} + /**************************************************************************** * Name: l2cc_enable * diff --git a/arch/arm/src/armv7-r/cp15_cacheops.c b/arch/arm/src/armv7-r/cp15_cacheops.c index d7ebf330f9..bc542fc35c 100644 --- a/arch/arm/src/armv7-r/cp15_cacheops.c +++ b/arch/arm/src/armv7-r/cp15_cacheops.c @@ -269,3 +269,8 @@ uint32_t cp15_cache_size(void) return sets * ways * line; } + +uint32_t cp15_cache_linesize(void) +{ + return cp15_cache_get_info(NULL, NULL); +} diff --git a/arch/arm/src/armv7-r/cp15_cacheops.h b/arch/arm/src/armv7-r/cp15_cacheops.h index af99104648..4561844fc2 100644 --- a/arch/arm/src/armv7-r/cp15_cacheops.h +++ b/arch/arm/src/armv7-r/cp15_cacheops.h @@ -1113,6 +1113,22 @@ void cp15_flush_dcache_all(void); uint32_t cp15_cache_size(void); +/**************************************************************************** + * Name: cp15_cache_linesize + * + * Description: + * Get cp15 cache linesize in byte + * + * Input Parameters: + * None + * + * Returned Value: + * Cache linesize in byte + * + ****************************************************************************/ + +uint32_t cp15_cache_linesize(void); + #undef EXTERN #ifdef __cplusplus } diff --git a/arch/arm/src/armv7-r/l2cc.h b/arch/arm/src/armv7-r/l2cc.h index 722ec6f88f..c0b659d534 100644 --- a/arch/arm/src/armv7-r/l2cc.h +++ b/arch/arm/src/armv7-r/l2cc.h @@ -70,6 +70,22 @@ extern "C" void arm_l2ccinitialize(void); #endif +/**************************************************************************** + * Name: l2cc_get_linesize + * + * Description: + * Get L2 cache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * L2 cache linesize + * + ****************************************************************************/ + +uint32_t l2cc_get_linesize(void); + /**************************************************************************** * Name: l2cc_enable * @@ -229,6 +245,7 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr); * compilation in one place. */ +# define l2cc_get_linesize() 0 # define l2cc_enable() # define l2cc_disable() # define l2cc_sync() diff --git a/arch/arm/src/armv8-m/arm_cache.c b/arch/arm/src/armv8-m/arm_cache.c index 543d4b9049..eab92de3ab 100644 --- a/arch/arm/src/armv8-m/arm_cache.c +++ b/arch/arm/src/armv8-m/arm_cache.c @@ -100,10 +100,68 @@ static inline uint32_t arm_clz(unsigned int value) } #endif +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_get_cache_linesize + * + * Description: + * Get cache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +#if defined(CONFIG_ARMV8M_ICACHE) || defined(CONFIG_ARMV8M_DCACHE) +static size_t up_get_cache_linesize(void) +{ + static uint32_t clsize; + + if (clsize == 0) + { + uint32_t ccsidr; + uint32_t sshift; + + ccsidr = getreg32(NVIC_CCSIDR); + sshift = CCSIDR_LSSHIFT(ccsidr) + 4; /* log2(cache-line-size-in-bytes) */ + clsize = 1 << sshift; + } + + return clsize; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: up_get_icache_linesize + * + * Description: + * Get icache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +#ifdef CONFIG_ARMV8M_ICACHE +size_t up_get_icache_linesize(void) +{ + return up_get_cache_linesize(); +} +#endif + /**************************************************************************** * Name: up_enable_icache * @@ -196,20 +254,10 @@ void up_disable_icache(void) #ifdef CONFIG_ARMV8M_ICACHE void up_invalidate_icache(uintptr_t start, uintptr_t end) { - uint32_t ccsidr; - uint32_t sshift; - uint32_t ssize; + uint32_t ssize = up_get_icache_linesize(); - /* Get the characteristics of the I-Cache */ - - ccsidr = getreg32(NVIC_CCSIDR); - sshift = CCSIDR_LSSHIFT(ccsidr) + 4; /* log2(cache-line-size-in-bytes) */ - - /* Invalidate the I-Cache containing this range of addresses */ - - ssize = (1 << sshift); - - /* Round down the start address to the nearest cache line boundary. + /* Invalidate the I-Cache containing this range of addresses. + * Round down the start address to the nearest cache line boundary. * * sshift = 5 : Offset to the beginning of the set field * (ssize - 1) = 0x007f : Mask of the set field @@ -279,6 +327,27 @@ void up_invalidate_icache_all(void) } #endif +/**************************************************************************** + * Name: up_get_dcache_linesize + * + * Description: + * Get dcache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +#ifdef CONFIG_ARMV8M_DCACHE +size_t up_get_dcache_linesize(void) +{ + return up_get_cache_linesize(); +} +#endif + /**************************************************************************** * Name: up_enable_dcache * @@ -459,20 +528,10 @@ void up_disable_dcache(void) #ifdef CONFIG_ARMV8M_DCACHE void up_invalidate_dcache(uintptr_t start, uintptr_t end) { - uint32_t ccsidr; - uint32_t sshift; - uint32_t ssize; + uint32_t ssize = up_get_dcache_linesize(); - /* Get the characteristics of the D-Cache */ - - ccsidr = getreg32(NVIC_CCSIDR); - sshift = CCSIDR_LSSHIFT(ccsidr) + 4; /* log2(cache-line-size-in-bytes) */ - - /* Invalidate the D-Cache containing this range of addresses */ - - ssize = (1 << sshift); - - /* Round down the start address to the nearest cache line boundary. + /* Invalidate the D-Cache containing this range of addresses + * Round down the start address to the nearest cache line boundary. * * sshift = 5 : Offset to the beginning of the set field * (ssize - 1) = 0x007f : Mask of the set field diff --git a/arch/arm64/src/common/arm64_cache.c b/arch/arm64/src/common/arm64_cache.c index ce0d3f7758..92a0dca7dc 100644 --- a/arch/arm64/src/common/arm64_cache.c +++ b/arch/arm64/src/common/arm64_cache.c @@ -266,6 +266,25 @@ static inline int arm64_dcache_all(int op) * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: up_get_icache_linesize + * + * Description: + * Get icache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +size_t up_get_icache_linesize(void) +{ + return g_dcache_line_size; +} + /**************************************************************************** * Name: up_invalidate_dcache * @@ -335,6 +354,25 @@ void up_invalidate_icache_all(void) __ic_ialluis(); } +/**************************************************************************** + * Name: up_get_dcache_linesize + * + * Description: + * Get dcache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +size_t up_get_dcache_linesize(void) +{ + return g_dcache_line_size; +} + /**************************************************************************** * Name: up_clean_dcache * diff --git a/arch/xtensa/src/common/xtensa_cache.c b/arch/xtensa/src/common/xtensa_cache.c index eee53b4739..455605e57f 100644 --- a/arch/xtensa/src/common/xtensa_cache.c +++ b/arch/xtensa/src/common/xtensa_cache.c @@ -40,6 +40,27 @@ * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: up_get_icache_linesize + * + * Description: + * Get icache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +#ifdef CONFIG_XTENSA_ICACHE +size_t up_get_icache_linesize(void) +{ + return XCHAL_ICACHE_LINESIZE; +} +#endif + /**************************************************************************** * Name: up_enable_icache * @@ -245,6 +266,27 @@ void up_unlock_icache_all(void) } #endif +/**************************************************************************** + * Name: up_get_dcache_linesize + * + * Description: + * Get dcache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +#ifdef CONFIG_XTENSA_DCACHE +size_t up_get_dcache_linesize(void) +{ + return XCHAL_DCACHE_LINESIZE; +} +#endif + /**************************************************************************** * Name: up_enable_dcache * diff --git a/include/nuttx/cache.h b/include/nuttx/cache.h index 139c0344af..7814165fd1 100644 --- a/include/nuttx/cache.h +++ b/include/nuttx/cache.h @@ -48,6 +48,26 @@ extern "C" * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: up_get_icache_linesize + * + * Description: + * Get icache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_ICACHE +size_t up_get_icache_linesize(void); +#else +# define up_get_icache_linesize() 0 +#endif + /**************************************************************************** * Name: up_enable_icache * @@ -197,6 +217,26 @@ void up_unlock_icache_all(void); # define up_unlock_icache_all() #endif +/**************************************************************************** + * Name: up_get_dcache_linesize + * + * Description: + * Get dcache linesize + * + * Input Parameters: + * None + * + * Returned Value: + * Cache line size + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_DCACHE +size_t up_get_dcache_linesize(void); +#else +# define up_get_dcache_linesize() 0 +#endif + /**************************************************************************** * Name: up_enable_dcache *