RTEMS 6.1-rc2
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.
#define NULL
Requests a GPIO pin group configuration.
Definition: xil_types.h:54
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.