Skip to content

Commit

Permalink
cache: introduce incoherent cache interface
Browse files Browse the repository at this point in the history
Introduce a set of cache APIs used on architectures with cache incoherency.

Signed-off-by: Anas Nashif <[email protected]>
  • Loading branch information
nashif committed Feb 3, 2024
1 parent 211ddf1 commit 9183cea
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 0 deletions.
18 changes: 18 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,13 @@ config CPU_HAS_DCACHE
help
This hidden configuration should be selected when the CPU has a d-cache.

config CPU_CACHE_INCOHERENT
bool
help
This hidden configuration should be selected when the CPU has
incoherent cache. This applies to intra-CPU multiprocessing
incoherence and makes only sense when MP_NUM_CPUS > 1.

config CPU_HAS_ICACHE
bool
help
Expand Down Expand Up @@ -925,6 +932,17 @@ config ICACHE
help
This option enables the support for the instruction cache (i-cache).

config CACHE_DOUBLEMAP
bool "Cache double-mapping support"
depends on CPU_CACHE_INCOHERENT
default y
help
Double-mapping behavior where a pointer can be cheaply converted to
point to the same cached/uncached memory at different locations.

This applies to intra-CPU multiprocessing incoherence and makes only
sense when MP_NUM_CPUS > 1.

config CACHE_MANAGEMENT
bool "Cache management features"
depends on DCACHE || ICACHE
Expand Down
1 change: 1 addition & 0 deletions doc/zephyr.doxyfile.in
Original file line number Diff line number Diff line change
Expand Up @@ -2399,6 +2399,7 @@ PREDEFINED = __DOXYGEN__ \
XEN_GUEST_HANDLE_64(x)= \
_LINKER \
__deprecated= \
__sparse_cache= \
__packed= \
__aligned(x)= \
__attribute_nonnull(...)= \
Expand Down
14 changes: 14 additions & 0 deletions include/zephyr/arch/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,20 @@ size_t arch_icache_line_size_get(void);

#endif /* CONFIG_ICACHE || __DOXYGEN__ */

#if CONFIG_CACHE_DOUBLEMAP || __DOXYGEN__
bool arch_cache_is_ptr_cached(void *ptr);
#define cache_is_ptr_cached(ptr) arch_cache_is_ptr_cached(ptr)

bool arch_cache_is_ptr_uncached(void *ptr);
#define cache_is_ptr_uncached(ptr) arch_cache_is_ptr_uncached(ptr)

void __sparse_cache *arch_cache_cached_ptr_get(void *ptr);
#define cache_cached_ptr(ptr) arch_cache_cached_ptr_get(ptr)

void *arch_cache_uncached_ptr_get(void __sparse_cache *ptr);
#define cache_uncached_ptr(ptr) arch_cache_uncached_ptr_get(ptr)
#endif /* CONFIG_CACHE_DOUBLEMAP */

/**
* @}
*/
Expand Down
102 changes: 102 additions & 0 deletions include/zephyr/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include <zephyr/kernel.h>
#include <zephyr/arch/cpu.h>
#include <zephyr/debug/sparse.h>

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -441,6 +442,107 @@ static ALWAYS_INLINE size_t sys_cache_instr_line_size_get(void)
#endif
}

/**
* @brief Test if a pointer is in cached region.
*
* Some hardware may map the same physical memory twice
* so that it can be seen in both (incoherent) cached mappings
* and a coherent "shared" area. This tests if a particular
* pointer is within the cached, coherent area.
*
* @param ptr Pointer
*
* @retval True if pointer is in cached region.
* @retval False if pointer is not in cached region.
*/
static ALWAYS_INLINE bool sys_cache_is_ptr_cached(void *ptr)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_CACHE_DOUBLEMAP)
return cache_is_ptr_cached(ptr);
#else
ARG_UNUSED(ptr);

return false;
#endif
}

/**
* @brief Test if a pointer is in un-cached region.
*
* Some hardware may map the same physical memory twice
* so that it can be seen in both (incoherent) cached mappings
* and a coherent "shared" area. This tests if a particular
* pointer is within the un-cached, incoherent area.
*
* @param ptr Pointer
*
* @retval True if pointer is not in cached region.
* @retval False if pointer is in cached region.
*/
static ALWAYS_INLINE bool sys_cache_is_ptr_uncached(void *ptr)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_CACHE_DOUBLEMAP)
return cache_is_ptr_uncached(ptr);
#else
ARG_UNUSED(ptr);

return false;
#endif
}

/**
* @brief Return cached pointer to a RAM address
*
* This function takes a pointer to any addressable object (either in
* cacheable memory or not) and returns a pointer that can be used to
* refer to the same memory through the L1 data cache. Data read
* through the resulting pointer will reflect locally cached values on
* the current CPU if they exist, and writes will go first into the
* cache and be written back later.
*
* @note This API returns the same pointer if CONFIG_CACHE_DOUBLEMAP is not
* enabled.
*
* @see arch_uncached_ptr()
*
* @param ptr A pointer to a valid C object
* @return A pointer to the same object via the L1 dcache
*/
static ALWAYS_INLINE void __sparse_cache *sys_cache_cached_ptr_get(void *ptr)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_CACHE_DOUBLEMAP)
return cache_cached_ptr(ptr);
#else
return (__sparse_force void __sparse_cache *)ptr;
#endif
}

/**
* @brief Return uncached pointer to a RAM address
*
* This function takes a pointer to any addressable object (either in
* cacheable memory or not) and returns a pointer that can be used to
* refer to the same memory while bypassing the L1 data cache. Data
* in the L1 cache will not be inspected nor modified by the access.
*
* @note This API returns the same pointer if CONFIG_CACHE_DOUBLEMAP is not
* enabled.
*
* @see arch_cached_ptr()
*
* @param ptr A pointer to a valid C object
* @return A pointer to the same object bypassing the L1 dcache
*/
static ALWAYS_INLINE void *sys_cache_uncached_ptr_get(void __sparse_cache *ptr)
{
#if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_CACHE_DOUBLEMAP)
return cache_uncached_ptr(ptr);
#else
return (__sparse_force void *)ptr;
#endif
}


#ifdef CONFIG_LIBMETAL
static ALWAYS_INLINE void sys_cache_flush(void *addr, size_t size)
{
Expand Down

0 comments on commit 9183cea

Please sign in to comment.