RTEMS 6.1-rc6
Loading...
Searching...
No Matches
cacheimpl.h
Go to the documentation of this file.
1
10/*
11 * Cache Manager
12 *
13 * Copyright (C) 2014, 2018 embedded brains GmbH & Co. KG
14 *
15 * COPYRIGHT (c) 1989-1999.
16 * On-Line Applications Research Corporation (OAR).
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
111#include <rtems.h>
112
113#include <sys/param.h>
114
115#if defined(RTEMS_SMP) && defined(CPU_CACHE_NO_INSTRUCTION_CACHE_SNOOPING)
116#include <rtems/score/smpimpl.h>
118#endif
119
120#if CPU_DATA_CACHE_ALIGNMENT > CPU_CACHE_LINE_BYTES
121#error "CPU_DATA_CACHE_ALIGNMENT is greater than CPU_CACHE_LINE_BYTES"
122#endif
123
124#if CPU_INSTRUCTION_CACHE_ALIGNMENT > CPU_CACHE_LINE_BYTES
125#error "CPU_INSTRUCTION_CACHE_ALIGNMENT is greater than CPU_CACHE_LINE_BYTES"
126#endif
127
136/*
137 * THESE FUNCTIONS ONLY HAVE BODIES IF WE HAVE A DATA CACHE
138 */
139
140/*
141 * This function is called to flush the data cache by performing cache
142 * copybacks. It must determine how many cache lines need to be copied
143 * back and then perform the copybacks.
144 */
145void
146rtems_cache_flush_multiple_data_lines( const void * d_addr, size_t n_bytes )
147{
148#if defined(CPU_DATA_CACHE_ALIGNMENT)
149#if defined(CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS)
150 _CPU_cache_flush_data_range( d_addr, n_bytes );
151#else
152 const void * final_address;
153
154 /*
155 * Set d_addr to the beginning of the cache line; final_address indicates
156 * the last address_t which needs to be pushed. Increment d_addr and push
157 * the resulting line until final_address is passed.
158 */
159
160 if( n_bytes == 0 )
161 /* Do nothing if number of bytes to flush is zero */
162 return;
163
164 final_address = (void *)((size_t)d_addr + n_bytes - 1);
165 d_addr = (void *)((size_t)d_addr & ~(CPU_DATA_CACHE_ALIGNMENT - 1));
166 while( d_addr <= final_address ) {
167 _CPU_cache_flush_1_data_line( d_addr );
168 d_addr = (void *)((size_t)d_addr + CPU_DATA_CACHE_ALIGNMENT);
169 }
170#endif
171#endif
172}
173
174/*
175 * This function is responsible for performing a data cache invalidate.
176 * It must determine how many cache lines need to be invalidated and then
177 * perform the invalidations.
178 */
179void
180rtems_cache_invalidate_multiple_data_lines( const void * d_addr, size_t n_bytes )
181{
182#if defined(CPU_DATA_CACHE_ALIGNMENT)
183#if defined(CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS)
184 _CPU_cache_invalidate_data_range( d_addr, n_bytes );
185#else
186 const void * final_address;
187
188 /*
189 * Set d_addr to the beginning of the cache line; final_address indicates
190 * the last address_t which needs to be invalidated. Increment d_addr and
191 * invalidate the resulting line until final_address is passed.
192 */
193
194 if( n_bytes == 0 )
195 /* Do nothing if number of bytes to invalidate is zero */
196 return;
197
198 final_address = (void *)((size_t)d_addr + n_bytes - 1);
199 d_addr = (void *)((size_t)d_addr & ~(CPU_DATA_CACHE_ALIGNMENT - 1));
200 while( final_address >= d_addr ) {
201 _CPU_cache_invalidate_1_data_line( d_addr );
202 d_addr = (void *)((size_t)d_addr + CPU_DATA_CACHE_ALIGNMENT);
203 }
204#endif
205#endif
206}
207
208/*
209 * This function is responsible for performing a data cache flush.
210 * It flushes the entire cache.
211 */
212void
214{
215#if defined(CPU_DATA_CACHE_ALIGNMENT)
216 /*
217 * Call the CPU-specific routine
218 */
219 _CPU_cache_flush_entire_data();
220#endif
221}
222
223/*
224 * This function is responsible for performing a data cache
225 * invalidate. It invalidates the entire cache.
226 */
227void
229{
230#if defined(CPU_DATA_CACHE_ALIGNMENT)
231 /*
232 * Call the CPU-specific routine
233 */
234
235 _CPU_cache_invalidate_entire_data();
236#endif
237}
238
239/*
240 * This function returns the data cache granularity.
241 */
242size_t
244{
245#if defined(CPU_DATA_CACHE_ALIGNMENT)
246 return CPU_DATA_CACHE_ALIGNMENT;
247#else
248 return 0;
249#endif
250}
251
252size_t
254{
255#if defined(CPU_CACHE_SUPPORT_PROVIDES_CACHE_SIZE_FUNCTIONS)
256 return _CPU_cache_get_data_cache_size( level );
257#else
258 return 0;
259#endif
260}
261
262/*
263 * This function freezes the data cache; cache lines
264 * are not replaced.
265 */
266void
268{
269#if defined(CPU_DATA_CACHE_ALIGNMENT)
270 _CPU_cache_freeze_data();
271#endif
272}
273
275{
276#if defined(CPU_DATA_CACHE_ALIGNMENT)
277 _CPU_cache_unfreeze_data();
278#endif
279}
280
281void
283{
284#if defined(CPU_DATA_CACHE_ALIGNMENT)
285 _CPU_cache_enable_data();
286#endif
287}
288
289#if !defined(CPU_CACHE_SUPPORT_PROVIDES_DISABLE_DATA)
290void
292{
293#if defined(CPU_DATA_CACHE_ALIGNMENT)
294 _CPU_cache_disable_data();
295#endif
296}
297#endif
298
299/*
300 * THESE FUNCTIONS ONLY HAVE BODIES IF WE HAVE AN INSTRUCTION CACHE
301 */
302
303#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT) \
304 && defined(RTEMS_SMP) \
305 && defined(CPU_CACHE_NO_INSTRUCTION_CACHE_SNOOPING)
306
307typedef struct {
308 const void *addr;
309 size_t size;
310} smp_cache_area;
311
312static void smp_cache_inst_inv(void *arg)
313{
314 smp_cache_area *area = arg;
315
316 _CPU_cache_invalidate_instruction_range(area->addr, area->size);
317}
318
319static void smp_cache_inst_inv_all(void *arg)
320{
321 (void) arg;
322 _CPU_cache_invalidate_entire_instruction();
323}
324
325static void smp_cache_broadcast( SMP_Action_handler handler, void *arg )
326{
327 uint32_t isr_level;
328 Per_CPU_Control *cpu_self;
329
330 isr_level = _ISR_Get_level();
331
332 if ( isr_level == 0 ) {
333 cpu_self = _Thread_Dispatch_disable();
334 } else {
335 cpu_self = _Per_CPU_Get();
336 }
337
338 ( *handler )( arg );
339 _SMP_Othercast_action( handler, arg );
340
341 if ( isr_level == 0 ) {
342 _Thread_Dispatch_enable( cpu_self );
343 }
344}
345
346#endif
347
348/*
349 * This function is responsible for performing an instruction cache
350 * invalidate. It must determine how many cache lines need to be invalidated
351 * and then perform the invalidations.
352 */
353#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT) \
354 && !defined(CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS)
355static void
356_CPU_cache_invalidate_instruction_range(
357 const void * i_addr,
358 size_t n_bytes
359)
360{
361 const void * final_address;
362
363 /*
364 * Set i_addr to the beginning of the cache line; final_address indicates
365 * the last address_t which needs to be invalidated. Increment i_addr and
366 * invalidate the resulting line until final_address is passed.
367 */
368
369 if( n_bytes == 0 )
370 /* Do nothing if number of bytes to invalidate is zero */
371 return;
372
373 final_address = (void *)((size_t)i_addr + n_bytes - 1);
374 i_addr = (void *)((size_t)i_addr & ~(CPU_INSTRUCTION_CACHE_ALIGNMENT - 1));
375 while( final_address >= i_addr ) {
376 _CPU_cache_invalidate_1_instruction_line( i_addr );
377 i_addr = (void *)((size_t)i_addr + CPU_INSTRUCTION_CACHE_ALIGNMENT);
378 }
379}
380#endif
381
382void
384 const void * i_addr,
385 size_t n_bytes
386)
387{
388#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
389#if defined(RTEMS_SMP) && defined(CPU_CACHE_NO_INSTRUCTION_CACHE_SNOOPING)
390 smp_cache_area area = { i_addr, n_bytes };
391
392 smp_cache_broadcast( smp_cache_inst_inv, &area );
393#else
394 _CPU_cache_invalidate_instruction_range( i_addr, n_bytes );
395#endif
396#endif
397}
398
399/*
400 * This function is responsible for performing an instruction cache
401 * invalidate. It invalidates the entire cache.
402 */
403void
405{
406#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
407#if defined(RTEMS_SMP) && defined(CPU_CACHE_NO_INSTRUCTION_CACHE_SNOOPING)
408 smp_cache_broadcast( smp_cache_inst_inv_all, NULL );
409#else
410 _CPU_cache_invalidate_entire_instruction();
411#endif
412#endif
413}
414
415/*
416 * This function returns the instruction cache granularity.
417 */
418size_t
420{
421#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
422 return CPU_INSTRUCTION_CACHE_ALIGNMENT;
423#else
424 return 0;
425#endif
426}
427
428size_t
430{
431#if defined(CPU_CACHE_SUPPORT_PROVIDES_CACHE_SIZE_FUNCTIONS)
432 return _CPU_cache_get_instruction_cache_size( level );
433#else
434 return 0;
435#endif
436}
437
438/*
439 * This function freezes the instruction cache; cache lines
440 * are not replaced.
441 */
442void
444{
445#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
446 _CPU_cache_freeze_instruction();
447#endif
448}
449
451{
452#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
453 _CPU_cache_unfreeze_instruction();
454#endif
455}
456
457void
459{
460#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
461 _CPU_cache_enable_instruction();
462#endif
463}
464
465void
467{
468#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
469 _CPU_cache_disable_instruction();
470#endif
471}
472
473/* Returns the maximal cache line size of all cache kinds in bytes. */
475{
476#if defined(CPU_MAXIMAL_CACHE_ALIGNMENT)
477 return CPU_MAXIMAL_CACHE_ALIGNMENT;
478#endif
479 size_t data_line_size =
480#if defined(CPU_DATA_CACHE_ALIGNMENT)
481 CPU_DATA_CACHE_ALIGNMENT;
482#else
483 0;
484#endif
485 size_t instruction_line_size =
486#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
487 CPU_INSTRUCTION_CACHE_ALIGNMENT;
488#else
489 0;
490#endif
491 return MAX( data_line_size, instruction_line_size );
492}
493
494/*
495 * Purpose is to synchronize caches after code has been loaded
496 * or self modified. Actual implementation is simple only
497 * but it can and should be repaced by optimized version
498 * which does not need flush and invalidate all cache levels
499 * when code is changed.
500 */
502 const void *code_addr,
503 size_t n_bytes
504)
505{
506#if defined(CPU_CACHE_SUPPORT_PROVIDES_INSTRUCTION_SYNC_FUNCTION)
507 _CPU_cache_instruction_sync_after_code_change( code_addr, n_bytes );
508#else
509 rtems_cache_flush_multiple_data_lines( code_addr, n_bytes );
511#endif
512}
void rtems_cache_unfreeze_instruction(void)
Unfreezes the instruction cache.
Definition: cacheimpl.h:450
void rtems_cache_unfreeze_data(void)
Unfreezes the data cache.
Definition: cacheimpl.h:274
void rtems_cache_freeze_instruction(void)
Freezes the instruction caches.
Definition: cacheimpl.h:443
void rtems_cache_freeze_data(void)
Freezes the data caches.
Definition: cacheimpl.h:267
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:501
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:474
void rtems_cache_invalidate_entire_instruction(void)
Invalidates the entire instruction cache.
Definition: cacheimpl.h:404
void rtems_cache_invalidate_entire_data(void)
Invalidates the entire data cache.
Definition: cacheimpl.h:228
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:383
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:253
void rtems_cache_enable_data(void)
Enables the data cache.
Definition: cacheimpl.h:282
void rtems_cache_disable_instruction(void)
Disables the instruction cache.
Definition: cacheimpl.h:466
void rtems_cache_disable_data(void)
Disables the data cache.
Definition: cacheimpl.h:291
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:429
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:180
void rtems_cache_flush_entire_data(void)
Flushes the entire data cache.
Definition: cacheimpl.h:213
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:146
size_t rtems_cache_get_instruction_line_size(void)
Gets the instruction cache line size in bytes.
Definition: cacheimpl.h:419
size_t rtems_cache_get_data_line_size(void)
Gets the data cache line size in bytes.
Definition: cacheimpl.h:243
void rtems_cache_enable_instruction(void)
Enables the instruction cache.
Definition: cacheimpl.h:458
#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.