source: rtems/bsps/or1k/shared/cache/cache.c @ 4cf93658

5
Last change on this file since 4cf93658 was 4cf93658, checked in by Sebastian Huber <sebastian.huber@…>, on Jan 27, 2018 at 1:37:51 PM

bsps: Rework cache manager implementation

The previous cache manager support used a single souce file
(cache_manager.c) which included an implementation header (cache_.h).
This required the use of specialized include paths to find the right
header file. Change this to include a generic implementation header
(cacheimpl.h) in specialized source files.

Use the following directories and files:

  • bsps/shared/cache
  • bsps/@RTEMS_CPU@/shared/cache
  • bsps/@RTEMS_CPU@/@RTEMS_BSP_FAMILY/start/cache.c

Update #3285.

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * COPYRIGHT (c) 2014, 2016 ÅAC Microtec AB <www.aacmicrotec.com>
3 * Contributor(s):
4 *  Karol Gugala <kgugala@antmicro.com>
5 *  Martin Werner <martin.werner@aacmicrotec.com>
6 *
7 * COPYRIGHT (c) 2014 Hesham ALMatary <heshamelmatary@gmail.com>
8 *
9 * COPYRIGHT (c) 1989-2006
10 * On-Line Applications Research Corporation (OAR).
11 *
12 * The license and distribution terms for this file may be
13 * found in the file LICENSE in this distribution or at
14 * http://www.rtems.org/license/LICENSE.
15 */
16
17#include <rtems/score/cpu.h>
18#include <rtems/score/interr.h>
19#include <rtems/score/or1k-utility.h>
20#include <rtems/score/percpu.h>
21
22#define CPU_DATA_CACHE_ALIGNMENT        32
23#define CPU_INSTRUCTION_CACHE_ALIGNMENT 32
24
25#define CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS 1
26#define CPU_CACHE_SUPPORT_PROVIDES_CACHE_SIZE_FUNCTIONS 1
27
28static inline size_t
29_CPU_cache_get_data_cache_size( const uint32_t level )
30{
31  return (level == 0 || level == 1)? 8192 : 0;
32}
33
34static inline size_t
35_CPU_cache_get_instruction_cache_size( const uint32_t level )
36{
37  return (level == 0 || level == 1)? 8192 : 0;
38}
39
40static inline void _CPU_OR1K_Cache_data_block_prefetch(const void *d_addr)
41{
42  ISR_Level level;
43
44  _ISR_Local_disable (level);
45
46  _OR1K_mtspr(CPU_OR1K_SPR_DCBPR, (uintptr_t) d_addr);
47
48  _ISR_Local_enable(level);
49}
50
51static inline void _CPU_OR1K_Cache_data_block_writeback(const void *d_addr)
52{
53  ISR_Level level;
54
55  _ISR_Local_disable (level);
56
57  _OR1K_mtspr(CPU_OR1K_SPR_DCBWR, (uintptr_t) d_addr);
58
59  _ISR_Local_enable(level);
60}
61
62static inline void _CPU_OR1K_Cache_data_block_lock(const void *d_addr)
63{
64  ISR_Level level;
65
66  _ISR_Local_disable (level);
67
68  _OR1K_mtspr(CPU_OR1K_SPR_DCBLR, (uintptr_t) d_addr);
69
70  _ISR_Local_enable(level);
71}
72
73static inline void _CPU_OR1K_Cache_instruction_block_prefetch
74(const void *d_addr)
75{
76  ISR_Level level;
77
78  _ISR_Local_disable (level);
79
80  _OR1K_mtspr(CPU_OR1K_SPR_ICBPR, (uintptr_t) d_addr);
81
82  _ISR_Local_enable(level);
83}
84
85static inline void _CPU_OR1K_Cache_instruction_block_lock
86(const void *d_addr)
87{
88  ISR_Level level;
89
90  _ISR_Local_disable (level);
91
92  _OR1K_mtspr(CPU_OR1K_SPR_ICBLR, (uintptr_t) d_addr);
93
94  _ISR_Local_enable(level);
95}
96
97/* Implement RTEMS cache manager functions */
98
99static void _CPU_cache_flush_1_data_line(const void *d_addr)
100{
101  ISR_Level level;
102
103  _ISR_Local_disable (level);
104
105  _OR1K_mtspr(CPU_OR1K_SPR_DCBFR, (uintptr_t) d_addr);
106
107  //__asm__ volatile("l.csync");
108
109  _ISR_Local_enable(level);
110}
111
112static void _CPU_cache_invalidate_1_data_line(const void *d_addr)
113{
114  ISR_Level level;
115
116  _ISR_Local_disable (level);
117
118  _OR1K_mtspr(CPU_OR1K_SPR_DCBIR, (uintptr_t) d_addr);
119
120  _ISR_Local_enable(level);
121}
122
123static void _CPU_cache_freeze_data(void)
124{
125  /* Do nothing */
126}
127
128static void _CPU_cache_unfreeze_data(void)
129{
130  /* Do nothing */
131}
132
133static void _CPU_cache_invalidate_1_instruction_line(const void *d_addr)
134{
135  ISR_Level level;
136
137  _ISR_Local_disable (level);
138
139  _OR1K_mtspr(CPU_OR1K_SPR_ICBIR, (uintptr_t) d_addr);
140
141  _ISR_Local_enable(level);
142}
143
144static void _CPU_cache_freeze_instruction(void)
145{
146  /* Do nothing */
147}
148
149static void _CPU_cache_unfreeze_instruction(void)
150{
151  /* Do nothing */
152}
153
154static void _CPU_cache_flush_entire_data(void)
155{
156  size_t addr;
157  ISR_Level level;
158
159  _ISR_Local_disable (level);
160
161  /* We have only 0 level cache so we do not need to invalidate others */
162  for (
163      addr = _CPU_cache_get_data_cache_size(0);
164      addr > 0;
165      addr -= CPU_DATA_CACHE_ALIGNMENT
166  ) {
167    _OR1K_mtspr(CPU_OR1K_SPR_DCBFR, (uintptr_t) addr);
168  }
169
170  _ISR_Local_enable (level);
171}
172
173static void _CPU_cache_invalidate_entire_data(void)
174{
175  size_t addr;
176  ISR_Level level;
177
178  _ISR_Local_disable (level);
179
180  /* We have only 0 level cache so we do not need to invalidate others */
181  for (
182      addr = _CPU_cache_get_data_cache_size(0);
183      addr > 0;
184      addr -= CPU_DATA_CACHE_ALIGNMENT
185  ) {
186    _OR1K_mtspr(CPU_OR1K_SPR_DCBIR, (uintptr_t) addr);
187  }
188
189  _ISR_Local_enable (level);
190}
191
192static void _CPU_cache_invalidate_entire_instruction(void)
193{
194  size_t addr;
195  ISR_Level level;
196
197  _ISR_Local_disable (level);
198
199  /* We have only 0 level cache so we do not need to invalidate others */
200  for (
201      addr = _CPU_cache_get_instruction_cache_size(0);
202      addr > 0;
203      addr -= CPU_INSTRUCTION_CACHE_ALIGNMENT
204  ) {
205    _OR1K_mtspr(CPU_OR1K_SPR_ICBIR, (uintptr_t) addr);
206  }
207
208  /* Flush instructions out of instruction buffer */
209  __asm__ volatile("l.nop");
210  __asm__ volatile("l.nop");
211  __asm__ volatile("l.nop");
212  __asm__ volatile("l.nop");
213  __asm__ volatile("l.nop");
214
215  _ISR_Local_enable (level);
216}
217
218/*
219 * The range functions are copied almost verbatim from the generic
220 * implementations in c/src/lib/libcpu/shared/src/cache_manager.c. The main
221 * modification here is avoiding reapeated off/on toggling of the ISR for each
222 * cache line operation.
223 */
224
225static void _CPU_cache_flush_data_range(const void *d_addr, size_t n_bytes)
226{
227  const void * final_address;
228  ISR_Level level;
229
230 /*
231  * Set d_addr to the beginning of the cache line; final_address indicates
232  * the last address_t which needs to be pushed. Increment d_addr and push
233  * the resulting line until final_address is passed.
234  */
235
236  if( n_bytes == 0 )
237    /* Do nothing if number of bytes to flush is zero */
238    return;
239
240  final_address = (void *)((size_t)d_addr + n_bytes - 1);
241  d_addr = (void *)((size_t)d_addr & ~(CPU_DATA_CACHE_ALIGNMENT - 1));
242
243  if( final_address - d_addr > _CPU_cache_get_data_cache_size(0) ) {
244    /*
245     * Avoid iterating over the whole cache multiple times if the range is
246     * larger than the cache size.
247     */
248    _CPU_cache_flush_entire_data();
249    return;
250  }
251
252  _ISR_Local_disable (level);
253
254  while( d_addr <= final_address )  {
255    _OR1K_mtspr(CPU_OR1K_SPR_DCBFR, (uintptr_t) d_addr);
256    d_addr = (void *)((size_t)d_addr + CPU_DATA_CACHE_ALIGNMENT);
257  }
258
259  _ISR_Local_enable (level);
260}
261
262static void _CPU_cache_invalidate_data_range(const void *d_addr, size_t n_bytes)
263{
264  const void * final_address;
265  ISR_Level level;
266
267 /*
268  * Set d_addr to the beginning of the cache line; final_address indicates
269  * the last address_t which needs to be pushed. Increment d_addr and push
270  * the resulting line until final_address is passed.
271  */
272
273  if( n_bytes == 0 )
274    /* Do nothing if number of bytes to flush is zero */
275    return;
276
277  final_address = (void *)((size_t)d_addr + n_bytes - 1);
278  d_addr = (void *)((size_t)d_addr & ~(CPU_DATA_CACHE_ALIGNMENT - 1));
279
280  if( final_address - d_addr > _CPU_cache_get_data_cache_size(0) ) {
281    /*
282     * Avoid iterating over the whole cache multiple times if the range is
283     * larger than the cache size.
284     */
285    _CPU_cache_invalidate_entire_data();
286    return;
287  }
288
289  _ISR_Local_disable (level);
290
291  while( d_addr <= final_address )  {
292    _OR1K_mtspr(CPU_OR1K_SPR_DCBIR, (uintptr_t) d_addr);
293    d_addr = (void *)((size_t)d_addr + CPU_DATA_CACHE_ALIGNMENT);
294  }
295
296  _ISR_Local_enable (level);
297}
298
299static void _CPU_cache_invalidate_instruction_range(const void *i_addr, size_t n_bytes)
300{
301  const void * final_address;
302  ISR_Level level;
303
304 /*
305  * Set i_addr to the beginning of the cache line; final_address indicates
306  * the last address_t which needs to be pushed. Increment i_addr and push
307  * the resulting line until final_address is passed.
308  */
309
310  if( n_bytes == 0 )
311    /* Do nothing if number of bytes to flush is zero */
312    return;
313
314  final_address = (void *)((size_t)i_addr + n_bytes - 1);
315  i_addr = (void *)((size_t)i_addr & ~(CPU_INSTRUCTION_CACHE_ALIGNMENT - 1));
316
317  if( final_address - i_addr > _CPU_cache_get_data_cache_size(0) ) {
318    /*
319     * Avoid iterating over the whole cache multiple times if the range is
320     * larger than the cache size.
321     */
322    _CPU_cache_invalidate_entire_instruction();
323    return;
324  }
325
326  _ISR_Local_disable (level);
327
328  while( i_addr <= final_address )  {
329    _OR1K_mtspr(CPU_OR1K_SPR_ICBIR, (uintptr_t) i_addr);
330    i_addr = (void *)((size_t)i_addr + CPU_DATA_CACHE_ALIGNMENT);
331  }
332
333  _ISR_Local_enable (level);
334}
335
336static void _CPU_cache_enable_data(void)
337{
338  uint32_t sr;
339  ISR_Level level;
340
341  _ISR_Local_disable (level);
342
343  sr = _OR1K_mfspr(CPU_OR1K_SPR_SR);
344  _OR1K_mtspr(CPU_OR1K_SPR_SR, sr | CPU_OR1K_SPR_SR_DCE);
345
346  _ISR_Local_enable(level);
347}
348
349static void _CPU_cache_disable_data(void)
350{
351  uint32_t sr;
352  ISR_Level level;
353
354  _ISR_Local_disable (level);
355
356  sr = _OR1K_mfspr(CPU_OR1K_SPR_SR);
357  _OR1K_mtspr(CPU_OR1K_SPR_SR, (sr & ~CPU_OR1K_SPR_SR_DCE));
358
359  _ISR_Local_enable(level);
360}
361
362static void _CPU_cache_enable_instruction(void)
363{
364  uint32_t sr;
365  ISR_Level level;
366
367  _ISR_Local_disable (level);
368
369  sr = _OR1K_mfspr(CPU_OR1K_SPR_SR);
370  _OR1K_mtspr(CPU_OR1K_SPR_SR, sr | CPU_OR1K_SPR_SR_ICE);
371
372  _ISR_Local_enable(level);
373}
374
375static void _CPU_cache_disable_instruction(void)
376{
377  uint32_t sr;
378  ISR_Level level;
379
380  _ISR_Local_disable (level);
381
382  sr = _OR1K_mfspr(CPU_OR1K_SPR_SR);
383  _OR1K_mtspr(CPU_OR1K_SPR_SR, (sr & ~CPU_OR1K_SPR_SR_ICE));
384
385  _ISR_Local_enable(level);
386}
387
388#include "../../../shared/cache/cacheimpl.h"
Note: See TracBrowser for help on using the repository browser.