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_ */
|