RTEMS  5.1
cache-cp15.h
1 
9 /*
10  * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
11  *
12  * embedded brains GmbH
13  * Dornierstr. 4
14  * 82178 Puchheim
15  * Germany
16  * <rtems@embedded-brains.de>
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 
23 #ifndef LIBBSP_ARM_SHARED_CACHE_L1_H
24 #define LIBBSP_ARM_SHARED_CACHE_L1_H
25 
26 #include <bsp.h>
27 #include <libcpu/arm-cp15.h>
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif /* __cplusplus */
32 
33 /* These two defines also ensure that the rtems_cache_* functions have bodies */
34 #define ARM_CACHE_L1_CPU_DATA_ALIGNMENT 32
35 #define ARM_CACHE_L1_CPU_INSTRUCTION_ALIGNMENT 32
36 
37 #define ARM_CACHE_L1_CSS_ID_DATA \
38  (ARM_CP15_CACHE_CSS_ID_DATA | ARM_CP15_CACHE_CSS_LEVEL(0))
39 #define ARM_CACHE_L1_CSS_ID_INSTRUCTION \
40  (ARM_CP15_CACHE_CSS_ID_INSTRUCTION | ARM_CP15_CACHE_CSS_LEVEL(0))
41 #define ARM_CACHE_L1_DATA_LINE_MASK ( ARM_CACHE_L1_CPU_DATA_ALIGNMENT - 1 )
42 #define ARM_CACHE_L1_INSTRUCTION_LINE_MASK \
43  ( ARM_CACHE_L1_CPU_INSTRUCTION_ALIGNMENT \
44  - 1 )
45 
46 /* Errata Handlers */
47 static void arm_cache_l1_errata_764369_handler( void )
48 {
49 #ifdef RTEMS_SMP
50  _ARM_Data_synchronization_barrier();
51 #endif
52 }
53 
54 /*
55  * @param l1LineSize Number of bytes in cache line expressed as power of
56  * 2 value
57  * @param l1Associativity Associativity of cache. The associativity does not
58  * have to be a power of 2.
59  * qparam liNumSets Number of sets in cache
60  * */
61 
62 static inline void arm_cache_l1_properties_for_level(
63  uint32_t *l1LineSize,
64  uint32_t *l1Associativity,
65  uint32_t *l1NumSets,
66  uint32_t level_and_inst_dat
67 )
68 {
69  uint32_t ccsidr;
70 
71  ccsidr = arm_cp15_get_cache_size_id_for_level(level_and_inst_dat);
72 
73  /* Cache line size in words + 2 -> bytes) */
74  *l1LineSize = arm_ccsidr_get_line_power(ccsidr);
75  /* Number of Ways */
76  *l1Associativity = arm_ccsidr_get_associativity(ccsidr);
77  /* Number of Sets */
78  *l1NumSets = arm_ccsidr_get_num_sets(ccsidr);
79 }
80 
81 /*
82  * @param log_2_line_bytes The number of bytes per cache line expressed in log2
83  * @param associativity The associativity of the cache beeing operated
84  * @param cache_level_idx The level of the cache beeing operated minus 1 e.g 0
85  * for cache level 1
86  * @param set Number of the set to operate on
87  * @param way Number of the way to operate on
88  * */
89 
90 static inline uint32_t arm_cache_l1_get_set_way_param(
91  const uint32_t log_2_line_bytes,
92  const uint32_t associativity,
93  const uint32_t cache_level_idx,
94  const uint32_t set,
95  const uint32_t way )
96 {
97  uint32_t way_shift = __builtin_clz( associativity - 1 );
98 
99 
100  return ( 0
101  | ( way
102  << way_shift ) | ( set << log_2_line_bytes ) | ( cache_level_idx << 1 ) );
103 }
104 
105 static inline void arm_cache_l1_flush_1_data_line( const void *d_addr )
106 {
107  /* Flush the Data cache */
108  arm_cp15_data_cache_clean_and_invalidate_line( d_addr );
109 
110  /* Wait for L1 flush to complete */
111  _ARM_Data_synchronization_barrier();
112 }
113 
114 static inline void arm_cache_l1_flush_entire_data( void )
115 {
116  uint32_t l1LineSize, l1Associativity, l1NumSets;
117  uint32_t s, w;
118  uint32_t set_way_param;
119 
120  /* ensure ordering with previous memory accesses */
121  _ARM_Data_memory_barrier();
122 
123  /* Get the L1 cache properties */
124  arm_cache_l1_properties_for_level( &l1LineSize,
125  &l1Associativity, &l1NumSets,
126  ARM_CACHE_L1_CSS_ID_DATA);
127 
128  for ( w = 0; w < l1Associativity; ++w ) {
129  for ( s = 0; s < l1NumSets; ++s ) {
130  set_way_param = arm_cache_l1_get_set_way_param(
131  l1LineSize,
132  l1Associativity,
133  0,
134  s,
135  w
136  );
137  arm_cp15_data_cache_clean_line_by_set_and_way( set_way_param );
138  }
139  }
140 
141  /* Wait for L1 flush to complete */
142  _ARM_Data_synchronization_barrier();
143 }
144 
145 static inline void arm_cache_l1_invalidate_entire_data( void )
146 {
147  uint32_t l1LineSize, l1Associativity, l1NumSets;
148  uint32_t s, w;
149  uint32_t set_way_param;
150 
151  /* ensure ordering with previous memory accesses */
152  _ARM_Data_memory_barrier();
153 
154  /* Get the L1 cache properties */
155  arm_cache_l1_properties_for_level( &l1LineSize,
156  &l1Associativity, &l1NumSets,
157  ARM_CACHE_L1_CSS_ID_DATA);
158 
159  for ( w = 0; w < l1Associativity; ++w ) {
160  for ( s = 0; s < l1NumSets; ++s ) {
161  set_way_param = arm_cache_l1_get_set_way_param(
162  l1LineSize,
163  l1Associativity,
164  0,
165  s,
166  w
167  );
168  arm_cp15_data_cache_invalidate_line_by_set_and_way( set_way_param );
169  }
170  }
171 
172  /* Wait for L1 invalidate to complete */
173  _ARM_Data_synchronization_barrier();
174 }
175 
176 static inline void arm_cache_l1_clean_and_invalidate_entire_data( void )
177 {
178  uint32_t l1LineSize, l1Associativity, l1NumSets;
179  uint32_t s, w;
180  uint32_t set_way_param;
181 
182  /* ensure ordering with previous memory accesses */
183  _ARM_Data_memory_barrier();
184 
185 
186  /* Get the L1 cache properties */
187  arm_cache_l1_properties_for_level( &l1LineSize,
188  &l1Associativity, &l1NumSets,
189  ARM_CACHE_L1_CSS_ID_DATA);
190 
191  for ( w = 0; w < l1Associativity; ++w ) {
192  for ( s = 0; s < l1NumSets; ++s ) {
193  set_way_param = arm_cache_l1_get_set_way_param(
194  l1LineSize,
195  l1Associativity,
196  0,
197  s,
198  w
199  );
200  arm_cp15_data_cache_clean_and_invalidate_line_by_set_and_way(
201  set_way_param );
202  }
203  }
204 
205  /* Wait for L1 invalidate to complete */
206  _ARM_Data_synchronization_barrier();
207 }
208 
209 static inline void arm_cache_l1_flush_data_range(
210  const void *d_addr,
211  size_t n_bytes
212 )
213 {
214  if ( n_bytes != 0 ) {
215  uint32_t adx = (uint32_t) d_addr
216  & ~ARM_CACHE_L1_DATA_LINE_MASK;
217  const uint32_t ADDR_LAST =
218  (uint32_t)( (size_t) d_addr + n_bytes - 1 );
219 
220  arm_cache_l1_errata_764369_handler();
221 
222  for (; adx <= ADDR_LAST; adx += ARM_CACHE_L1_CPU_DATA_ALIGNMENT ) {
223  /* Store and invalidate the Data cache line */
224  arm_cp15_data_cache_clean_and_invalidate_line( (void*)adx );
225  }
226  /* Wait for L1 store to complete */
227  _ARM_Data_synchronization_barrier();
228  }
229 }
230 
231 
232 static inline void arm_cache_l1_invalidate_1_data_line(
233  const void *d_addr )
234 {
235  /* Invalidate the data cache line */
236  arm_cp15_data_cache_invalidate_line( d_addr );
237 
238  /* Wait for L1 invalidate to complete */
239  _ARM_Data_synchronization_barrier();
240 }
241 
242 static inline void arm_cache_l1_freeze_data( void )
243 {
244  /* To be implemented as needed, if supported by hardware at all */
245 }
246 
247 static inline void arm_cache_l1_unfreeze_data( void )
248 {
249  /* To be implemented as needed, if supported by hardware at all */
250 }
251 
252 static inline void arm_cache_l1_invalidate_1_instruction_line(
253  const void *i_addr )
254 {
255  /* Invalidate the Instruction cache line */
256  arm_cp15_instruction_cache_invalidate_line( i_addr );
257 
258  /* Wait for L1 invalidate to complete */
259  _ARM_Data_synchronization_barrier();
260 }
261 
262 static inline void arm_cache_l1_invalidate_data_range(
263  const void *d_addr,
264  size_t n_bytes
265 )
266 {
267  if ( n_bytes != 0 ) {
268  uint32_t adx = (uint32_t) d_addr
269  & ~ARM_CACHE_L1_DATA_LINE_MASK;
270  const uint32_t end =
271  (uint32_t)( (size_t)d_addr + n_bytes -1);
272 
273  arm_cache_l1_errata_764369_handler();
274 
275  /* Back starting address up to start of a line and invalidate until end */
276  for (;
277  adx <= end;
279  /* Invalidate the Instruction cache line */
280  arm_cp15_data_cache_invalidate_line( (void*)adx );
281  }
282  /* Wait for L1 invalidate to complete */
283  _ARM_Data_synchronization_barrier();
284  }
285 }
286 
287 static inline void arm_cache_l1_invalidate_instruction_range(
288  const void *i_addr,
289  size_t n_bytes
290 )
291 {
292  if ( n_bytes != 0 ) {
293  uint32_t adx = (uint32_t) i_addr
294  & ~ARM_CACHE_L1_INSTRUCTION_LINE_MASK;
295  const uint32_t end =
296  (uint32_t)( (size_t)i_addr + n_bytes -1);
297 
298  arm_cache_l1_errata_764369_handler();
299 
300  /* Back starting address up to start of a line and invalidate until end */
301  for (;
302  adx <= end;
303  adx += ARM_CACHE_L1_CPU_INSTRUCTION_ALIGNMENT ) {
304  /* Invalidate the Instruction cache line */
305  arm_cp15_instruction_cache_invalidate_line( (void*)adx );
306  }
307  /* Wait for L1 invalidate to complete */
308  _ARM_Data_synchronization_barrier();
309  }
310 }
311 
312 static inline void arm_cache_l1_invalidate_entire_instruction( void )
313 {
314  uint32_t ctrl = arm_cp15_get_control();
315 
316 
317  #ifdef RTEMS_SMP
318 
319  /* invalidate I-cache inner shareable */
320  arm_cp15_instruction_cache_inner_shareable_invalidate_all();
321 
322  /* I+BTB cache invalidate */
323  arm_cp15_instruction_cache_invalidate();
324  #else /* RTEMS_SMP */
325  /* I+BTB cache invalidate */
326  arm_cp15_instruction_cache_invalidate();
327  #endif /* RTEMS_SMP */
328 
329  if ( ( ctrl & ARM_CP15_CTRL_Z ) != 0 ) {
330  #if defined(__ARM_ARCH_7A__)
331  arm_cp15_branch_predictor_inner_shareable_invalidate_all();
332  #endif
333  #if defined(__ARM_ARCH_6KZ__) || defined(__ARM_ARCH_7A__)
334  arm_cp15_branch_predictor_invalidate_all();
335  #endif
336  }
337 }
338 
339 static inline void arm_cache_l1_freeze_instruction( void )
340 {
341  /* To be implemented as needed, if supported by hardware at all */
342 }
343 
344 static inline void arm_cache_l1_unfreeze_instruction( void )
345 {
346  /* To be implemented as needed, if supported by hardware at all */
347 }
348 
349 static inline void arm_cache_l1_disable_data( void )
350 {
351  /* Clean and invalidate the Data cache */
352  arm_cache_l1_flush_entire_data();
353 
354  /* Disable the Data cache */
355  arm_cp15_set_control( arm_cp15_get_control() & ~ARM_CP15_CTRL_C );
356 }
357 
358 static inline void arm_cache_l1_disable_instruction( void )
359 {
360  /* Synchronize the processor */
361  _ARM_Data_synchronization_barrier();
362 
363  /* Invalidate the Instruction cache */
364  arm_cache_l1_invalidate_entire_instruction();
365 
366  /* Disable the Instruction cache */
367  arm_cp15_set_control( arm_cp15_get_control() & ~ARM_CP15_CTRL_I );
368 }
369 
370 static inline size_t arm_cache_l1_get_data_cache_size( void )
371 {
372  size_t size;
373  uint32_t line_size = 0;
374  uint32_t associativity = 0;
375  uint32_t num_sets = 0;
376 
377  arm_cache_l1_properties_for_level( &line_size,
378  &associativity, &num_sets,
379  ARM_CACHE_L1_CSS_ID_DATA);
380 
381  size = (1 << line_size) * associativity * num_sets;
382 
383  return size;
384 }
385 
386 static inline size_t arm_cache_l1_get_instruction_cache_size( void )
387 {
388  size_t size;
389  uint32_t line_size = 0;
390  uint32_t associativity = 0;
391  uint32_t num_sets = 0;
392 
393  arm_cache_l1_properties_for_level( &line_size,
394  &associativity, &num_sets,
395  ARM_CACHE_L1_CSS_ID_INSTRUCTION);
396 
397  size = (1 << line_size) * associativity * num_sets;
398 
399  return size;
400 }
401 
402 #ifdef __cplusplus
403 }
404 #endif /* __cplusplus */
405 
406 #endif /* LIBBSP_ARM_SHARED_CACHE_L1_H */
ARM co-processor 15 (CP15) API.
unsigned w
Definition: tlb.h:226
unsigned size
Definition: tte.h:74
#define ARM_CACHE_L1_CPU_DATA_ALIGNMENT
Level 1 Cache definitions and functions.
Definition: cache-cp15.h:34