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