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 01/27/18 at 13:37:51

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
RevLine 
[c080c343]1/*
[3b4ddaf]2 * COPYRIGHT (c) 2014, 2016 ÅAC Microtec AB <www.aacmicrotec.com>
[e639c026]3 * Contributor(s):
4 *  Karol Gugala <kgugala@antmicro.com>
[3b4ddaf]5 *  Martin Werner <martin.werner@aacmicrotec.com>
[e639c026]6 *
[c080c343]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>
[48fed9a]20#include <rtems/score/percpu.h>
[4cf93658]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}
[c080c343]39
40static inline void _CPU_OR1K_Cache_data_block_prefetch(const void *d_addr)
41{
42  ISR_Level level;
43
[24713163]44  _ISR_Local_disable (level);
[c080c343]45
[37885d5d]46  _OR1K_mtspr(CPU_OR1K_SPR_DCBPR, (uintptr_t) d_addr);
[c080c343]47
[24713163]48  _ISR_Local_enable(level);
[c080c343]49}
50
51static inline void _CPU_OR1K_Cache_data_block_writeback(const void *d_addr)
52{
[4dcaa48]53  ISR_Level level;
54
[24713163]55  _ISR_Local_disable (level);
[c080c343]56
[37885d5d]57  _OR1K_mtspr(CPU_OR1K_SPR_DCBWR, (uintptr_t) d_addr);
[c080c343]58
[24713163]59  _ISR_Local_enable(level);
[c080c343]60}
61
62static inline void _CPU_OR1K_Cache_data_block_lock(const void *d_addr)
63{
[4dcaa48]64  ISR_Level level;
65
[24713163]66  _ISR_Local_disable (level);
[c080c343]67
[37885d5d]68  _OR1K_mtspr(CPU_OR1K_SPR_DCBLR, (uintptr_t) d_addr);
[c080c343]69
[24713163]70  _ISR_Local_enable(level);
[c080c343]71}
72
73static inline void _CPU_OR1K_Cache_instruction_block_prefetch
74(const void *d_addr)
75{
[4dcaa48]76  ISR_Level level;
77
[24713163]78  _ISR_Local_disable (level);
[c080c343]79
[37885d5d]80  _OR1K_mtspr(CPU_OR1K_SPR_ICBPR, (uintptr_t) d_addr);
[c080c343]81
[24713163]82  _ISR_Local_enable(level);
[c080c343]83}
84
85static inline void _CPU_OR1K_Cache_instruction_block_lock
86(const void *d_addr)
87{
[4dcaa48]88  ISR_Level level;
89
[24713163]90  _ISR_Local_disable (level);
[c080c343]91
[37885d5d]92  _OR1K_mtspr(CPU_OR1K_SPR_ICBLR, (uintptr_t) d_addr);
[c080c343]93
[24713163]94  _ISR_Local_enable(level);
[c080c343]95}
96
97/* Implement RTEMS cache manager functions */
98
[4cf93658]99static void _CPU_cache_flush_1_data_line(const void *d_addr)
[c080c343]100{
[4dcaa48]101  ISR_Level level;
102
[24713163]103  _ISR_Local_disable (level);
[c080c343]104
[3b4ddaf]105  _OR1K_mtspr(CPU_OR1K_SPR_DCBFR, (uintptr_t) d_addr);
[c080c343]106
[4dcaa48]107  //__asm__ volatile("l.csync");
[c080c343]108
[24713163]109  _ISR_Local_enable(level);
[c080c343]110}
111
[4cf93658]112static void _CPU_cache_invalidate_1_data_line(const void *d_addr)
[c080c343]113{
[4dcaa48]114  ISR_Level level;
115
[24713163]116  _ISR_Local_disable (level);
[c080c343]117
[3b4ddaf]118  _OR1K_mtspr(CPU_OR1K_SPR_DCBIR, (uintptr_t) d_addr);
[c080c343]119
[24713163]120  _ISR_Local_enable(level);
[c080c343]121}
122
[4cf93658]123static void _CPU_cache_freeze_data(void)
[c080c343]124{
125  /* Do nothing */
126}
127
[4cf93658]128static void _CPU_cache_unfreeze_data(void)
[c080c343]129{
130  /* Do nothing */
131}
132
[4cf93658]133static void _CPU_cache_invalidate_1_instruction_line(const void *d_addr)
[c080c343]134{
[4dcaa48]135  ISR_Level level;
136
[24713163]137  _ISR_Local_disable (level);
[c080c343]138
[3b4ddaf]139  _OR1K_mtspr(CPU_OR1K_SPR_ICBIR, (uintptr_t) d_addr);
[c080c343]140
[24713163]141  _ISR_Local_enable(level);
[c080c343]142}
143
[4cf93658]144static void _CPU_cache_freeze_instruction(void)
[c080c343]145{
146  /* Do nothing */
147}
148
[4cf93658]149static void _CPU_cache_unfreeze_instruction(void)
[c080c343]150{
151  /* Do nothing */
152}
153
[4cf93658]154static void _CPU_cache_flush_entire_data(void)
[c080c343]155{
[3b4ddaf]156  size_t addr;
157  ISR_Level level;
158
159  _ISR_Local_disable (level);
[e639c026]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  ) {
[3b4ddaf]167    _OR1K_mtspr(CPU_OR1K_SPR_DCBFR, (uintptr_t) addr);
[e639c026]168  }
[3b4ddaf]169
170  _ISR_Local_enable (level);
[c080c343]171}
172
[4cf93658]173static void _CPU_cache_invalidate_entire_data(void)
[c080c343]174{
[3b4ddaf]175  size_t addr;
176  ISR_Level level;
177
178  _ISR_Local_disable (level);
[e639c026]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  ) {
[3b4ddaf]186    _OR1K_mtspr(CPU_OR1K_SPR_DCBIR, (uintptr_t) addr);
[e639c026]187  }
[3b4ddaf]188
189  _ISR_Local_enable (level);
[c080c343]190}
191
[4cf93658]192static void _CPU_cache_invalidate_entire_instruction(void)
[c080c343]193{
[3b4ddaf]194  size_t addr;
195  ISR_Level level;
196
197  _ISR_Local_disable (level);
[e639c026]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  ) {
[3b4ddaf]205    _OR1K_mtspr(CPU_OR1K_SPR_ICBIR, (uintptr_t) addr);
[e639c026]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");
[3b4ddaf]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
[4cf93658]225static void _CPU_cache_flush_data_range(const void *d_addr, size_t n_bytes)
[3b4ddaf]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
[9bf9068]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
[3b4ddaf]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
[4cf93658]262static void _CPU_cache_invalidate_data_range(const void *d_addr, size_t n_bytes)
[3b4ddaf]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
[9bf9068]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
[3b4ddaf]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
[4cf93658]299static void _CPU_cache_invalidate_instruction_range(const void *i_addr, size_t n_bytes)
[3b4ddaf]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
[9bf9068]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
[3b4ddaf]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);
[c080c343]334}
335
[4cf93658]336static void _CPU_cache_enable_data(void)
[c080c343]337{
[a59dd5c]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);
[c080c343]347}
348
[4cf93658]349static void _CPU_cache_disable_data(void)
[c080c343]350{
[a59dd5c]351  uint32_t sr;
352  ISR_Level level;
[c080c343]353
[a59dd5c]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);
[c080c343]360}
361
[4cf93658]362static void _CPU_cache_enable_instruction(void)
[c080c343]363{
[a59dd5c]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);
[c080c343]371
[a59dd5c]372  _ISR_Local_enable(level);
[c080c343]373}
374
[4cf93658]375static void _CPU_cache_disable_instruction(void)
[c080c343]376{
[a59dd5c]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);
[c080c343]386}
[4cf93658]387
388#include "../../../shared/cache/cacheimpl.h"
Note: See TracBrowser for help on using the repository browser.