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