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),
161 INTERFACE [arm && (mpcore || armca9)]:
168 Control = Mem_layout::Mp_scu_map_base + 0x0,
169 Config = Mem_layout::Mp_scu_map_base + 0x4,
170 Power_status = Mem_layout::Mp_scu_map_base + 0x8,
171 Inv = Mem_layout::Mp_scu_map_base + 0xc,
173 Control_ic_standby = 1 << 6,
174 Control_scu_standby = 1 << 5,
175 Control_force_port0 = 1 << 4,
176 Control_spec_linefill = 1 << 3,
177 Control_ram_parity = 1 << 2,
178 Control_addr_filtering = 1 << 1,
179 Control_enable = 1 << 0,
182 static void reset() { Io::write<Mword>(0xffffffff, Inv); }
184 static void enable(Mword bits = 0)
186 Unsigned32 ctrl = Io::read<Unsigned32>(Control);
187 if (!(ctrl & Control_enable))
188 Io::write<Unsigned32>(ctrl | bits | Control_enable, Control);
199 Cp15_c1_cache_enabled = Cp15_c1_generic | Cp15_c1_cache_bits,
200 Cp15_c1_cache_disabled = Cp15_c1_generic,
204 //---------------------------------------------------------------------------
205 INTERFACE [arm && !bsp_cpu]:
210 void bsp_init(bool) {}
213 //---------------------------------------------------------------------------
214 INTERFACE [arm && (mpcore || armca9) && !bsp_cpu]:
219 enum { Bsp_enable_bits = 0 };
222 //-------------------------------------------------------------------------
223 IMPLEMENTATION [arm]:
225 PRIVATE static inline
230 asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (m));
234 IMPLEMENTATION [arm && armv6]: // -----------------------------------------
236 PUBLIC static inline NEEDS[Cpu::set_actrl]
243 PUBLIC static inline NEEDS[Cpu::clear_actrl]
250 IMPLEMENTATION [arm && armv7]: //------------------------------------------
252 PUBLIC static inline NEEDS[Cpu::midr]
254 Cpu::is_smp_capable()
256 // ACTRL is implementation defined
257 return (midr() & 0xff0ffff0) == 0x410fc090;
264 if (!is_smp_capable())
268 asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (actrl));
270 asm volatile ("mcr p15, 0, %0, c1, c0, 1" : : "r" (actrl | 0x41));
273 PUBLIC static inline NEEDS[Cpu::clear_actrl]
277 if (!is_smp_capable())
283 //---------------------------------------------------------------------------
284 IMPLEMENTATION [arm && (mpcore || armca9)]:
286 PRIVATE static inline void
287 Cpu::early_init_platform()
290 Scu::enable(Scu::Bsp_enable_bits);
292 Io::write<Mword>(Io::read<Mword>(Mem_layout::Gic_cpu_map_base + 0) | 1,
293 Mem_layout::Gic_cpu_map_base + 0);
294 Io::write<Mword>(Io::read<Mword>(Mem_layout::Gic_dist_map_base + 0) | 1,
295 Mem_layout::Gic_dist_map_base + 0);
297 Mem_unit::clean_dcache();
302 //---------------------------------------------------------------------------
303 IMPLEMENTATION [arm && !(mpcore || armca9)]:
305 PRIVATE static inline void Cpu::early_init_platform()
308 //---------------------------------------------------------------------------
309 IMPLEMENTATION [arm]:
316 #include "pagetable.h"
317 #include "kmem_space.h"
318 #include "kmem_alloc.h"
319 #include "mem_unit.h"
320 #include "processor.h"
321 #include "ram_quota.h"
323 DEFINE_PER_CPU_P(0) Per_cpu<Cpu> Cpu::cpus(true);
328 Cpu::stack_align(Mword stack)
329 { return stack & ~0x3; }
333 void Cpu::early_init()
335 // switch to supervisor mode and intialize the memory system
336 asm volatile ( " mov r2, r13 \n"
342 " mcr p15, 0, %0, c1, c0 \n"
344 : "r" (Config::Cache_enabled
345 ? Cp15_c1_cache_enabled : Cp15_c1_cache_disabled),
349 early_init_platform();
351 Mem_unit::flush_cache();
357 Cpu::have_superpages()
362 Cpu::debugctl_enable()
367 Cpu::debugctl_disable()
370 PUBLIC static inline NEEDS["types.h"]
372 Cpu::get_scaler_tsc_to_ns()
375 PUBLIC static inline NEEDS["types.h"]
377 Cpu::get_scaler_tsc_to_us()
380 PUBLIC static inline NEEDS["types.h"]
382 Cpu::get_scaler_ns_to_tsc()
398 extern char ivt_start;
399 // map the interrupt vector table to 0xffff0000
400 Pte pte = Kmem_space::kdir()->walk((void*)Kmem_space::Ivt_base, 4096, true,
401 Kmem_alloc::q_allocator(Ram_quota::root),
404 pte.set((unsigned long)&ivt_start, 4096,
405 Mem_page_attr(Page::KERN_RW | Page::CACHEABLE), true);
407 Mem_unit::tlb_flush();
417 Cpu::init(bool is_boot_cpu)
425 _phys_id = Proc::cpu_id();
429 init_errata_workarounds();
430 bsp_init(is_boot_cpu);
439 asm volatile("mrc p15, 0, %0, c1, c0, 0 \n"
441 "mcr p15, 0, %0, c1, c0, 0 \n"
442 : : "r" (0), "i" (Cp15_c1_cache));
447 Cpu::disable_dcache()
449 asm volatile("mrc p15, 0, %0, c1, c0, 0 \n"
451 "mcr p15, 0, %0, c1, c0, 0 \n"
452 : : "r" (0), "i" (Cp15_c1_cache));
455 //---------------------------------------------------------------------------
456 IMPLEMENTATION [arm && !armv6plus]:
464 //---------------------------------------------------------------------------
465 IMPLEMENTATION [arm && armv6plus]:
467 PRIVATE static inline
469 Cpu::set_actrl(Mword bit_mask)
472 asm volatile("mrc p15, 0, %0, c1, c0, 1 \n\t"
473 "orr %0, %0, %1 \n\t"
474 "mcr p15, 0, %0, c1, c0, 1 \n\t"
475 : "=r"(t) : "r" (bit_mask));
478 PRIVATE static inline
480 Cpu::clear_actrl(Mword bit_mask)
483 asm volatile("mrc p15, 0, %0, c1, c0, 1 \n\t"
485 "mcr p15, 0, %0, c1, c0, 1 \n\t"
486 : "=r"(t) : "r" (bit_mask));
493 __asm__("mrc p15, 0, %0, c0, c1, 0": "=r" (_cpu_id._pfr[0]));
494 __asm__("mrc p15, 0, %0, c0, c1, 1": "=r" (_cpu_id._pfr[1]));
495 __asm__("mrc p15, 0, %0, c0, c1, 2": "=r" (_cpu_id._dfr0));
496 __asm__("mrc p15, 0, %0, c0, c1, 3": "=r" (_cpu_id._afr0));
497 __asm__("mrc p15, 0, %0, c0, c1, 4": "=r" (_cpu_id._mmfr[0]));
498 __asm__("mrc p15, 0, %0, c0, c1, 5": "=r" (_cpu_id._mmfr[1]));
499 __asm__("mrc p15, 0, %0, c0, c1, 6": "=r" (_cpu_id._mmfr[2]));
500 __asm__("mrc p15, 0, %0, c0, c1, 7": "=r" (_cpu_id._mmfr[3]));
503 //---------------------------------------------------------------------------
504 IMPLEMENTATION [!arm_cpu_errata || !armv6plus]:
506 PRIVATE static inline
507 void Cpu::init_errata_workarounds() {}
509 //---------------------------------------------------------------------------
510 IMPLEMENTATION [arm_cpu_errata && armv6plus]:
512 PRIVATE static inline
514 Cpu::set_c15_c0_1(Mword bits_mask)
517 asm volatile("mrc p15, 0, %0, c15, c0, 1 \n\t"
518 "orr %0, %0, %1 \n\t"
519 "mcr p15, 0, %0, c15, c0, 1 \n\t"
520 : "=r"(t) : "r" (bits_mask));
523 PRIVATE static inline NEEDS[Cpu::midr]
525 Cpu::init_errata_workarounds()
529 if ((mid & 0xff000000) == 0x41000000) // ARM CPU
531 Mword rev = ((mid & 0x00f00000) >> 16) | (mid & 0x0f);
532 Mword part = (mid & 0x0000fff0) >> 4;
534 if (part == 0xc08) // Cortex A8
537 if ((rev & 0xf0) == 0x10)
538 set_actrl(1 << 6); // IBE to 1
542 set_actrl((1 << 5) | (1 << 9)); // L1NEON & PLDNOP
548 asm volatile ("mrc p15, 1, %0, c9, c0, 2 \n\t"
549 "orr %0, %0, #1 << 22 \n\t" // Write alloc disable
550 "mcr p15, 1, %0, c9, c0, 2 \n\t" : "=r"(t));
554 if (part == 0xc09) // Cortex A9
556 // errata: 742230 (DMB errata)
557 // make DMB a DSB to fix behavior
558 if (rev <= 0x22) // <= r2p2
559 set_c15_c0_1(1 << 4);
562 if (rev == 0x20 || rev == 0x21 || rev == 0x22)
563 set_c15_c0_1((1 << 12) | (1 << 22));
566 if ((rev & 0xf0) == 0x20)
567 set_c15_c0_1(1 << 6);
571 set_c15_c0_1(1 << 11);
576 //---------------------------------------------------------------------------
577 IMPLEMENTATION [arm && !tz]:
579 PRIVATE static inline
584 //---------------------------------------------------------------------------
585 INTERFACE [arm && tz]:
591 static char monitor_vector_base asm ("monitor_vector_base");
594 //---------------------------------------------------------------------------
595 IMPLEMENTATION [arm && tz]:
599 PRIVATE inline NEEDS[<cassert>]
603 // set monitor vector base address
604 assert(!((Mword)&monitor_vector_base & 31));
605 tz_mvbar((Mword)&monitor_vector_base);
607 // enable nonsecure access to vfp coprocessor
608 asm volatile("mov r0, #0xc00;"
609 "mcr p15, 0, r0, c1, c1, 2;"
618 Cpu::tz_switch_to_ns(Mword *nonsecure_state)
620 volatile register Mword r0 asm("r0") = (Mword)nonsecure_state;
621 extern char go_nonsecure;
623 asm volatile("stmdb sp!, {fp} \n"
625 "mov r2, sp \n" // copy sp_svc to sp_mon
626 "cps #0x16 \n" // switch to monitor mode
628 "adr r3, 1f \n" // save return eip
629 "mrs r4, cpsr \n" // save return psr
630 "mov pc, r1 \n" // go nonsecure!
632 "mov r0, sp \n" // copy sp_mon to sp_svc
633 "cps #0x13 \n" // switch to svc mode
637 : : "r" (r0), "r" (&go_nonsecure)
638 : "r2", "r3", "r4", "r5", "r6", "r7",
639 "r8", "r9", "r10", "r12", "r14", "memory");
647 asm volatile ("mrc p15, 0, %0, c1, c1, 0" : "=r" (r));
653 Cpu::tz_scr(Mword val)
655 asm volatile ("mcr p15, 0, %0, c1, c1, 0" : : "r" (val));
663 asm volatile ("mrc p15, 0, %0, c12, c0, 1" : "=r" (r));
669 Cpu::tz_mvbar(Mword val)
671 asm volatile ("mcr p15, 0, %0, c12, c0, 1" : : "r" (val));
674 // ------------------------------------------------------------------------
675 IMPLEMENTATION [arm && tz && armca9]:
679 Cpu::enable_irq_ovrr()
681 // set IRQ/FIQ/Abort override bits
682 asm volatile("mov r0, #0x1c0 \n"
683 "mcr p15, 0, r0, c1, c1, 3 \n"
687 IMPLEMENTATION [!tz || !armca9]:
691 Cpu::enable_irq_ovrr()
694 // ------------------------------------------------------------------------
695 IMPLEMENTATION [!debug]:
697 PRIVATE static inline
702 // ------------------------------------------------------------------------
703 IMPLEMENTATION [debug && armv6plus]:
707 Cpu::id_print_infos()
709 printf("ID_PFR[01]: %08lx %08lx", _cpu_id._pfr[0], _cpu_id._pfr[1]);
710 printf(" ID_[DA]FR0: %08lx %08lx\n", _cpu_id._dfr0, _cpu_id._afr0);
711 printf("ID_MMFR[04]: %08lx %08lx %08lx %08lx\n",
712 _cpu_id._mmfr[0], _cpu_id._mmfr[1], _cpu_id._mmfr[2], _cpu_id._mmfr[3]);
715 // ------------------------------------------------------------------------
716 IMPLEMENTATION [debug && !armv6plus]:
720 Cpu::id_print_infos()
724 // ------------------------------------------------------------------------
725 IMPLEMENTATION [debug]:
731 printf("Cache config: %s\n", Config::Cache_enabled ? "ON" : "OFF");