4 #include "mem_layout.h"
7 #include "per_cpu_data.h"
14 void init(bool is_boot_cpu = false);
16 static void early_init();
18 static Per_cpu<Cpu> cpus;
19 static Cpu *boot_cpu() { return _boot_cpu; }
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,
30 Cpu(unsigned id) { set_id(id); }
34 Mword _pfr[2], _dfr0, _afr0, _mmfr[4];
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,
45 unsigned copro_dbg_model() const { return _cpu_id._dfr0 & 0xf; }
48 static Cpu *_boot_cpu;
54 // ------------------------------------------------------------------------
55 INTERFACE [arm && armv5]:
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,
72 Cp15_c1_generic = Cp15_c1_mmu
73 | (Config::Cp15_c1_use_alignment_check ? Cp15_c1_alignment_check : 0)
74 | Cp15_c1_write_buffer
79 | Cp15_c1_high_vector,
81 Cp15_c1_cache_bits = Cp15_c1_cache
83 | Cp15_c1_write_buffer,
88 INTERFACE [arm && armv6]:
98 Cp15_c1_nmfi = 1 << 27,
99 Cp15_c1_tex = 1 << 28,
100 Cp15_c1_force_ap = 1 << 29,
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
109 Cp15_c1_cache_bits = Cp15_c1_cache
110 | Cp15_c1_insn_cache,
114 INTERFACE [arm && armv7 && armca8]:
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),
125 Cp15_c1_cache_bits = Cp15_c1_cache
126 | Cp15_c1_insn_cache,
128 Cp15_c1_generic = Cp15_c1_mmu
129 | (Config::Cp15_c1_use_alignment_check ? Cp15_c1_alignment_check : 0)
130 | Cp15_c1_branch_predict
132 | Cp15_c1_high_vector,
136 INTERFACE [arm && armv7 && armca9]:
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),
149 Cp15_c1_cache_bits = Cp15_c1_cache
150 | Cp15_c1_insn_cache,
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
157 | (Config::Cp15_c1_use_a9_swp_enable ? Cp15_c1_sw : 0),
167 Cp15_c1_cache_enabled = Cp15_c1_generic | Cp15_c1_cache_bits,
168 Cp15_c1_cache_disabled = Cp15_c1_generic,
172 //---------------------------------------------------------------------------
173 IMPLEMENTATION [arm && armv6]:
175 PRIVATE static inline void
178 asm volatile ("mrc p15, 0, %0, c1, c0, 1 \n"
180 "mcr p15, 0, %0, c1, c0, 1 \n"
181 : : "r" (0), "i" (0x20));
184 //---------------------------------------------------------------------------
185 IMPLEMENTATION [arm && armv7]:
187 PRIVATE static inline void
191 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (midr));
193 // ACTRL is implementation defined
194 if ((midr & 0xff0ffff0) != 0x410fc090)
198 asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (actrl));
200 asm volatile ("mcr p15, 0, %0, c1, c0, 1" : : "r" (actrl | 0x41));
203 //---------------------------------------------------------------------------
204 IMPLEMENTATION [arm && (mpcore || armca9)]:
206 PRIVATE static inline void
207 Cpu::early_init_platform()
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,
216 Io::write<Mword>(0xffffffff, Scu_inv);
217 Io::write<Mword>(Io::read<Mword>(Scu_control) | 1, Scu_control);
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);
224 Mem_unit::clean_dcache();
229 //---------------------------------------------------------------------------
230 IMPLEMENTATION [arm && !(mpcore || armca9)]:
232 PRIVATE static inline void Cpu::early_init_platform()
235 //---------------------------------------------------------------------------
236 IMPLEMENTATION [arm]:
243 #include "pagetable.h"
244 #include "kmem_space.h"
245 #include "mem_unit.h"
246 #include "processor.h"
247 #include "ram_quota.h"
249 Per_cpu<Cpu> DEFINE_PER_CPU_P(0) Cpu::cpus(true);
254 Cpu::stack_align(Mword stack)
255 { return stack & ~0x3; }
259 void Cpu::early_init()
261 // switch to supervisor mode and intialize the memory system
262 asm volatile ( " mov r2, r13 \n"
268 " mcr p15, 0, %0, c1, c0 \n"
270 : "r" (Config::cache_enabled
271 ? Cp15_c1_cache_enabled : Cp15_c1_cache_disabled),
275 early_init_platform();
277 Mem_unit::flush_cache();
283 Cpu::have_superpages()
288 Cpu::debugctl_enable()
293 Cpu::debugctl_disable()
296 PUBLIC static inline NEEDS["types.h"]
298 Cpu::get_scaler_tsc_to_ns()
301 PUBLIC static inline NEEDS["types.h"]
303 Cpu::get_scaler_tsc_to_us()
306 PUBLIC static inline NEEDS["types.h"]
308 Cpu::get_scaler_ns_to_tsc()
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);
329 pte.set((unsigned long)&ivt_start, 4096,
330 Mem_page_attr(Page::KERN_RW | Page::CACHEABLE),
333 Mem_unit::tlb_flush();
343 Cpu::init(bool is_boot_cpu)
351 _phys_id = Proc::cpu_id();
360 //---------------------------------------------------------------------------
361 IMPLEMENTATION [arm && !armv6plus]:
369 //---------------------------------------------------------------------------
370 IMPLEMENTATION [arm && armv6plus]:
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]));
386 //---------------------------------------------------------------------------
387 IMPLEMENTATION [arm && !tz]:
389 PRIVATE static inline
394 //---------------------------------------------------------------------------
395 INTERFACE [arm && tz]:
401 static char monitor_vector_base asm ("monitor_vector_base");
404 //---------------------------------------------------------------------------
405 IMPLEMENTATION [arm && tz]:
411 // set monitor vector base address
412 assert(!((Mword)&monitor_vector_base & 31));
413 tz_mvbar((Mword)&monitor_vector_base);
415 // enable nonsecure access to vfp coprocessor
416 asm volatile("mov r0, #0xc00;"
417 "mcr p15, 0, r0, c1, c1, 2;"
426 Cpu::tz_switch_to_ns(Mword *nonsecure_state)
428 volatile register Mword r0 asm("r0") = (Mword)nonsecure_state;
429 extern char go_nonsecure;
431 asm volatile("stmdb sp!, {fp} \n"
433 "mov r2, sp \n" // copy sp_svc to sp_mon
434 "cps #0x16 \n" // switch to monitor mode
436 "adr r3, 1f \n" // save return eip
437 "mrs r4, cpsr \n" // save return psr
438 "mov pc, r1 \n" // go nonsecure!
440 "mov r0, sp \n" // copy sp_mon to sp_svc
441 "cps #0x13 \n" // switch to svc mode
445 : : "r" (r0), "r" (&go_nonsecure)
446 : "r2", "r3", "r4", "r5", "r6", "r7",
447 "r8", "r9", "r10", "r12", "r14", "memory");
455 asm volatile ("mrc p15, 0, %0, c1, c1, 0" : "=r" (r));
461 Cpu::tz_scr(Mword val)
463 asm volatile ("mcr p15, 0, %0, c1, c1, 0" : : "r" (val));
471 asm volatile ("mrc p15, 0, %0, c12, c0, 1" : "=r" (r));
477 Cpu::tz_mvbar(Mword val)
479 asm volatile ("mcr p15, 0, %0, c12, c0, 1" : : "r" (val));
482 // ------------------------------------------------------------------------
483 IMPLEMENTATION [arm && tz && armca9]:
487 Cpu::enable_irq_ovrr()
489 // set IRQ/FIQ/Abort override bits
490 asm volatile("mov r0, #0x1c0 \n"
491 "mcr p15, 0, r0, c1, c1, 3 \n"
495 IMPLEMENTATION [!tz || !armca9]:
499 Cpu::enable_irq_ovrr()
502 // ------------------------------------------------------------------------
503 IMPLEMENTATION [!debug]:
505 PRIVATE static inline
510 // ------------------------------------------------------------------------
511 IMPLEMENTATION [debug && armv6plus]:
515 Cpu::id_print_infos()
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]);
527 // ------------------------------------------------------------------------
528 IMPLEMENTATION [debug && !armv6plus]:
532 Cpu::id_print_infos()
536 // ------------------------------------------------------------------------
537 IMPLEMENTATION [debug]:
543 printf("Cache config: %s\n", Config::cache_enabled ? "ON" : "OFF");