RTEMS 7.0-rc1
Loading...
Searching...
No Matches
cacheimpl.h
Go to the documentation of this file.
1
10/*
11 * Copyright (C) 2014, 2018 embedded brains GmbH & Co. KG
12 * Copyright (C) 1989, 1999 On-Line Applications Research Corporation (OAR)
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
124#include <rtems.h>
125
126#include <sys/param.h>
127
128#if defined(RTEMS_SMP) && defined(CPU_CACHE_NO_INSTRUCTION_CACHE_SNOOPING)
129#include <rtems/score/smpimpl.h>
131#endif
132
133#if CPU_DATA_CACHE_ALIGNMENT > CPU_CACHE_LINE_BYTES
134#error "CPU_DATA_CACHE_ALIGNMENT is greater than CPU_CACHE_LINE_BYTES"
135#endif
136
137#if CPU_INSTRUCTION_CACHE_ALIGNMENT > CPU_CACHE_LINE_BYTES
138#error "CPU_INSTRUCTION_CACHE_ALIGNMENT is greater than CPU_CACHE_LINE_BYTES"
139#endif
140
149/*
150 * THESE FUNCTIONS ONLY HAVE BODIES IF WE HAVE A DATA CACHE
151 */
152
153/*
154 * This function is called to flush the data cache by performing cache
155 * copybacks. It must determine how many cache lines need to be copied
156 * back and then perform the copybacks.
157 */
158void
159rtems_cache_flush_multiple_data_lines( const void * d_addr, size_t n_bytes )
160{
161#if defined(CPU_DATA_CACHE_ALIGNMENT)
162#if defined(CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS)
163 _CPU_cache_flush_data_range( d_addr, n_bytes );
164#else
165 const void * final_address;
166
167 /*
168 * Set d_addr to the beginning of the cache line; final_address indicates
169 * the last address_t which needs to be pushed. Increment d_addr and push
170 * the resulting line until final_address is passed.
171 */
172
173 if( n_bytes == 0 )
174 /* Do nothing if number of bytes to flush is zero */
175 return;
176
177 final_address = (void *)((size_t)d_addr + n_bytes - 1);
178 d_addr = (void *)((size_t)d_addr & ~(CPU_DATA_CACHE_ALIGNMENT - 1));
179 while( d_addr <= final_address ) {
180 _CPU_cache_flush_1_data_line( d_addr );
181 d_addr = (void *)((size_t)d_addr + CPU_DATA_CACHE_ALIGNMENT);
182 }
183#endif
184#else
185 (void) d_addr;
186 (void) n_bytes;
187#endif
188}
189
190/*
191 * This function is responsible for performing a data cache invalidate.
192 * It must determine how many cache lines need to be invalidated and then
193 * perform the invalidations.
194 */
195void
196rtems_cache_invalidate_multiple_data_lines( const void * d_addr, size_t n_bytes )
197{
198#if defined(CPU_DATA_CACHE_ALIGNMENT)
199#if defined(CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS)
200 _CPU_cache_invalidate_data_range( d_addr, n_bytes );
201#else
202 const void * final_address;
203
204 /*
205 * Set d_addr to the beginning of the cache line; final_address indicates
206 * the last address_t which needs to be invalidated. Increment d_addr and
207 * invalidate the resulting line until final_address is passed.
208 */
209
210 if( n_bytes == 0 )
211 /* Do nothing if number of bytes to invalidate is zero */
212 return;
213
214 final_address = (void *)((size_t)d_addr + n_bytes - 1);
215 d_addr = (void *)((size_t)d_addr & ~(CPU_DATA_CACHE_ALIGNMENT - 1));
216 while( final_address >= d_addr ) {
217 _CPU_cache_invalidate_1_data_line( d_addr );
218 d_addr = (void *)((size_t)d_addr + CPU_DATA_CACHE_ALIGNMENT);
219 }
220#endif
221#else
222 (void) d_addr;
223 (void) n_bytes;
224#endif
225}
226
227/*
228 * This function is responsible for performing a data cache flush.
229 * It flushes the entire cache.
230 */
231void
233{
234#if defined(CPU_DATA_CACHE_ALIGNMENT)
235 /*
236 * Call the CPU-specific routine
237 */
238 _CPU_cache_flush_entire_data();
239#endif
240}
241
242/*
243 * This function is responsible for performing a data cache
244 * invalidate. It invalidates the entire cache.
245 */
246void
248{
249#if defined(CPU_DATA_CACHE_ALIGNMENT)
250 /*
251 * Call the CPU-specific routine
252 */
253
254 _CPU_cache_invalidate_entire_data();
255#endif
256}
257
258/*
259 * This function returns the data cache granularity.
260 */
261size_t
263{
264#if defined(CPU_DATA_CACHE_ALIGNMENT)
265 return CPU_DATA_CACHE_ALIGNMENT;
266#else
267 return 0;
268#endif
269}
270
271size_t
273{
274#if defined(CPU_CACHE_SUPPORT_PROVIDES_CACHE_SIZE_FUNCTIONS)
275 return _CPU_cache_get_data_cache_size( level );
276#else
277 (void) level;
278
279 return 0;
280#endif
281}
282
283/*
284 * This function freezes the data cache; cache lines
285 * are not replaced.
286 */
287void
289{
290#if defined(CPU_DATA_CACHE_ALIGNMENT)
291 _CPU_cache_freeze_data();
292#endif
293}
294
296{
297#if defined(CPU_DATA_CACHE_ALIGNMENT)
298 _CPU_cache_unfreeze_data();
299#endif
300}
301
302void
304{
305#if defined(CPU_DATA_CACHE_ALIGNMENT)
306 _CPU_cache_enable_data();
307#endif
308}
309
310#if !defined(CPU_CACHE_SUPPORT_PROVIDES_DISABLE_DATA)
311void
313{
314#if defined(CPU_DATA_CACHE_ALIGNMENT)
315 _CPU_cache_disable_data();
316#endif
317}
318#endif
319
320/*
321 * THESE FUNCTIONS ONLY HAVE BODIES IF WE HAVE AN INSTRUCTION CACHE
322 */
323
324#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT) \
325 && defined(RTEMS_SMP) \
326 && defined(CPU_CACHE_NO_INSTRUCTION_CACHE_SNOOPING)
327
328typedef struct {
329 const void *addr;
330 size_t size;
331} smp_cache_area;
332
333static void smp_cache_inst_inv(void *arg)
334{
335 smp_cache_area *area = arg;
336
337 _CPU_cache_invalidate_instruction_range(area->addr, area->size);
338}
339
340static void smp_cache_inst_inv_all(void *arg)
341{
342 (void) arg;
343 _CPU_cache_invalidate_entire_instruction();
344}
345
346static void smp_cache_broadcast( SMP_Action_handler handler, void *arg )
347{
348 uint32_t isr_level;
349 Per_CPU_Control *cpu_self;
350
351 isr_level = _ISR_Get_level();
352
353 if ( isr_level == 0 ) {
354 cpu_self = _Thread_Dispatch_disable();
355 } else {
356 cpu_self = _Per_CPU_Get();
357 }
358
359 ( *handler )( arg );
360 _SMP_Othercast_action( handler, arg );
361
362 if ( isr_level == 0 ) {
363 _Thread_Dispatch_enable( cpu_self );
364 }
365}
366
367#endif
368
369/*
370 * This function is responsible for performing an instruction cache
371 * invalidate. It must determine how many cache lines need to be invalidated
372 * and then perform the invalidations.
373 */
374#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT) \
375 && !defined(CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS)
376static void
377_CPU_cache_invalidate_instruction_range(
378 const void * i_addr,
379 size_t n_bytes
380)
381{
382 const void * final_address;
383
384 /*
385 * Set i_addr to the beginning of the cache line; final_address indicates
386 * the last address_t which needs to be invalidated. Increment i_addr and
387 * invalidate the resulting line until final_address is passed.
388 */
389
390 if( n_bytes == 0 )
391 /* Do nothing if number of bytes to invalidate is zero */
392 return;
393
394 final_address = (void *)((size_t)i_addr + n_bytes - 1);
395 i_addr = (void *)((size_t)i_addr & ~(CPU_INSTRUCTION_CACHE_ALIGNMENT - 1));
396 while( final_address >= i_addr ) {
397 _CPU_cache_invalidate_1_instruction_line( i_addr );
398 i_addr = (void *)((size_t)i_addr + CPU_INSTRUCTION_CACHE_ALIGNMENT);
399 }
400}
401#endif
402
403void
405 const void * i_addr,
406 size_t n_bytes
407)
408{
409#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
410#if defined(RTEMS_SMP) && defined(CPU_CACHE_NO_INSTRUCTION_CACHE_SNOOPING)
411 smp_cache_area area = { i_addr, n_bytes };
412
413 smp_cache_broadcast( smp_cache_inst_inv, &area );
414#else
415 _CPU_cache_invalidate_instruction_range( i_addr, n_bytes );
416#endif
417#else
418 (void) i_addr;
419 (void) n_bytes;
420#endif
421}
422
423/*
424 * This function is responsible for performing an instruction cache
425 * invalidate. It invalidates the entire cache.
426 */
427void
429{
430#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
431#if defined(RTEMS_SMP) && defined(CPU_CACHE_NO_INSTRUCTION_CACHE_SNOOPING)
432 smp_cache_broadcast( smp_cache_inst_inv_all, NULL );
433#else
434 _CPU_cache_invalidate_entire_instruction();
435#endif
436#endif
437}
438
439/*
440 * This function returns the instruction cache granularity.
441 */
442size_t
444{
445#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
446 return CPU_INSTRUCTION_CACHE_ALIGNMENT;
447#else
448 return 0;
449#endif
450}
451
452size_t
454{
455#if defined(CPU_CACHE_SUPPORT_PROVIDES_CACHE_SIZE_FUNCTIONS)
456 return _CPU_cache_get_instruction_cache_size( level );
457#else
458 (void) level;
459
460 return 0;
461#endif
462}
463
464/*
465 * This function freezes the instruction cache; cache lines
466 * are not replaced.
467 */
468void
470{
471#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
472 _CPU_cache_freeze_instruction();
473#endif
474}
475
477{
478#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
479 _CPU_cache_unfreeze_instruction();
480#endif
481}
482
483void
485{
486#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
487 _CPU_cache_enable_instruction();
488#endif
489}
490
491void
493{
494#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
495 _CPU_cache_disable_instruction();
496#endif
497}
498
499/* Returns the maximal cache line size of all cache kinds in bytes. */
501{
502#if defined(CPU_MAXIMAL_CACHE_ALIGNMENT)
503 return CPU_MAXIMAL_CACHE_ALIGNMENT;
504#endif
505 size_t data_line_size =
506#if defined(CPU_DATA_CACHE_ALIGNMENT)
507 CPU_DATA_CACHE_ALIGNMENT;
508#else
509 0;
510#endif
511 size_t instruction_line_size =
512#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
513 CPU_INSTRUCTION_CACHE_ALIGNMENT;
514#else
515 0;
516#endif
517 return MAX( data_line_size, instruction_line_size );
518}
519
520/*
521 * Purpose is to synchronize caches after code has been loaded
522 * or self modified. Actual implementation is simple only
523 * but it can and should be repaced by optimized version
524 * which does not need flush and invalidate all cache levels
525 * when code is changed.
526 */
528 const void *code_addr,
529 size_t n_bytes
530)
531{
532#if defined(CPU_CACHE_SUPPORT_PROVIDES_INSTRUCTION_SYNC_FUNCTION)
533 _CPU_cache_instruction_sync_after_code_change( code_addr, n_bytes );
534#else
535 rtems_cache_flush_multiple_data_lines( code_addr, n_bytes );
537#endif
538}
void rtems_cache_unfreeze_instruction(void)
Unfreezes the instruction cache.
Definition: cacheimpl.h:476
void rtems_cache_unfreeze_data(void)
Unfreezes the data cache.
Definition: cacheimpl.h:295
void rtems_cache_freeze_instruction(void)
Freezes the instruction caches.
Definition: cacheimpl.h:469
void rtems_cache_freeze_data(void)
Freezes the data caches.
Definition: cacheimpl.h:288
void rtems_cache_instruction_sync_after_code_change(const void *code_addr, size_t n_bytes)
Ensures necessary synchronization required after code changes.
Definition: cacheimpl.h:527
size_t rtems_cache_get_maximal_line_size(void)
Gets the maximal cache line size in bytes of all caches (data, instruction, or unified).
Definition: cacheimpl.h:500
void rtems_cache_invalidate_entire_instruction(void)
Invalidates the entire instruction cache.
Definition: cacheimpl.h:428
void rtems_cache_invalidate_entire_data(void)
Invalidates the entire data cache.
Definition: cacheimpl.h:247
void rtems_cache_invalidate_multiple_instruction_lines(const void *i_addr, size_t n_bytes)
Invalidates the instruction cache lines covering the memory area.
Definition: cacheimpl.h:404
size_t rtems_cache_get_data_cache_size(uint32_t level)
Gets the data cache size in bytes for the cache level.
Definition: cacheimpl.h:272
void rtems_cache_enable_data(void)
Enables the data cache.
Definition: cacheimpl.h:303
void rtems_cache_disable_instruction(void)
Disables the instruction cache.
Definition: cacheimpl.h:492
void rtems_cache_disable_data(void)
Disables the data cache.
Definition: cacheimpl.h:312
size_t rtems_cache_get_instruction_cache_size(uint32_t level)
Gets the instruction cache size in bytes for the cache level.
Definition: cacheimpl.h:453
void rtems_cache_invalidate_multiple_data_lines(const void *d_addr, size_t n_bytes)
Invalidates the data cache lines covering the memory area.
Definition: cacheimpl.h:196
void rtems_cache_flush_entire_data(void)
Flushes the entire data cache.
Definition: cacheimpl.h:232
void rtems_cache_flush_multiple_data_lines(const void *d_addr, size_t n_bytes)
Flushes the data cache lines covering the memory area.
Definition: cacheimpl.h:159
size_t rtems_cache_get_instruction_line_size(void)
Gets the instruction cache line size in bytes.
Definition: cacheimpl.h:443
size_t rtems_cache_get_data_line_size(void)
Gets the data cache line size in bytes.
Definition: cacheimpl.h:262
void rtems_cache_enable_instruction(void)
Enables the instruction cache.
Definition: cacheimpl.h:484
#define _ISR_Get_level()
Return current interrupt level.
Definition: isrlevel.h:147
void _Thread_Dispatch_enable(Per_CPU_Control *cpu_self)
Enables thread dispatching.
This header file defines the RTEMS Classic API.
This header file provides interfaces of the SMP Support which are only used by the implementation.
Per CPU Core Structure.
Definition: percpu.h:384
This header file provides the interfaces of the Thread Handler related to thread dispatching.