source: rtems/c/src/lib/libcpu/shared/src/cache_manager.c @ 4bf2a6aa

4.115
Last change on this file since 4bf2a6aa was 4bf2a6aa, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 27, 2015 at 7:40:16 AM

bsps/cache: Clarify range functions support

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