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