source: rtems/c/src/lib/libcpu/shared/src/cache_manager.c @ 1981b469

4.115
Last change on this file since 1981b469 was 26c142e5, checked in by Sebastian Huber <sebastian.huber@…>, on 04/17/15 at 10:05:16

score: Refactor SMP cache manager support

  • Property mode set to 100644
File size: 10.6 KB
Line 
1/*
2 *  Cache Manager
3 *
4 *  COPYRIGHT (c) 1989-1999.
5 *  On-Line Applications Research Corporation (OAR).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.org/license/LICENSE.
10 *
11 *
12 *  The functions in this file implement the API to the RTEMS Cache Manager and
13 *  are divided into data cache and instruction cache functions. Data cache
14 *  functions only have bodies if a data cache is supported. Instruction
15 *  cache functions only have bodies if an instruction cache is supported.
16 *  Support for a particular cache exists only if CPU_x_CACHE_ALIGNMENT is
17 *  defined, where x E {DATA, INSTRUCTION}. These definitions are found in
18 *  the Cache Manager Wrapper header files, often
19 *
20 *  rtems/c/src/lib/libcpu/CPU/cache_.h
21 *
22 *  The cache implementation header file can define
23 *  CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS
24 *  if it provides cache maintenance functions which operate on multiple lines.
25 *  Otherwise a generic loop with single line operations will be used.
26 *
27 *  The functions below are implemented with CPU dependent inline routines
28 *  found in the cache.c files for each CPU. In the event that a CPU does
29 *  not support a specific function for a cache it has, the CPU dependent
30 *  routine does nothing (but does exist).
31 *
32 *  At this point, the Cache Manager makes no considerations, and provides no
33 *  support for BSP specific issues such as a secondary cache. In such a system,
34 *  the CPU dependent routines would have to be modified, or a BSP layer added
35 *  to this Manager.
36 */
37
38#include <rtems.h>
39#include "cache_.h"
40
41#if defined(RTEMS_SMP)
42
43#include <rtems/score/smpimpl.h>
44
45typedef struct {
46  const void *addr;
47  size_t size;
48} smp_cache_area;
49
50#if defined(CPU_DATA_CACHE_ALIGNMENT)
51
52static void smp_cache_data_flush(void *arg)
53{
54  smp_cache_area *area = arg;
55
56  rtems_cache_flush_multiple_data_lines(area->addr, area->size);
57}
58
59static void smp_cache_data_inv(void *arg)
60{
61  smp_cache_area *area = arg;
62
63  rtems_cache_invalidate_multiple_data_lines(area->addr, area->size);
64}
65
66static void smp_cache_data_flush_all(void *arg)
67{
68  rtems_cache_flush_entire_data();
69}
70
71static void smp_cache_data_inv_all(void *arg)
72{
73  rtems_cache_invalidate_entire_data();
74}
75
76#endif /* defined(CPU_DATA_CACHE_ALIGNMENT) */
77
78void
79rtems_cache_flush_multiple_data_lines_processor_set(
80  const void *addr,
81  size_t size,
82  const size_t setsize,
83  const cpu_set_t *set
84)
85{
86#if defined(CPU_DATA_CACHE_ALIGNMENT)
87  smp_cache_area area = { addr, size };
88
89  _SMP_Multicast_action( setsize, set, smp_cache_data_flush, &area );
90#endif
91}
92
93void
94rtems_cache_invalidate_multiple_data_lines_processor_set(
95  const void *addr,
96  size_t size,
97  const size_t setsize,
98  const cpu_set_t *set
99)
100{
101#if defined(CPU_DATA_CACHE_ALIGNMENT)
102  smp_cache_area area = { addr, size };
103
104  _SMP_Multicast_action( setsize, set, smp_cache_data_inv, &area );
105#endif
106}
107
108void
109rtems_cache_flush_entire_data_processor_set(
110  const size_t setsize,
111  const cpu_set_t *set
112)
113{
114#if defined(CPU_DATA_CACHE_ALIGNMENT)
115  _SMP_Multicast_action( setsize, set, smp_cache_data_flush_all, NULL );
116#endif
117}
118
119void
120rtems_cache_invalidate_entire_data_processor_set(
121  const size_t setsize,
122  const cpu_set_t *set
123)
124{
125#if defined(CPU_DATA_CACHE_ALIGNMENT)
126  _SMP_Multicast_action( setsize, set, smp_cache_data_inv_all, NULL );
127#endif
128}
129
130#endif /* defined(RTEMS_SMP) */
131
132/*
133 * THESE FUNCTIONS ONLY HAVE BODIES IF WE HAVE A DATA CACHE
134 */
135
136/*
137 * This function is called to flush the data cache by performing cache
138 * copybacks. It must determine how many cache lines need to be copied
139 * back and then perform the copybacks.
140 */
141void
142rtems_cache_flush_multiple_data_lines( const void * d_addr, size_t n_bytes )
143{
144#if defined(CPU_DATA_CACHE_ALIGNMENT)
145#if defined(CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS)
146  _CPU_cache_flush_data_range( d_addr, n_bytes );
147#else
148  const void * final_address;
149
150 /*
151  * Set d_addr to the beginning of the cache line; final_address indicates
152  * the last address_t which needs to be pushed. Increment d_addr and push
153  * the resulting line until final_address is passed.
154  */
155
156  if( n_bytes == 0 )
157    /* Do nothing if number of bytes to flush is zero */
158    return;
159
160  final_address = (void *)((size_t)d_addr + n_bytes - 1);
161  d_addr = (void *)((size_t)d_addr & ~(CPU_DATA_CACHE_ALIGNMENT - 1));
162  while( d_addr <= final_address )  {
163    _CPU_cache_flush_1_data_line( d_addr );
164    d_addr = (void *)((size_t)d_addr + CPU_DATA_CACHE_ALIGNMENT);
165  }
166#endif
167#endif
168}
169
170
171/*
172 * This function is responsible for performing a data cache invalidate.
173 * It must determine how many cache lines need to be invalidated and then
174 * perform the invalidations.
175 */
176
177void
178rtems_cache_invalidate_multiple_data_lines( const void * d_addr, size_t n_bytes )
179{
180#if defined(CPU_DATA_CACHE_ALIGNMENT)
181#if defined(CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS)
182  _CPU_cache_invalidate_data_range( d_addr, n_bytes );
183#else
184  const void * final_address;
185
186 /*
187  * Set d_addr to the beginning of the cache line; final_address indicates
188  * the last address_t which needs to be invalidated. Increment d_addr and
189  * invalidate the resulting line until final_address is passed.
190  */
191
192  if( n_bytes == 0 )
193    /* Do nothing if number of bytes to invalidate is zero */
194    return;
195
196  final_address = (void *)((size_t)d_addr + n_bytes - 1);
197  d_addr = (void *)((size_t)d_addr & ~(CPU_DATA_CACHE_ALIGNMENT - 1));
198  while( final_address >= d_addr ) {
199    _CPU_cache_invalidate_1_data_line( d_addr );
200    d_addr = (void *)((size_t)d_addr + CPU_DATA_CACHE_ALIGNMENT);
201  }
202#endif
203#endif
204}
205
206
207/*
208 * This function is responsible for performing a data cache flush.
209 * It flushes the entire cache.
210 */
211void
212rtems_cache_flush_entire_data( void )
213{
214#if defined(CPU_DATA_CACHE_ALIGNMENT)
215   /*
216    * Call the CPU-specific routine
217    */
218   _CPU_cache_flush_entire_data();
219#endif
220}
221
222
223/*
224 * This function is responsible for performing a data cache
225 * invalidate. It invalidates the entire cache.
226 */
227void
228rtems_cache_invalidate_entire_data( void )
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/*
241 * This function returns the data cache granularity.
242 */
243size_t
244rtems_cache_get_data_line_size( void )
245{
246#if defined(CPU_DATA_CACHE_ALIGNMENT)
247  return CPU_DATA_CACHE_ALIGNMENT;
248#else
249  return 0;
250#endif
251}
252
253
254size_t
255rtems_cache_get_data_cache_size( uint32_t level )
256{
257#if defined(CPU_CACHE_SUPPORT_PROVIDES_CACHE_SIZE_FUNCTIONS)
258  return _CPU_cache_get_data_cache_size( level );
259#else
260  return 0;
261#endif
262}
263
264/*
265 * This function freezes the data cache; cache lines
266 * are not replaced.
267 */
268void
269rtems_cache_freeze_data( void )
270{
271#if defined(CPU_DATA_CACHE_ALIGNMENT)
272  _CPU_cache_freeze_data();
273#endif
274}
275
276
277/*
278 * This function unfreezes the instruction cache.
279 */
280void rtems_cache_unfreeze_data( void )
281{
282#if defined(CPU_DATA_CACHE_ALIGNMENT)
283  _CPU_cache_unfreeze_data();
284#endif
285}
286
287
288/* Turn on the data cache. */
289void
290rtems_cache_enable_data( void )
291{
292#if defined(CPU_DATA_CACHE_ALIGNMENT)
293  _CPU_cache_enable_data();
294#endif
295}
296
297
298/* Turn off the data cache. */
299void
300rtems_cache_disable_data( void )
301{
302#if defined(CPU_DATA_CACHE_ALIGNMENT)
303  _CPU_cache_disable_data();
304#endif
305}
306
307
308
309/*
310 * THESE FUNCTIONS ONLY HAVE BODIES IF WE HAVE AN INSTRUCTION CACHE
311 */
312
313#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT) \
314  && defined(RTEMS_SMP) \
315  && defined(CPU_CACHE_NO_INSTRUCTION_CACHE_SNOOPING)
316
317static void smp_cache_inst_inv(void *arg)
318{
319  smp_cache_area *area = arg;
320
321  _CPU_cache_invalidate_instruction_range(area->addr, area->size);
322}
323
324static void smp_cache_inst_inv_all(void *arg)
325{
326  _CPU_cache_invalidate_entire_instruction();
327}
328
329#endif
330
331/*
332 * This function is responsible for performing an instruction cache
333 * invalidate. It must determine how many cache lines need to be invalidated
334 * and then perform the invalidations.
335 */
336
337#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT) \
338  && !defined(CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS)
339static void
340_CPU_cache_invalidate_instruction_range(
341  const void * i_addr,
342  size_t n_bytes
343)
344{
345  const void * final_address;
346
347 /*
348  * Set i_addr to the beginning of the cache line; final_address indicates
349  * the last address_t which needs to be invalidated. Increment i_addr and
350  * invalidate the resulting line until final_address is passed.
351  */
352
353  if( n_bytes == 0 )
354    /* Do nothing if number of bytes to invalidate is zero */
355    return;
356
357  final_address = (void *)((size_t)i_addr + n_bytes - 1);
358  i_addr = (void *)((size_t)i_addr & ~(CPU_INSTRUCTION_CACHE_ALIGNMENT - 1));
359  while( final_address >= i_addr ) {
360    _CPU_cache_invalidate_1_instruction_line( i_addr );
361    i_addr = (void *)((size_t)i_addr + CPU_INSTRUCTION_CACHE_ALIGNMENT);
362  }
363}
364#endif
365
366void
367rtems_cache_invalidate_multiple_instruction_lines(
368  const void * i_addr,
369  size_t n_bytes
370)
371{
372#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
373#if defined(RTEMS_SMP) && defined(CPU_CACHE_NO_INSTRUCTION_CACHE_SNOOPING)
374  smp_cache_area area = { i_addr, n_bytes };
375
376  _SMP_Multicast_action( 0, NULL, smp_cache_inst_inv, &area );
377#else
378  _CPU_cache_invalidate_instruction_range( i_addr, n_bytes );
379#endif
380#endif
381}
382
383
384/*
385 * This function is responsible for performing an instruction cache
386 * invalidate. It invalidates the entire cache.
387 */
388void
389rtems_cache_invalidate_entire_instruction( void )
390{
391#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
392#if defined(RTEMS_SMP) && defined(CPU_CACHE_NO_INSTRUCTION_CACHE_SNOOPING)
393  _SMP_Multicast_action( 0, NULL, smp_cache_inst_inv_all, NULL );
394#else
395 _CPU_cache_invalidate_entire_instruction();
396#endif
397#endif
398}
399
400
401/*
402 * This function returns the instruction cache granularity.
403 */
404size_t
405rtems_cache_get_instruction_line_size( void )
406{
407#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
408  return CPU_INSTRUCTION_CACHE_ALIGNMENT;
409#else
410  return 0;
411#endif
412}
413
414
415size_t
416rtems_cache_get_instruction_cache_size( uint32_t level )
417{
418#if defined(CPU_CACHE_SUPPORT_PROVIDES_CACHE_SIZE_FUNCTIONS)
419  return _CPU_cache_get_instruction_cache_size( level );
420#else
421  return 0;
422#endif
423}
424
425
426/*
427 * This function freezes the instruction cache; cache lines
428 * are not replaced.
429 */
430void
431rtems_cache_freeze_instruction( void )
432{
433#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
434  _CPU_cache_freeze_instruction();
435#endif
436}
437
438
439/*
440 * This function unfreezes the instruction cache.
441 */
442void rtems_cache_unfreeze_instruction( void )
443{
444#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
445  _CPU_cache_unfreeze_instruction();
446#endif
447}
448
449
450/* Turn on the instruction cache. */
451void
452rtems_cache_enable_instruction( void )
453{
454#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
455  _CPU_cache_enable_instruction();
456#endif
457}
458
459
460/* Turn off the instruction cache. */
461void
462rtems_cache_disable_instruction( void )
463{
464#if defined(CPU_INSTRUCTION_CACHE_ALIGNMENT)
465  _CPU_cache_disable_instruction();
466#endif
467}
Note: See TracBrowser for help on using the repository browser.