]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/outer_cache-l2cxx0.cpp
15e96d62a4fede421eca37959a3c315d4c30759e
[l4.git] / kernel / fiasco / src / kern / arm / outer_cache-l2cxx0.cpp
1 INTERFACE [arm && outer_cache_l2cxx0]:
2
3 #include "mem_layout.h"
4 #include "spin_lock.h"
5
6 EXTENSION class Outer_cache
7 {
8 private:
9   enum
10   {
11     Cache_line_shift = 5,
12
13     CACHE_ID                       = Mem_layout::L2cxx0_map_base + 0x000,
14     CACHE_TYPE                     = Mem_layout::L2cxx0_map_base + 0x004,
15     CONTROL                        = Mem_layout::L2cxx0_map_base + 0x100,
16     AUX_CONTROL                    = Mem_layout::L2cxx0_map_base + 0x104,
17     TAG_RAM_CONTROL                = Mem_layout::L2cxx0_map_base + 0x108,
18     DATA_RAM_CONTROL               = Mem_layout::L2cxx0_map_base + 0x10c,
19     EVENT_COUNTER_CONTROL          = Mem_layout::L2cxx0_map_base + 0x200,
20     EVENT_COUTNER1_CONFIG          = Mem_layout::L2cxx0_map_base + 0x204,
21     EVENT_COUNTER0_CONFIG          = Mem_layout::L2cxx0_map_base + 0x208,
22     EVENT_COUNTER1_VALUE           = Mem_layout::L2cxx0_map_base + 0x20c,
23     EVENT_COUNTER0_VALUE           = Mem_layout::L2cxx0_map_base + 0x210,
24     INTERRUPT_MASK                 = Mem_layout::L2cxx0_map_base + 0x214,
25     MASKED_INTERRUPT_STATUS        = Mem_layout::L2cxx0_map_base + 0x218,
26     RAW_INTERRUPT_STATUS           = Mem_layout::L2cxx0_map_base + 0x21c,
27     INTERRUPT_CLEAR                = Mem_layout::L2cxx0_map_base + 0x220,
28     CACHE_SYNC                     = Mem_layout::L2cxx0_map_base + 0x730,
29     INVALIDATE_LINE_BY_PA          = Mem_layout::L2cxx0_map_base + 0x770,
30     INVALIDATE_BY_WAY              = Mem_layout::L2cxx0_map_base + 0x77c,
31     CLEAN_LINE_BY_PA               = Mem_layout::L2cxx0_map_base + 0x7b0,
32     CLEAN_LINE_BY_INDEXWAY         = Mem_layout::L2cxx0_map_base + 0x7bb,
33     CLEAN_BY_WAY                   = Mem_layout::L2cxx0_map_base + 0x7bc,
34     CLEAN_AND_INV_LINE_BY_PA       = Mem_layout::L2cxx0_map_base + 0x7f0,
35     CLEAN_AND_INV_LINE_BY_INDEXWAY = Mem_layout::L2cxx0_map_base + 0x7f8,
36     CLEAN_AND_INV_BY_WAY           = Mem_layout::L2cxx0_map_base + 0x7fc,
37     LOCKDOWN_BY_WAY_D_SIDE         = Mem_layout::L2cxx0_map_base + 0x900,
38     LOCKDOWN_BY_WAY_I_SIDE         = Mem_layout::L2cxx0_map_base + 0x904,
39     TEST_OPERATION                 = Mem_layout::L2cxx0_map_base + 0xf00,
40     LINE_TAG                       = Mem_layout::L2cxx0_map_base + 0xf30,
41     DEBUG_CONTROL_REGISTER         = Mem_layout::L2cxx0_map_base + 0xf40,
42   };
43
44   static Spin_lock<> _lock;
45
46   static Mword platform_init(Mword aux);
47
48   static bool need_sync;
49   static unsigned waymask;
50
51 public:
52   enum
53   {
54     Cache_line_size = 1 << Cache_line_shift,
55     Cache_line_mask = Cache_line_size - 1,
56   };
57 };
58
59 // ------------------------------------------------------------------------
60 IMPLEMENTATION [arm && outer_cache_l2cxx0]:
61
62 #include "io.h"
63 #include "lock_guard.h"
64 #include "static_init.h"
65
66 Spin_lock<> Outer_cache::_lock;
67 bool Outer_cache::need_sync;
68 unsigned Outer_cache::waymask;
69
70 IMPLEMENT inline NEEDS ["io.h"]
71 void
72 Outer_cache::sync()
73 {
74   while (Io::read<Mword>(CACHE_SYNC))
75     Proc::preemption_point();
76 }
77
78 PRIVATE static inline NEEDS ["io.h", "lock_guard.h"]
79 void
80 Outer_cache::write(Address reg, Mword val, bool before = false)
81 {
82   auto guard = lock_guard(_lock);
83   if (before)
84     while (Io::read<Mword>(reg) & 1)
85       ;
86   Io::write<Mword>(val, reg);
87   if (!before)
88     while (Io::read<Mword>(reg) & 1)
89       ;
90 }
91
92 IMPLEMENT inline NEEDS[Outer_cache::write]
93 void
94 Outer_cache::clean()
95 {
96   write(CLEAN_BY_WAY, waymask);
97   sync();
98 }
99
100 IMPLEMENT inline NEEDS[Outer_cache::write]
101 void
102 Outer_cache::clean(Mword phys_addr, bool do_sync = true)
103 {
104   write(CLEAN_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift));
105   if (need_sync && do_sync)
106     sync();
107 }
108
109 IMPLEMENT inline NEEDS[Outer_cache::write]
110 void
111 Outer_cache::flush()
112 {
113   write(CLEAN_AND_INV_BY_WAY, waymask);
114   sync();
115 }
116
117 IMPLEMENT inline NEEDS[Outer_cache::write]
118 void
119 Outer_cache::flush(Mword phys_addr, bool do_sync = true)
120 {
121   write(CLEAN_AND_INV_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift));
122   if (need_sync && do_sync)
123     sync();
124 }
125
126 IMPLEMENT inline NEEDS[Outer_cache::write]
127 void
128 Outer_cache::invalidate()
129 {
130   write(INVALIDATE_BY_WAY, waymask);
131   sync();
132 }
133
134 IMPLEMENT inline NEEDS[Outer_cache::write]
135 void
136 Outer_cache::invalidate(Address phys_addr, bool do_sync = true)
137 {
138   write(INVALIDATE_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift));
139   if (need_sync && do_sync)
140     sync();
141 }
142
143 PUBLIC static
144 void
145 Outer_cache::initialize(bool v)
146 {
147   Mword cache_id   = Io::read<Mword>(CACHE_ID);
148   Mword aux        = Io::read<Mword>(AUX_CONTROL);
149   unsigned ways    = 8;
150
151   need_sync = true;
152
153   aux = platform_init(aux);
154
155   switch ((cache_id >> 6) & 0xf)
156     {
157     case 1:
158       ways = (aux >> 13) & 0xf;
159       break;
160     case 3:
161       need_sync = false;
162       ways = aux & (1 << 16) ? 16 : 8;
163       break;
164     default:
165       break;
166     }
167
168   waymask = (1 << ways) - 1;
169
170   Io::write<Mword>(0,    INTERRUPT_MASK);
171   Io::write<Mword>(~0UL, INTERRUPT_CLEAR);
172
173   if (!(Io::read<Mword>(CONTROL) & 1))
174     {
175       Io::write(aux, AUX_CONTROL);
176       invalidate();
177       Io::write<Mword>(1, CONTROL);
178     }
179
180   if (v)
181     show_info(ways, cache_id, aux);
182 }
183
184 PUBLIC static
185 void
186 Outer_cache::init()
187 {
188   initialize(true);
189 }
190
191 STATIC_INITIALIZE_P(Outer_cache, STARTUP_INIT_PRIO);
192
193 // ------------------------------------------------------------------------
194 IMPLEMENTATION [arm && outer_cache_l2cxx0 && !debug]:
195
196 PRIVATE static
197 void
198 Outer_cache::show_info(unsigned, Mword, Mword)
199 {}
200
201 // ------------------------------------------------------------------------
202 IMPLEMENTATION [arm && outer_cache_l2cxx0 && debug]:
203
204 #include "io.h"
205 #include <cstdio>
206
207 PRIVATE static
208 void
209 Outer_cache::show_info(unsigned ways, Mword cache_id, Mword aux)
210 {
211   printf("L2: ID=%08lx Type=%08lx Aux=%08lx WMask=%x S=%d\n",
212          cache_id, Io::read<Mword>(CACHE_TYPE), aux, waymask, need_sync);
213
214   const char *type;
215   switch ((cache_id >> 6) & 0xf)
216     {
217     case 1:
218       type = "210";
219       break;
220     case 2:
221       type = "220";
222       break;
223     case 3:
224       type = "310";
225       if (cache_id & 0x3f == 5)
226         printf("L2: r3p0\n");
227       break;
228     default:
229       type = "Unknown";
230       break;
231     }
232
233   unsigned waysize = 16 << (((aux >> 17) & 7) - 1);
234   printf("L2: Type L2C-%s Size = %dkB\n", type, ways * waysize);
235 }