LCOV - code coverage report
Current view: top level - zephyr/arch/arm64 - cache.h Hit Total Coverage
Test: new.info Lines: 0 5 0.0 %
Date: 2024-12-21 18:13:37

          Line data    Source code
       1           0 : /*
       2             :  * Copyright 2022 Carlo Caione <ccaione@baylibre.com>
       3             :  *
       4             :  * SPDX-License-Identifier: Apache-2.0
       5             :  */
       6             : #ifndef ZEPHYR_INCLUDE_ARCH_ARM64_CACHE_H_
       7             : #define ZEPHYR_INCLUDE_ARCH_ARM64_CACHE_H_
       8             : 
       9             : #ifndef _ASMLANGUAGE
      10             : 
      11             : #include <zephyr/types.h>
      12             : #include <zephyr/sys/util.h>
      13             : #include <zephyr/sys/barrier.h>
      14             : #include <zephyr/arch/cpu.h>
      15             : #include <errno.h>
      16             : 
      17             : #ifdef __cplusplus
      18             : extern "C" {
      19             : #endif
      20             : 
      21           0 : #define K_CACHE_WB              BIT(0)
      22           0 : #define K_CACHE_INVD            BIT(1)
      23           0 : #define K_CACHE_WB_INVD         (K_CACHE_WB | K_CACHE_INVD)
      24             : 
      25             : #if defined(CONFIG_DCACHE)
      26             : 
      27             : #define CTR_EL0_DMINLINE_SHIFT          16
      28             : #define CTR_EL0_DMINLINE_MASK           BIT_MASK(4)
      29             : #define CTR_EL0_CWG_SHIFT               24
      30             : #define CTR_EL0_CWG_MASK                BIT_MASK(4)
      31             : 
      32             : /* clidr_el1 */
      33             : #define CLIDR_EL1_LOC_SHIFT             24
      34             : #define CLIDR_EL1_LOC_MASK              BIT_MASK(3)
      35             : #define CLIDR_EL1_CTYPE_SHIFT(level)    ((level) * 3)
      36             : #define CLIDR_EL1_CTYPE_MASK            BIT_MASK(3)
      37             : 
      38             : /* ccsidr_el1 */
      39             : #define CCSIDR_EL1_LN_SZ_SHIFT          0
      40             : #define CCSIDR_EL1_LN_SZ_MASK           BIT_MASK(3)
      41             : #define CCSIDR_EL1_WAYS_SHIFT           3
      42             : #define CCSIDR_EL1_WAYS_MASK            BIT_MASK(10)
      43             : #define CCSIDR_EL1_SETS_SHIFT           13
      44             : #define CCSIDR_EL1_SETS_MASK            BIT_MASK(15)
      45             : 
      46             : #define dc_ops(op, val)                                                 \
      47             : ({                                                                      \
      48             :         __asm__ volatile ("dc " op ", %0" :: "r" (val) : "memory");     \
      49             : })
      50             : 
      51             : static size_t dcache_line_size;
      52             : 
      53             : static ALWAYS_INLINE size_t arch_dcache_line_size_get(void)
      54             : {
      55             :         uint64_t ctr_el0;
      56             :         uint32_t dminline;
      57             : 
      58             :         if (dcache_line_size) {
      59             :                 return dcache_line_size;
      60             :         }
      61             : 
      62             :         ctr_el0 = read_sysreg(CTR_EL0);
      63             : 
      64             :         dminline = (ctr_el0 >> CTR_EL0_DMINLINE_SHIFT) & CTR_EL0_DMINLINE_MASK;
      65             : 
      66             :         dcache_line_size = 4 << dminline;
      67             : 
      68             :         return dcache_line_size;
      69             : }
      70             : 
      71             : /*
      72             :  * operation for data cache by virtual address to PoC
      73             :  * ops:  K_CACHE_INVD: invalidate
      74             :  *       K_CACHE_WB: clean
      75             :  *       K_CACHE_WB_INVD: clean and invalidate
      76             :  */
      77             : static ALWAYS_INLINE int arm64_dcache_range(void *addr, size_t size, int op)
      78             : {
      79             :         size_t line_size;
      80             :         uintptr_t start_addr = (uintptr_t)addr;
      81             :         uintptr_t end_addr = start_addr + size;
      82             : 
      83             :         if (op != K_CACHE_INVD && op != K_CACHE_WB && op != K_CACHE_WB_INVD) {
      84             :                 return -ENOTSUP;
      85             :         }
      86             : 
      87             :         line_size = arch_dcache_line_size_get();
      88             : 
      89             :         /*
      90             :          * For the data cache invalidate operation, clean and invalidate
      91             :          * the partial cache lines at both ends of the given range to
      92             :          * prevent data corruption.
      93             :          *
      94             :          * For example (assume cache line size is 64 bytes):
      95             :          * There are 2 consecutive 32-byte buffers, which can be cached in
      96             :          * one line like below.
      97             :          *                      +------------------+------------------+
      98             :          *       Cache line:    | buffer 0 (dirty) |     buffer 1     |
      99             :          *                      +------------------+------------------+
     100             :          * For the start address not aligned case, when invalidate the
     101             :          * buffer 1, the full cache line will be invalidated, if the buffer
     102             :          * 0 is dirty, its data will be lost.
     103             :          * The same logic applies to the not aligned end address.
     104             :          */
     105             :         if (op == K_CACHE_INVD) {
     106             :                 if (end_addr & (line_size - 1)) {
     107             :                         end_addr &= ~(line_size - 1);
     108             :                         dc_ops("civac", end_addr);
     109             :                 }
     110             : 
     111             :                 if (start_addr & (line_size - 1)) {
     112             :                         start_addr &= ~(line_size - 1);
     113             :                         if (start_addr == end_addr) {
     114             :                                 goto done;
     115             :                         }
     116             :                         dc_ops("civac", start_addr);
     117             :                         start_addr += line_size;
     118             :                 }
     119             :         }
     120             : 
     121             :         /* Align address to line size */
     122             :         start_addr &= ~(line_size - 1);
     123             : 
     124             :         while (start_addr < end_addr) {
     125             :                 if (op == K_CACHE_INVD) {
     126             :                         dc_ops("ivac", start_addr);
     127             :                 } else if (op == K_CACHE_WB) {
     128             :                         dc_ops("cvac", start_addr);
     129             :                 } else if (op == K_CACHE_WB_INVD) {
     130             :                         dc_ops("civac", start_addr);
     131             :                 }
     132             : 
     133             :                 start_addr += line_size;
     134             :         }
     135             : 
     136             : done:
     137             :         barrier_dsync_fence_full();
     138             : 
     139             :         return 0;
     140             : }
     141             : 
     142             : static ALWAYS_INLINE int arch_dcache_flush_all(void)
     143             : {
     144             :         return -ENOTSUP;
     145             : }
     146             : 
     147             : static ALWAYS_INLINE int arch_dcache_invd_all(void)
     148             : {
     149             :         return -ENOTSUP;
     150             : }
     151             : 
     152             : static ALWAYS_INLINE int arch_dcache_flush_and_invd_all(void)
     153             : {
     154             :         return -ENOTSUP;
     155             : }
     156             : 
     157             : static ALWAYS_INLINE int arch_dcache_flush_range(void *addr, size_t size)
     158             : {
     159             :         return arm64_dcache_range(addr, size, K_CACHE_WB);
     160             : }
     161             : 
     162             : static ALWAYS_INLINE int arch_dcache_invd_range(void *addr, size_t size)
     163             : {
     164             :         return arm64_dcache_range(addr, size, K_CACHE_INVD);
     165             : }
     166             : 
     167             : static ALWAYS_INLINE int arch_dcache_flush_and_invd_range(void *addr, size_t size)
     168             : {
     169             :         return arm64_dcache_range(addr, size, K_CACHE_WB_INVD);
     170             : }
     171             : 
     172             : static ALWAYS_INLINE void arch_dcache_enable(void)
     173             : {
     174             :         /* nothing */
     175             : }
     176             : 
     177             : static ALWAYS_INLINE void arch_dcache_disable(void)
     178             : {
     179             :         /* nothing */
     180             : }
     181             : 
     182             : #endif /* CONFIG_DCACHE */
     183             : 
     184             : #if defined(CONFIG_ICACHE)
     185             : 
     186             : static ALWAYS_INLINE size_t arch_icache_line_size_get(void)
     187             : {
     188             :         return -ENOTSUP;
     189             : }
     190             : 
     191             : static ALWAYS_INLINE int arch_icache_flush_all(void)
     192             : {
     193             :         return -ENOTSUP;
     194             : }
     195             : 
     196             : static ALWAYS_INLINE int arch_icache_invd_all(void)
     197             : {
     198             :         return -ENOTSUP;
     199             : }
     200             : 
     201             : static ALWAYS_INLINE int arch_icache_flush_and_invd_all(void)
     202             : {
     203             :         return -ENOTSUP;
     204             : }
     205             : 
     206             : static ALWAYS_INLINE int arch_icache_flush_range(void *addr, size_t size)
     207             : {
     208             :         ARG_UNUSED(addr);
     209             :         ARG_UNUSED(size);
     210             :         return -ENOTSUP;
     211             : }
     212             : 
     213             : static ALWAYS_INLINE int arch_icache_invd_range(void *addr, size_t size)
     214             : {
     215             :         ARG_UNUSED(addr);
     216             :         ARG_UNUSED(size);
     217             :         return -ENOTSUP;
     218             : }
     219             : 
     220             : static ALWAYS_INLINE int arch_icache_flush_and_invd_range(void *addr, size_t size)
     221             : {
     222             :         ARG_UNUSED(addr);
     223             :         ARG_UNUSED(size);
     224             :         return -ENOTSUP;
     225             : }
     226             : 
     227             : static ALWAYS_INLINE void arch_icache_enable(void)
     228             : {
     229             :         /* nothing */
     230             : }
     231             : 
     232             : static ALWAYS_INLINE void arch_icache_disable(void)
     233             : {
     234             :         /* nothing */
     235             : }
     236             : 
     237             : #endif /* CONFIG_ICACHE */
     238             : 
     239           0 : static ALWAYS_INLINE void arch_cache_init(void)
     240             : {
     241             : }
     242             : 
     243             : #ifdef __cplusplus
     244             : }
     245             : #endif
     246             : 
     247             : #endif /* _ASMLANGUAGE */
     248             : 
     249             : #endif /* ZEPHYR_INCLUDE_ARCH_ARM64_CACHE_H_ */

Generated by: LCOV version 1.14