RTEMS 6.1-rc6
Loading...
Searching...
No Matches
cache-cp15.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
12/*
13 * Copyright (c) 2014 embedded brains GmbH & Co. KG
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef LIBBSP_ARM_SHARED_CACHE_L1_H
38#define LIBBSP_ARM_SHARED_CACHE_L1_H
39
40#include <bsp.h>
41#include <libcpu/arm-cp15.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif /* __cplusplus */
46
47/* These two defines also ensure that the rtems_cache_* functions have bodies */
48#define ARM_CACHE_L1_CPU_DATA_ALIGNMENT 32
49#define ARM_CACHE_L1_CPU_INSTRUCTION_ALIGNMENT 32
50
51#define ARM_CACHE_L1_CSS_ID_DATA \
52 (ARM_CP15_CACHE_CSS_ID_DATA | ARM_CP15_CACHE_CSS_LEVEL(0))
53#define ARM_CACHE_L1_CSS_ID_INSTRUCTION \
54 (ARM_CP15_CACHE_CSS_ID_INSTRUCTION | ARM_CP15_CACHE_CSS_LEVEL(0))
55#define ARM_CACHE_L1_DATA_LINE_MASK ( ARM_CACHE_L1_CPU_DATA_ALIGNMENT - 1 )
56#define ARM_CACHE_L1_INSTRUCTION_LINE_MASK \
57 ( ARM_CACHE_L1_CPU_INSTRUCTION_ALIGNMENT \
58 - 1 )
59
60/* Errata Handlers */
61static void arm_cache_l1_errata_764369_handler( void )
62{
63#ifdef RTEMS_SMP
64 _ARM_Data_synchronization_barrier();
65#endif
66}
67
68/*
69 * @param l1LineSize Number of bytes in cache line expressed as power of
70 * 2 value
71 * @param l1Associativity Associativity of cache. The associativity does not
72 * have to be a power of 2.
73 * qparam liNumSets Number of sets in cache
74 * */
75
76static inline void arm_cache_l1_properties_for_level(
77 uint32_t *l1LineSize,
78 uint32_t *l1Associativity,
79 uint32_t *l1NumSets,
80 uint32_t level_and_inst_dat
81)
82{
83 uint32_t ccsidr;
84
85 ccsidr = arm_cp15_get_cache_size_id_for_level(level_and_inst_dat);
86
87 /* Cache line size in words + 2 -> bytes) */
88 *l1LineSize = arm_ccsidr_get_line_power(ccsidr);
89 /* Number of Ways */
90 *l1Associativity = arm_ccsidr_get_associativity(ccsidr);
91 /* Number of Sets */
92 *l1NumSets = arm_ccsidr_get_num_sets(ccsidr);
93}
94
95/*
96 * @param log_2_line_bytes The number of bytes per cache line expressed in log2
97 * @param associativity The associativity of the cache beeing operated
98 * @param cache_level_idx The level of the cache beeing operated minus 1 e.g 0
99 * for cache level 1
100 * @param set Number of the set to operate on
101 * @param way Number of the way to operate on
102 * */
103
104static inline uint32_t arm_cache_l1_get_set_way_param(
105 const uint32_t log_2_line_bytes,
106 const uint32_t associativity,
107 const uint32_t cache_level_idx,
108 const uint32_t set,
109 const uint32_t way )
110{
111 uint32_t way_shift = __builtin_clz( associativity - 1 );
112
113
114 return ( 0
115 | ( way
116 << way_shift ) | ( set << log_2_line_bytes ) | ( cache_level_idx << 1 ) );
117}
118
119static inline void arm_cache_l1_flush_1_data_line( const void *d_addr )
120{
121 /* Flush the Data cache */
122 arm_cp15_data_cache_clean_and_invalidate_line( d_addr );
123
124 /* Wait for L1 flush to complete */
125 _ARM_Data_synchronization_barrier();
126}
127
128static inline void arm_cache_l1_flush_entire_data( void )
129{
130 uint32_t l1LineSize, l1Associativity, l1NumSets;
131 uint32_t s, w;
132 uint32_t set_way_param;
133
134 /* ensure ordering with previous memory accesses */
135 _ARM_Data_memory_barrier();
136
137 /* Get the L1 cache properties */
138 arm_cache_l1_properties_for_level( &l1LineSize,
139 &l1Associativity, &l1NumSets,
140 ARM_CACHE_L1_CSS_ID_DATA);
141
142 for ( w = 0; w < l1Associativity; ++w ) {
143 for ( s = 0; s < l1NumSets; ++s ) {
144 set_way_param = arm_cache_l1_get_set_way_param(
145 l1LineSize,
146 l1Associativity,
147 0,
148 s,
149 w
150 );
151 arm_cp15_data_cache_clean_line_by_set_and_way( set_way_param );
152 }
153 }
154
155 /* Wait for L1 flush to complete */
156 _ARM_Data_synchronization_barrier();
157}
158
159static inline void arm_cache_l1_invalidate_entire_data( void )
160{
161 uint32_t l1LineSize, l1Associativity, l1NumSets;
162 uint32_t s, w;
163 uint32_t set_way_param;
164
165 /* ensure ordering with previous memory accesses */
166 _ARM_Data_memory_barrier();
167
168 /* Get the L1 cache properties */
169 arm_cache_l1_properties_for_level( &l1LineSize,
170 &l1Associativity, &l1NumSets,
171 ARM_CACHE_L1_CSS_ID_DATA);
172
173 for ( w = 0; w < l1Associativity; ++w ) {
174 for ( s = 0; s < l1NumSets; ++s ) {
175 set_way_param = arm_cache_l1_get_set_way_param(
176 l1LineSize,
177 l1Associativity,
178 0,
179 s,
180 w
181 );
182 arm_cp15_data_cache_invalidate_line_by_set_and_way( set_way_param );
183 }
184 }
185
186 /* Wait for L1 invalidate to complete */
187 _ARM_Data_synchronization_barrier();
188}
189
190static inline void arm_cache_l1_clean_and_invalidate_entire_data( void )
191{
192 uint32_t l1LineSize, l1Associativity, l1NumSets;
193 uint32_t s, w;
194 uint32_t set_way_param;
195
196 /* ensure ordering with previous memory accesses */
197 _ARM_Data_memory_barrier();
198
199
200 /* Get the L1 cache properties */
201 arm_cache_l1_properties_for_level( &l1LineSize,
202 &l1Associativity, &l1NumSets,
203 ARM_CACHE_L1_CSS_ID_DATA);
204
205 for ( w = 0; w < l1Associativity; ++w ) {
206 for ( s = 0; s < l1NumSets; ++s ) {
207 set_way_param = arm_cache_l1_get_set_way_param(
208 l1LineSize,
209 l1Associativity,
210 0,
211 s,
212 w
213 );
214 arm_cp15_data_cache_clean_and_invalidate_line_by_set_and_way(
215 set_way_param );
216 }
217 }
218
219 /* Wait for L1 invalidate to complete */
220 _ARM_Data_synchronization_barrier();
221}
222
223static inline void arm_cache_l1_flush_data_range(
224 const void *d_addr,
225 size_t n_bytes
226)
227{
228 if ( n_bytes != 0 ) {
229 uint32_t adx = (uint32_t) d_addr
230 & ~ARM_CACHE_L1_DATA_LINE_MASK;
231 const uint32_t ADDR_LAST =
232 (uint32_t)( (size_t) d_addr + n_bytes - 1 );
233
234 arm_cache_l1_errata_764369_handler();
235
236 for (; adx <= ADDR_LAST; adx += ARM_CACHE_L1_CPU_DATA_ALIGNMENT ) {
237 /* Store and invalidate the Data cache line */
238 arm_cp15_data_cache_clean_and_invalidate_line( (void*)adx );
239 }
240 /* Wait for L1 store to complete */
241 _ARM_Data_synchronization_barrier();
242 }
243}
244
245
246static inline void arm_cache_l1_invalidate_1_data_line(
247 const void *d_addr )
248{
249 /* Invalidate the data cache line */
250 arm_cp15_data_cache_invalidate_line( d_addr );
251
252 /* Wait for L1 invalidate to complete */
253 _ARM_Data_synchronization_barrier();
254}
255
256static inline void arm_cache_l1_freeze_data( void )
257{
258 /* To be implemented as needed, if supported by hardware at all */
259}
260
261static inline void arm_cache_l1_unfreeze_data( void )
262{
263 /* To be implemented as needed, if supported by hardware at all */
264}
265
266static inline void arm_cache_l1_invalidate_1_instruction_line(
267 const void *i_addr )
268{
269 /* Invalidate the Instruction cache line */
270 arm_cp15_instruction_cache_invalidate_line( i_addr );
271
272 /* Wait for L1 invalidate to complete */
273 _ARM_Data_synchronization_barrier();
274}
275
276static inline void arm_cache_l1_invalidate_data_range(
277 const void *d_addr,
278 size_t n_bytes
279)
280{
281 if ( n_bytes != 0 ) {
282 uint32_t adx = (uint32_t) d_addr
283 & ~ARM_CACHE_L1_DATA_LINE_MASK;
284 const uint32_t end =
285 (uint32_t)( (size_t)d_addr + n_bytes -1);
286
287 arm_cache_l1_errata_764369_handler();
288
289 /* Back starting address up to start of a line and invalidate until end */
290 for (;
291 adx <= end;
292 adx += ARM_CACHE_L1_CPU_DATA_ALIGNMENT ) {
293 /* Invalidate the Instruction cache line */
294 arm_cp15_data_cache_invalidate_line( (void*)adx );
295 }
296 /* Wait for L1 invalidate to complete */
297 _ARM_Data_synchronization_barrier();
298 }
299}
300
301static inline void arm_cache_l1_invalidate_instruction_range(
302 const void *i_addr,
303 size_t n_bytes
304)
305{
306 if ( n_bytes != 0 ) {
307 uint32_t adx = (uint32_t) i_addr
308 & ~ARM_CACHE_L1_INSTRUCTION_LINE_MASK;
309 const uint32_t end =
310 (uint32_t)( (size_t)i_addr + n_bytes -1);
311
312 arm_cache_l1_errata_764369_handler();
313
314 /* Back starting address up to start of a line and invalidate until end */
315 for (;
316 adx <= end;
317 adx += ARM_CACHE_L1_CPU_INSTRUCTION_ALIGNMENT ) {
318 /* Invalidate the Instruction cache line */
319 arm_cp15_instruction_cache_invalidate_line( (void*)adx );
320 }
321 /* Wait for L1 invalidate to complete */
322 _ARM_Data_synchronization_barrier();
323 }
324}
325
326static inline void arm_cache_l1_invalidate_entire_instruction( void )
327{
328 uint32_t ctrl = arm_cp15_get_control();
329
330
331 #ifdef RTEMS_SMP
332
333 /* invalidate I-cache inner shareable */
334 arm_cp15_instruction_cache_inner_shareable_invalidate_all();
335
336 /* I+BTB cache invalidate */
337 arm_cp15_instruction_cache_invalidate();
338 #else /* RTEMS_SMP */
339 /* I+BTB cache invalidate */
340 arm_cp15_instruction_cache_invalidate();
341 #endif /* RTEMS_SMP */
342
343 if ( ( ctrl & ARM_CP15_CTRL_Z ) != 0 ) {
344 #if defined(__ARM_ARCH_7A__)
345 arm_cp15_branch_predictor_inner_shareable_invalidate_all();
346 #endif
347 #if defined(__ARM_ARCH_6KZ__) || defined(__ARM_ARCH_7A__)
348 arm_cp15_branch_predictor_invalidate_all();
349 #endif
350 }
351}
352
353static inline void arm_cache_l1_freeze_instruction( void )
354{
355 /* To be implemented as needed, if supported by hardware at all */
356}
357
358static inline void arm_cache_l1_unfreeze_instruction( void )
359{
360 /* To be implemented as needed, if supported by hardware at all */
361}
362
363static inline size_t arm_cache_l1_get_data_cache_size( void )
364{
365 size_t size;
366 uint32_t line_size = 0;
367 uint32_t associativity = 0;
368 uint32_t num_sets = 0;
369
370 arm_cache_l1_properties_for_level( &line_size,
371 &associativity, &num_sets,
372 ARM_CACHE_L1_CSS_ID_DATA);
373
374 size = (1 << line_size) * associativity * num_sets;
375
376 return size;
377}
378
379static inline size_t arm_cache_l1_get_instruction_cache_size( void )
380{
381 size_t size;
382 uint32_t line_size = 0;
383 uint32_t associativity = 0;
384 uint32_t num_sets = 0;
385
386 arm_cache_l1_properties_for_level( &line_size,
387 &associativity, &num_sets,
388 ARM_CACHE_L1_CSS_ID_INSTRUCTION);
389
390 size = (1 << line_size) * associativity * num_sets;
391
392 return size;
393}
394
395#ifdef __cplusplus
396}
397#endif /* __cplusplus */
398
399#endif /* LIBBSP_ARM_SHARED_CACHE_L1_H */
ARM co-processor 15 (CP15) API.
unsigned w
Definition: tlb.h:16