LCOV - code coverage report
Current view: top level - zephyr - cache.h Hit Total Coverage
Test: new.info Lines: 23 23 100.0 %
Date: 2024-12-22 00:14:23

          Line data    Source code
       1           1 : /*
       2             :  * Copyright (c) 2015 Wind River Systems, Inc.
       3             :  * Copyright (c) 2022 Carlo Caione <ccaione@baylibre.com>
       4             :  *
       5             :  * SPDX-License-Identifier: Apache-2.0
       6             :  */
       7             : 
       8             : #ifndef ZEPHYR_INCLUDE_CACHE_H_
       9             : #define ZEPHYR_INCLUDE_CACHE_H_
      10             : 
      11             : /**
      12             :  * @file
      13             :  * @brief cache API interface
      14             :  */
      15             : 
      16             : #include <zephyr/kernel.h>
      17             : #include <zephyr/arch/cpu.h>
      18             : #include <zephyr/debug/sparse.h>
      19             : 
      20             : #ifdef __cplusplus
      21             : extern "C" {
      22             : #endif
      23             : 
      24             : #if defined(CONFIG_EXTERNAL_CACHE)
      25             : #include <zephyr/drivers/cache.h>
      26             : 
      27             : #elif defined(CONFIG_ARCH_CACHE)
      28             : #include <zephyr/arch/cache.h>
      29             : 
      30             : #endif
      31             : 
      32             : /**
      33             :  * @defgroup cache_interface Cache Interface
      34             :  * @ingroup os_services
      35             :  * @{
      36             :  */
      37             : 
      38             : /**
      39             :  * @cond INTERNAL_HIDDEN
      40             :  *
      41             :  */
      42             : 
      43             : #define _CPU DT_PATH(cpus, cpu_0)
      44             : 
      45             : /** @endcond */
      46             : 
      47             : /**
      48             :  * @brief Enable the d-cache
      49             :  *
      50             :  * Enable the data cache
      51             :  *
      52             :  */
      53           1 : static ALWAYS_INLINE void sys_cache_data_enable(void)
      54             : {
      55             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
      56             :         cache_data_enable();
      57             : #endif
      58             : }
      59             : 
      60             : /**
      61             :  * @brief Disable the d-cache
      62             :  *
      63             :  * Disable the data cache
      64             :  *
      65             :  */
      66           1 : static ALWAYS_INLINE void sys_cache_data_disable(void)
      67             : {
      68             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
      69             :         cache_data_disable();
      70             : #endif
      71             : }
      72             : 
      73             : /**
      74             :  * @brief Enable the i-cache
      75             :  *
      76             :  * Enable the instruction cache
      77             :  *
      78             :  */
      79           1 : static ALWAYS_INLINE void sys_cache_instr_enable(void)
      80             : {
      81             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
      82             :         cache_instr_enable();
      83             : #endif
      84             : }
      85             : 
      86             : /**
      87             :  * @brief Disable the i-cache
      88             :  *
      89             :  * Disable the instruction cache
      90             :  *
      91             :  */
      92           1 : static ALWAYS_INLINE void sys_cache_instr_disable(void)
      93             : {
      94             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
      95             :         cache_instr_disable();
      96             : #endif
      97             : }
      98             : 
      99             : /**
     100             :  * @brief Flush the d-cache
     101             :  *
     102             :  * Flush the whole data cache.
     103             :  *
     104             :  * @retval 0 If succeeded.
     105             :  * @retval -ENOTSUP If not supported.
     106             :  * @retval -errno Negative errno for other failures.
     107             :  */
     108           1 : static ALWAYS_INLINE int sys_cache_data_flush_all(void)
     109             : {
     110             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
     111             :         return cache_data_flush_all();
     112             : #endif
     113             :         return -ENOTSUP;
     114             : }
     115             : 
     116             : /**
     117             :  * @brief Flush the i-cache
     118             :  *
     119             :  * Flush the whole instruction cache.
     120             :  *
     121             :  * @retval 0 If succeeded.
     122             :  * @retval -ENOTSUP If not supported.
     123             :  * @retval -errno Negative errno for other failures.
     124             :  */
     125           1 : static ALWAYS_INLINE int sys_cache_instr_flush_all(void)
     126             : {
     127             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
     128             :         return cache_instr_flush_all();
     129             : #endif
     130             :         return -ENOTSUP;
     131             : }
     132             : 
     133             : /**
     134             :  * @brief Invalidate the d-cache
     135             :  *
     136             :  * Invalidate the whole data cache.
     137             :  *
     138             :  * @retval 0 If succeeded.
     139             :  * @retval -ENOTSUP If not supported.
     140             :  * @retval -errno Negative errno for other failures.
     141             :  */
     142           1 : static ALWAYS_INLINE int sys_cache_data_invd_all(void)
     143             : {
     144             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
     145             :         return cache_data_invd_all();
     146             : #endif
     147             :         return -ENOTSUP;
     148             : }
     149             : 
     150             : /**
     151             :  * @brief Invalidate the i-cache
     152             :  *
     153             :  * Invalidate the whole instruction cache.
     154             :  *
     155             :  * @retval 0 If succeeded.
     156             :  * @retval -ENOTSUP If not supported.
     157             :  * @retval -errno Negative errno for other failures.
     158             :  */
     159           1 : static ALWAYS_INLINE int sys_cache_instr_invd_all(void)
     160             : {
     161             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
     162             :         return cache_instr_invd_all();
     163             : #endif
     164             :         return -ENOTSUP;
     165             : }
     166             : 
     167             : /**
     168             :  * @brief Flush and Invalidate the d-cache
     169             :  *
     170             :  * Flush and Invalidate the whole data cache.
     171             :  *
     172             :  * @retval 0 If succeeded.
     173             :  * @retval -ENOTSUP If not supported.
     174             :  * @retval -errno Negative errno for other failures.
     175             :  */
     176           1 : static ALWAYS_INLINE int sys_cache_data_flush_and_invd_all(void)
     177             : {
     178             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
     179             :         return cache_data_flush_and_invd_all();
     180             : #endif
     181             :         return -ENOTSUP;
     182             : }
     183             : 
     184             : /**
     185             :  * @brief Flush and Invalidate the i-cache
     186             :  *
     187             :  * Flush and Invalidate the whole instruction cache.
     188             :  *
     189             :  * @retval 0 If succeeded.
     190             :  * @retval -ENOTSUP If not supported.
     191             :  * @retval -errno Negative errno for other failures.
     192             :  */
     193           1 : static ALWAYS_INLINE int sys_cache_instr_flush_and_invd_all(void)
     194             : {
     195             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
     196             :         return cache_instr_flush_and_invd_all();
     197             : #endif
     198             :         return -ENOTSUP;
     199             : }
     200             : 
     201             : /**
     202             :  * @brief Flush an address range in the d-cache
     203             :  *
     204             :  * Flush the specified address range of the data cache.
     205             :  *
     206             :  * @note the cache operations act on cache line. When multiple data structures
     207             :  *       share the same cache line being flushed, all the portions of the
     208             :  *       data structures sharing the same line will be flushed. This is usually
     209             :  *       not a problem because writing back is a non-destructive process that
     210             :  *       could be triggered by hardware at any time, so having an aligned
     211             :  *       @p addr or a padded @p size is not strictly necessary.
     212             :  *
     213             :  * @param addr Starting address to flush.
     214             :  * @param size Range size.
     215             :  *
     216             :  * @retval 0 If succeeded.
     217             :  * @retval -ENOTSUP If not supported.
     218             :  * @retval -errno Negative errno for other failures.
     219             :  */
     220           1 : __syscall_always_inline int sys_cache_data_flush_range(void *addr, size_t size);
     221             : 
     222             : static ALWAYS_INLINE int z_impl_sys_cache_data_flush_range(void *addr, size_t size)
     223             : {
     224             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
     225             :         return cache_data_flush_range(addr, size);
     226             : #endif
     227             :         ARG_UNUSED(addr);
     228             :         ARG_UNUSED(size);
     229             : 
     230             :         return -ENOTSUP;
     231             : }
     232             : 
     233             : /**
     234             :  * @brief Flush an address range in the i-cache
     235             :  *
     236             :  * Flush the specified address range of the instruction cache.
     237             :  *
     238             :  * @note the cache operations act on cache line. When multiple data structures
     239             :  *       share the same cache line being flushed, all the portions of the
     240             :  *       data structures sharing the same line will be flushed. This is usually
     241             :  *       not a problem because writing back is a non-destructive process that
     242             :  *       could be triggered by hardware at any time, so having an aligned
     243             :  *       @p addr or a padded @p size is not strictly necessary.
     244             :  *
     245             :  * @param addr Starting address to flush.
     246             :  * @param size Range size.
     247             :  *
     248             :  * @retval 0 If succeeded.
     249             :  * @retval -ENOTSUP If not supported.
     250             :  * @retval -errno Negative errno for other failures.
     251             :  */
     252           1 : static ALWAYS_INLINE int sys_cache_instr_flush_range(void *addr, size_t size)
     253             : {
     254             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
     255             :         return cache_instr_flush_range(addr, size);
     256             : #endif
     257             :         ARG_UNUSED(addr);
     258             :         ARG_UNUSED(size);
     259             : 
     260             :         return -ENOTSUP;
     261             : }
     262             : 
     263             : /**
     264             :  * @brief Invalidate an address range in the d-cache
     265             :  *
     266             :  * Invalidate the specified address range of the data cache.
     267             :  *
     268             :  * @note the cache operations act on cache line. When multiple data structures
     269             :  *       share the same cache line being invalidated, all the portions of the
     270             :  *       non-read-only data structures sharing the same line will be
     271             :  *       invalidated as well. This is a destructive process that could lead to
     272             :  *       data loss and/or corruption. When @p addr is not aligned to the cache
     273             :  *       line and/or @p size is not a multiple of the cache line size the
     274             :  *       behaviour is undefined.
     275             :  *
     276             :  * @param addr Starting address to invalidate.
     277             :  * @param size Range size.
     278             :  *
     279             :  * @retval 0 If succeeded.
     280             :  * @retval -ENOTSUP If not supported.
     281             :  * @retval -errno Negative errno for other failures.
     282             :  */
     283           1 : __syscall_always_inline int sys_cache_data_invd_range(void *addr, size_t size);
     284             : 
     285             : static ALWAYS_INLINE int z_impl_sys_cache_data_invd_range(void *addr, size_t size)
     286             : {
     287             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
     288             :         return cache_data_invd_range(addr, size);
     289             : #endif
     290             :         ARG_UNUSED(addr);
     291             :         ARG_UNUSED(size);
     292             : 
     293             :         return -ENOTSUP;
     294             : }
     295             : 
     296             : /**
     297             :  * @brief Invalidate an address range in the i-cache
     298             :  *
     299             :  * Invalidate the specified address range of the instruction cache.
     300             :  *
     301             :  * @note the cache operations act on cache line. When multiple data structures
     302             :  *       share the same cache line being invalidated, all the portions of the
     303             :  *       non-read-only data structures sharing the same line will be
     304             :  *       invalidated as well. This is a destructive process that could lead to
     305             :  *       data loss and/or corruption. When @p addr is not aligned to the cache
     306             :  *       line and/or @p size is not a multiple of the cache line size the
     307             :  *       behaviour is undefined.
     308             :  *
     309             :  * @param addr Starting address to invalidate.
     310             :  * @param size Range size.
     311             :  *
     312             :  * @retval 0 If succeeded.
     313             :  * @retval -ENOTSUP If not supported.
     314             :  * @retval -errno Negative errno for other failures.
     315             :  */
     316           1 : static ALWAYS_INLINE int sys_cache_instr_invd_range(void *addr, size_t size)
     317             : {
     318             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
     319             :         return cache_instr_invd_range(addr, size);
     320             : #endif
     321             :         ARG_UNUSED(addr);
     322             :         ARG_UNUSED(size);
     323             : 
     324             :         return -ENOTSUP;
     325             : }
     326             : 
     327             : /**
     328             :  * @brief Flush and Invalidate an address range in the d-cache
     329             :  *
     330             :  * Flush and Invalidate the specified address range of the data cache.
     331             :  *
     332             :  * @note the cache operations act on cache line. When multiple data structures
     333             :  *       share the same cache line being flushed, all the portions of the
     334             :  *       data structures sharing the same line will be flushed before being
     335             :  *       invalidated. This is usually not a problem because writing back is a
     336             :  *       non-destructive process that could be triggered by hardware at any
     337             :  *       time, so having an aligned @p addr or a padded @p size is not strictly
     338             :  *       necessary.
     339             :  *
     340             :  * @param addr Starting address to flush and invalidate.
     341             :  * @param size Range size.
     342             :  *
     343             :  * @retval 0 If succeeded.
     344             :  * @retval -ENOTSUP If not supported.
     345             :  * @retval -errno Negative errno for other failures.
     346             :  */
     347           1 : __syscall_always_inline int sys_cache_data_flush_and_invd_range(void *addr, size_t size);
     348             : 
     349             : static ALWAYS_INLINE int z_impl_sys_cache_data_flush_and_invd_range(void *addr, size_t size)
     350             : {
     351             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
     352             :         return cache_data_flush_and_invd_range(addr, size);
     353             : #endif
     354             :         ARG_UNUSED(addr);
     355             :         ARG_UNUSED(size);
     356             : 
     357             :         return -ENOTSUP;
     358             : }
     359             : 
     360             : /**
     361             :  * @brief Flush and Invalidate an address range in the i-cache
     362             :  *
     363             :  * Flush and Invalidate the specified address range of the instruction cache.
     364             :  *
     365             :  * @note the cache operations act on cache line. When multiple data structures
     366             :  *       share the same cache line being flushed, all the portions of the
     367             :  *       data structures sharing the same line will be flushed before being
     368             :  *       invalidated. This is usually not a problem because writing back is a
     369             :  *       non-destructive process that could be triggered by hardware at any
     370             :  *       time, so having an aligned @p addr or a padded @p size is not strictly
     371             :  *       necessary.
     372             :  *
     373             :  * @param addr Starting address to flush and invalidate.
     374             :  * @param size Range size.
     375             :  *
     376             :  * @retval 0 If succeeded.
     377             :  * @retval -ENOTSUP If not supported.
     378             :  * @retval -errno Negative errno for other failures.
     379             :  */
     380           1 : static ALWAYS_INLINE int sys_cache_instr_flush_and_invd_range(void *addr, size_t size)
     381             : {
     382             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
     383             :         return cache_instr_flush_and_invd_range(addr, size);
     384             : #endif
     385             :         ARG_UNUSED(addr);
     386             :         ARG_UNUSED(size);
     387             : 
     388             :         return -ENOTSUP;
     389             : }
     390             : 
     391             : /**
     392             :  *
     393             :  * @brief Get the d-cache line size.
     394             :  *
     395             :  * The API is provided to get the data cache line.
     396             :  *
     397             :  * The cache line size is calculated (in order of priority):
     398             :  *
     399             :  * - At run-time when @kconfig{CONFIG_DCACHE_LINE_SIZE_DETECT} is set.
     400             :  * - At compile time using the value set in @kconfig{CONFIG_DCACHE_LINE_SIZE}.
     401             :  * - At compile time using the `d-cache-line-size` CPU0 property of the DT.
     402             :  * - 0 otherwise
     403             :  *
     404             :  * @retval size Size of the d-cache line.
     405             :  * @retval 0 If the d-cache is not enabled.
     406             :  */
     407           1 : static ALWAYS_INLINE size_t sys_cache_data_line_size_get(void)
     408             : {
     409             : #ifdef CONFIG_DCACHE_LINE_SIZE_DETECT
     410             :         return cache_data_line_size_get();
     411             : #elif (CONFIG_DCACHE_LINE_SIZE != 0)
     412             :         return CONFIG_DCACHE_LINE_SIZE;
     413             : #else
     414             :         return DT_PROP_OR(_CPU, d_cache_line_size, 0);
     415             : #endif
     416             : }
     417             : 
     418             : /**
     419             :  *
     420             :  * @brief Get the i-cache line size.
     421             :  *
     422             :  * The API is provided to get the instruction cache line.
     423             :  *
     424             :  * The cache line size is calculated (in order of priority):
     425             :  *
     426             :  * - At run-time when @kconfig{CONFIG_ICACHE_LINE_SIZE_DETECT} is set.
     427             :  * - At compile time using the value set in @kconfig{CONFIG_ICACHE_LINE_SIZE}.
     428             :  * - At compile time using the `i-cache-line-size` CPU0 property of the DT.
     429             :  * - 0 otherwise
     430             :  *
     431             :  * @retval size Size of the d-cache line.
     432             :  * @retval 0 If the d-cache is not enabled.
     433             :  */
     434           1 : static ALWAYS_INLINE size_t sys_cache_instr_line_size_get(void)
     435             : {
     436             : #ifdef CONFIG_ICACHE_LINE_SIZE_DETECT
     437             :         return cache_instr_line_size_get();
     438             : #elif (CONFIG_ICACHE_LINE_SIZE != 0)
     439             :         return CONFIG_ICACHE_LINE_SIZE;
     440             : #else
     441             :         return DT_PROP_OR(_CPU, i_cache_line_size, 0);
     442             : #endif
     443             : }
     444             : 
     445             : /**
     446             :  * @brief Test if a pointer is in cached region.
     447             :  *
     448             :  * Some hardware may map the same physical memory twice
     449             :  * so that it can be seen in both (incoherent) cached mappings
     450             :  * and a coherent "shared" area. This tests if a particular
     451             :  * pointer is within the cached, coherent area.
     452             :  *
     453             :  * @param ptr Pointer
     454             :  *
     455             :  * @retval True if pointer is in cached region.
     456             :  * @retval False if pointer is not in cached region.
     457             :  */
     458           1 : static ALWAYS_INLINE bool sys_cache_is_ptr_cached(void *ptr)
     459             : {
     460             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_CACHE_DOUBLEMAP)
     461             :         return cache_is_ptr_cached(ptr);
     462             : #else
     463             :         ARG_UNUSED(ptr);
     464             : 
     465             :         return false;
     466             : #endif
     467             : }
     468             : 
     469             : /**
     470             :  * @brief Test if a pointer is in un-cached region.
     471             :  *
     472             :  * Some hardware may map the same physical memory twice
     473             :  * so that it can be seen in both (incoherent) cached mappings
     474             :  * and a coherent "shared" area. This tests if a particular
     475             :  * pointer is within the un-cached, incoherent area.
     476             :  *
     477             :  * @param ptr Pointer
     478             :  *
     479             :  * @retval True if pointer is not in cached region.
     480             :  * @retval False if pointer is in cached region.
     481             :  */
     482           1 : static ALWAYS_INLINE bool sys_cache_is_ptr_uncached(void *ptr)
     483             : {
     484             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_CACHE_DOUBLEMAP)
     485             :         return cache_is_ptr_uncached(ptr);
     486             : #else
     487             :         ARG_UNUSED(ptr);
     488             : 
     489             :         return false;
     490             : #endif
     491             : }
     492             : 
     493             : /**
     494             :  * @brief Return cached pointer to a RAM address
     495             :  *
     496             :  * This function takes a pointer to any addressable object (either in
     497             :  * cacheable memory or not) and returns a pointer that can be used to
     498             :  * refer to the same memory through the L1 data cache.  Data read
     499             :  * through the resulting pointer will reflect locally cached values on
     500             :  * the current CPU if they exist, and writes will go first into the
     501             :  * cache and be written back later.
     502             :  *
     503             :  * @note This API returns the same pointer if CONFIG_CACHE_DOUBLEMAP is not
     504             :  * enabled.
     505             :  *
     506             :  * @see arch_uncached_ptr()
     507             :  *
     508             :  * @param ptr A pointer to a valid C object
     509             :  * @return A pointer to the same object via the L1 dcache
     510             :  */
     511           1 : static ALWAYS_INLINE void __sparse_cache *sys_cache_cached_ptr_get(void *ptr)
     512             : {
     513             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_CACHE_DOUBLEMAP)
     514             :         return cache_cached_ptr(ptr);
     515             : #else
     516             :         return (__sparse_force void __sparse_cache *)ptr;
     517             : #endif
     518             : }
     519             : 
     520             : /**
     521             :  * @brief Return uncached pointer to a RAM address
     522             :  *
     523             :  * This function takes a pointer to any addressable object (either in
     524             :  * cacheable memory or not) and returns a pointer that can be used to
     525             :  * refer to the same memory while bypassing the L1 data cache.  Data
     526             :  * in the L1 cache will not be inspected nor modified by the access.
     527             :  *
     528             :  * @note This API returns the same pointer if CONFIG_CACHE_DOUBLEMAP is not
     529             :  * enabled.
     530             :  *
     531             :  * @see arch_cached_ptr()
     532             :  *
     533             :  * @param ptr A pointer to a valid C object
     534             :  * @return A pointer to the same object bypassing the L1 dcache
     535             :  */
     536           1 : static ALWAYS_INLINE void *sys_cache_uncached_ptr_get(void __sparse_cache *ptr)
     537             : {
     538             : #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_CACHE_DOUBLEMAP)
     539             :         return cache_uncached_ptr(ptr);
     540             : #else
     541             :         return (__sparse_force void *)ptr;
     542             : #endif
     543             : }
     544             : 
     545             : 
     546             : #ifdef CONFIG_LIBMETAL
     547             : static ALWAYS_INLINE void sys_cache_flush(void *addr, size_t size)
     548             : {
     549             :         sys_cache_data_flush_range(addr, size);
     550             : }
     551             : #endif
     552             : 
     553             : #include <zephyr/syscalls/cache.h>
     554             : #ifdef __cplusplus
     555             : }
     556             : #endif
     557             : 
     558             : /**
     559             :  * @}
     560             :  */
     561             : 
     562             : #endif /* ZEPHYR_INCLUDE_CACHE_H_ */

Generated by: LCOV version 1.14