]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/cpu-arm.cpp
d860118507f303806558a4b4a60f639b11d54d47
[l4.git] / kernel / fiasco / src / kern / arm / cpu-arm.cpp
1 INTERFACE [arm]:
2
3 #include "io.h"
4 #include "mem_layout.h"
5 #include "mem_unit.h"
6 #include "types.h"
7 #include "per_cpu_data.h"
8 #include "processor.h"
9
10 EXTENSION
11 class Cpu
12 {
13 public:
14   void init(bool is_boot_cpu = false);
15
16   static void early_init();
17
18   static Per_cpu<Cpu> cpus;
19   static Cpu *boot_cpu() { return _boot_cpu; }
20
21   enum {
22     Cp15_c1_mmu             = 1 << 0,
23     Cp15_c1_alignment_check = 1 << 1,
24     Cp15_c1_cache           = 1 << 2,
25     Cp15_c1_branch_predict  = 1 << 11,
26     Cp15_c1_insn_cache      = 1 << 12,
27     Cp15_c1_high_vector     = 1 << 13,
28   };
29
30   Cpu(unsigned id) { set_id(id); }
31
32 private:
33   static Cpu *_boot_cpu;
34
35   unsigned _phys_id;
36 };
37
38 // ------------------------------------------------------------------------
39 INTERFACE [arm && armv5]:
40
41 EXTENSION class Cpu
42 {
43 public:
44   enum {
45     Cp15_c1_write_buffer    = 1 << 3,
46     Cp15_c1_prog32          = 1 << 4,
47     Cp15_c1_data32          = 1 << 5,
48     Cp15_c1_late_abort      = 1 << 6,
49     Cp15_c1_big_endian      = 1 << 7,
50     Cp15_c1_system_protect  = 1 << 8,
51     Cp15_c1_rom_protect     = 1 << 9,
52     Cp15_c1_f               = 1 << 10,
53     Cp15_c1_rr              = 1 << 14,
54     Cp15_c1_l4              = 1 << 15,
55
56     Cp15_c1_generic         = Cp15_c1_mmu
57                               | (Config::Cp15_c1_use_alignment_check ?  Cp15_c1_alignment_check : 0)
58                               | Cp15_c1_write_buffer
59                               | Cp15_c1_prog32
60                               | Cp15_c1_data32
61                               | Cp15_c1_late_abort
62                               | Cp15_c1_rom_protect
63                               | Cp15_c1_high_vector,
64
65     Cp15_c1_cache_bits      = Cp15_c1_cache
66                               | Cp15_c1_insn_cache
67                               | Cp15_c1_write_buffer,
68
69   };
70 };
71
72 INTERFACE [arm && armv6]:
73
74 EXTENSION class Cpu
75 {
76 public:
77   enum {
78     Cp15_c1_l4              = 1 << 15,
79     Cp15_c1_u               = 1 << 22,
80     Cp15_c1_xp              = 1 << 23,
81     Cp15_c1_ee              = 1 << 25,
82     Cp15_c1_nmfi            = 1 << 27,
83     Cp15_c1_tex             = 1 << 28,
84     Cp15_c1_force_ap        = 1 << 29,
85
86     Cp15_c1_generic         = Cp15_c1_mmu
87                               | (Config::Cp15_c1_use_alignment_check ?  Cp15_c1_alignment_check : 0)
88                               | Cp15_c1_branch_predict
89                               | Cp15_c1_high_vector
90                               | Cp15_c1_u
91                               | Cp15_c1_xp,
92
93     Cp15_c1_cache_bits      = Cp15_c1_cache
94                               | Cp15_c1_insn_cache,
95
96     Smp_enable              = 0x20,
97   };
98 };
99
100 INTERFACE [arm && armv7 && armca8]:
101
102 EXTENSION class Cpu
103 {
104 public:
105   enum {
106     Cp15_c1_ee              = 1 << 25,
107     Cp15_c1_nmfi            = 1 << 27,
108     Cp15_c1_tre             = 1 << 28,
109     Cp15_c1_afe             = 1 << 29,
110     Cp15_c1_te              = 1 << 30,
111
112     Cp15_c1_cache_bits      = Cp15_c1_cache
113                               | Cp15_c1_insn_cache,
114
115     Cp15_c1_generic         = Cp15_c1_mmu
116                               | (Config::Cp15_c1_use_alignment_check ?  Cp15_c1_alignment_check : 0)
117                               | Cp15_c1_branch_predict
118                               | Cp15_c1_high_vector,
119   };
120 };
121
122 INTERFACE [arm && armv7 && armca9]:
123
124 EXTENSION class Cpu
125 {
126 public:
127   enum {
128     Cp15_c1_sw              = 1 << 10,
129     Cp15_c1_ha              = 1 << 17,
130     Cp15_c1_ee              = 1 << 25,
131     Cp15_c1_nmfi            = 1 << 27,
132     Cp15_c1_tre             = 1 << 28,
133     Cp15_c1_afe             = 1 << 29,
134     Cp15_c1_te              = 1 << 30,
135
136     Cp15_c1_cache_bits      = Cp15_c1_cache
137                               | Cp15_c1_insn_cache,
138
139     Cp15_c1_generic         = Cp15_c1_mmu
140                               | (Config::Cp15_c1_use_alignment_check ?  Cp15_c1_alignment_check : 0)
141                               | Cp15_c1_branch_predict
142                               | Cp15_c1_high_vector
143                               | (Config::Cp15_c1_use_a9_swp_enable ?  Cp15_c1_sw : 0),
144
145     Smp_enable              = 0x41,
146   };
147 };
148
149 INTERFACE [arm]:
150
151 EXTENSION class Cpu
152 {
153 public:
154   enum {
155     Cp15_c1_cache_enabled  = Cp15_c1_generic | Cp15_c1_cache_bits,
156     Cp15_c1_cache_disabled = Cp15_c1_generic,
157   };
158 };
159
160 //---------------------------------------------------------------------------
161 IMPLEMENTATION [arm && (mpcore || armca9)]:
162
163 PUBLIC static inline void
164 Cpu::early_init_platform()
165 {
166   Io::write<Mword>(0xffffffff, Mem_layout::Mp_scu_map_base + 0xc);
167   Io::write<Mword>(1,          Mem_layout::Mp_scu_map_base + 0);
168
169   Io::write<Mword>(Io::read<Mword>(Mem_layout::Gic_cpu_map_base + 0) | 1,
170                    Mem_layout::Gic_cpu_map_base + 0);
171   Io::write<Mword>(Io::read<Mword>(Mem_layout::Gic_dist_map_base + 0) | 1,
172                    Mem_layout::Gic_dist_map_base + 0);
173
174   Mem_unit::clean_dcache();
175
176   Mword tmp = 0;
177   __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1   \n"
178                        "orr %0, %1                  \n"
179                        "mcr p15, 0, %0, c1, c0, 1   \n"
180                        : : "r" (tmp), "i" (Smp_enable));
181 }
182
183 //---------------------------------------------------------------------------
184 IMPLEMENTATION [arm && !(mpcore || armca9)]:
185
186 PUBLIC static inline void Cpu::early_init_platform()
187 {}
188
189 //---------------------------------------------------------------------------
190 IMPLEMENTATION [arm]:
191
192 #include <cstdio>
193 #include <cstring>
194 #include <panic.h>
195
196 #include "io.h"
197 #include "pagetable.h"
198 #include "kmem_space.h"
199 #include "mem_unit.h"
200 #include "processor.h"
201 #include "ram_quota.h"
202
203 Per_cpu<Cpu> DEFINE_PER_CPU_P(0) Cpu::cpus(true);
204 Cpu *Cpu::_boot_cpu;
205
206 PUBLIC static inline
207 Mword
208 Cpu::stack_align(Mword stack)
209 { return stack & ~0x3; }
210
211
212 IMPLEMENT
213 void Cpu::early_init()
214 {
215   // switch to supervisor mode and intialize the memory system
216   asm volatile ( " mov  r2, r13             \n"
217                  " mov  r3, r14             \n"
218                  " msr  cpsr_c, %1          \n"
219                  " mov  r13, r2             \n"
220                  " mov  r14, r3             \n"
221
222                  " mcr  p15, 0, %0, c1, c0  \n"
223                  :
224                  : "r" (Config::cache_enabled
225                         ? Cp15_c1_cache_enabled : Cp15_c1_cache_disabled),
226                    "I" (0x0d3)
227                  : "r2", "r3");
228
229   early_init_platform();
230
231   Mem_unit::flush_cache();
232
233   print_infos();
234 }
235
236
237 PUBLIC static inline
238 bool
239 Cpu::have_superpages()
240 { return true; }
241
242 PUBLIC static inline
243 void
244 Cpu::debugctl_enable()
245 {}
246
247 PUBLIC static inline
248 void
249 Cpu::debugctl_disable()
250 {}
251
252 PUBLIC static inline NEEDS["types.h"]
253 Unsigned32
254 Cpu::get_scaler_tsc_to_ns()
255 { return 0; }
256
257 PUBLIC static inline NEEDS["types.h"]
258 Unsigned32
259 Cpu::get_scaler_tsc_to_us()
260 { return 0; }
261
262 PUBLIC static inline NEEDS["types.h"]
263 Unsigned32
264 Cpu::get_scaler_ns_to_tsc()
265 { return 0; }
266
267 PUBLIC static inline
268 bool
269 Cpu::tsc()
270 { return 0; }
271
272 PUBLIC static inline
273 Unsigned64
274 Cpu::rdtsc (void)
275 { return 0; }
276
277 PUBLIC static
278 void Cpu::init_mmu()
279 {
280   extern char ivt_start;
281   // map the interrupt vector table to 0xffff0000
282   Pte pte = Kmem_space::kdir()->walk((void*)Kmem_space::Ivt_base, 4096,
283       true, Ram_quota::root);
284
285   pte.set((unsigned long)&ivt_start, 4096, 
286       Mem_page_attr(Page::KERN_RW | Page::CACHEABLE),
287       true);
288
289   Mem_unit::tlb_flush();
290 }
291
292 IMPLEMENT inline
293 unsigned
294 Cpu::phys_id() const
295 { return _phys_id; }
296
297 IMPLEMENT
298 void
299 Cpu::init(bool is_boot_cpu)
300 {
301   if (is_boot_cpu)
302     {
303       _boot_cpu = this;
304       set_online(1);
305     }
306
307   _phys_id = Proc::cpu_id();
308
309   init_tz();
310 }
311
312 //---------------------------------------------------------------------------
313 IMPLEMENTATION [arm && !tz]:
314
315 PRIVATE static inline
316 void
317 Cpu::init_tz()
318 {}
319
320 //---------------------------------------------------------------------------
321 INTERFACE [arm && tz]:
322
323 EXTENSION class Cpu
324 {
325 public:
326
327   static char monitor_vector_base asm ("monitor_vector_base");
328 };
329
330 //---------------------------------------------------------------------------
331 IMPLEMENTATION [arm && tz]:
332
333 PRIVATE inline
334 void
335 Cpu::init_tz()
336 {
337   // set monitor vector base address
338   assert(!((Mword)&monitor_vector_base & 31));
339   tz_mvbar((Mword)&monitor_vector_base);
340
341   // enable nonsecure access to vfp coprocessor
342   asm volatile("mov r0, #0xc00;"
343                "mcr p15, 0, r0, c1, c1, 2;"
344                : : : "r0"
345               );
346
347   enable_irq_ovrr();
348 }
349
350 PUBLIC inline
351 void
352 Cpu::tz_switch_to_ns(Mword *nonsecure_state)
353 {
354   volatile register Mword r0 asm("r0") = (Mword)nonsecure_state;
355   extern char go_nonsecure;
356
357   asm volatile("stmdb sp!, {fp}   \n"
358                "stmdb sp!, {r0}   \n"
359                "mov    r2, sp     \n" // copy sp_svc to sp_mon
360                "cps    #0x16      \n" // switch to monitor mode
361                "mov    sp, r2     \n"
362                "adr    r3, 1f     \n" // save return eip
363                "mrs    r4, cpsr   \n" // save return psr
364                "mov    pc, r1     \n" // go nonsecure!
365                "1:                \n"
366                "mov    r0, sp     \n" // copy sp_mon to sp_svc
367                "cps    #0x13      \n" // switch to svc mode
368                "mov    sp, r0     \n"
369                "ldmia  sp!, {r0}  \n"
370                "ldmia  sp!, {fp}  \n"
371                : : "r" (r0), "r" (&go_nonsecure)
372                : "r2", "r3", "r4", "r5", "r6", "r7",
373                  "r8", "r9", "r10", "r12", "r14", "memory");
374 }
375
376 PUBLIC static inline
377 Mword
378 Cpu::tz_scr()
379 {
380   Mword r;
381   asm volatile ("mrc p15, 0, %0, c1, c1, 0" : "=r" (r));
382   return r;
383 }
384
385 PUBLIC static inline
386 void
387 Cpu::tz_scr(Mword val)
388 {
389   asm volatile ("mcr p15, 0, %0, c1, c1, 0" : : "r" (val));
390 }
391
392 PUBLIC static inline
393 Mword
394 Cpu::tz_mvbar()
395 {
396   Mword r;
397   asm volatile ("mrc p15, 0, %0, c12, c0, 1" : "=r" (r));
398   return r;
399 }
400
401 PUBLIC static inline
402 void
403 Cpu::tz_mvbar(Mword val)
404 {
405   asm volatile ("mcr p15, 0, %0, c12, c0, 1" : : "r" (val));
406 }
407
408 // ------------------------------------------------------------------------
409 IMPLEMENTATION [arm && tz && armca9]:
410
411 PUBLIC static inline
412 void
413 Cpu::enable_irq_ovrr()
414 {
415   // set IRQ/FIQ/Abort override bits
416   asm volatile("mov r0, #0x1c0            \n"
417                "mcr p15, 0, r0, c1, c1, 3 \n"
418                : : : "r0");
419 }
420
421 IMPLEMENTATION [!tz || !armca9]:
422
423 PUBLIC static inline
424 void
425 Cpu::enable_irq_ovrr()
426 {}
427
428 // ------------------------------------------------------------------------
429 IMPLEMENTATION [!debug]:
430
431 PRIVATE static inline
432 void
433 Cpu::print_infos()
434 {}
435
436 // ------------------------------------------------------------------------
437 IMPLEMENTATION [debug]:
438
439 PRIVATE static
440 void
441 Cpu::print_infos()
442 {
443   printf("Cache config: %s\n", Config::cache_enabled ? "ON" : "OFF");
444 }