From 3f42399fbbad4ab7159fad1cd6979f09039d993c Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Wed, 13 Feb 2013 16:09:27 +0100 Subject: [PATCH] FOC: Basic Arndale multi-core support Second CPU is up and receives timer interrupts. Caches are still disabled. --- kernel/fiasco/src/Kconfig | 2 +- kernel/fiasco/src/kern/arm/bootstrap.cpp | 4 +- .../fiasco/src/kern/arm/bsp/exynos5/Modules | 25 +++++---- .../arm/bsp/exynos5/bootstrap-arm-exynos5.cpp | 1 + .../bsp/exynos5/mem_layout-arm-exynos5.cpp | 1 + .../arm/bsp/exynos5/pic-arm-gic-exynos5.cpp | 8 +++ .../exynos5/platform_control-arm-exynos5.cpp | 22 ++++++++ .../arm/bsp/exynos5/timer-arm-exynos5.cpp | 51 +++++++++++------ kernel/fiasco/src/kern/arm/cpu-arm.cpp | 39 ++++++++++++- .../fiasco/src/kern/arm/kernel_thread-arm.cpp | 4 +- kernel/fiasco/src/kern/arm/pagetable-arch.cpp | 6 +- kernel/fiasco/src/kern/arm/perf_cnt-arm.cpp | 10 ++-- kernel/fiasco/src/kern/arm/tramp-mp.S | 26 +++++++-- kernel/fiasco/src/kern/irq_mgr.cpp | 6 +- .../src/kern/timer_tick-multi-vector.cpp | 55 +++++++++++++++++++ 15 files changed, 212 insertions(+), 48 deletions(-) create mode 100644 kernel/fiasco/src/kern/arm/bsp/exynos5/platform_control-arm-exynos5.cpp create mode 100644 kernel/fiasco/src/kern/timer_tick-multi-vector.cpp diff --git a/kernel/fiasco/src/Kconfig b/kernel/fiasco/src/Kconfig index b246814e..6c95dad9 100644 --- a/kernel/fiasco/src/Kconfig +++ b/kernel/fiasco/src/Kconfig @@ -85,7 +85,7 @@ config ABI_VF config PF_ARM_MP_CAPABLE bool - default y if ARM_MPCORE || ARM_CORTEX_A9 + default y if ARM_MPCORE || ARM_CORTEX_A9 || ARM_CORTEX_A15 config CAN_ARM_CPU_SA1100 bool diff --git a/kernel/fiasco/src/kern/arm/bootstrap.cpp b/kernel/fiasco/src/kern/arm/bootstrap.cpp index 63a7349b..0c5809fd 100644 --- a/kernel/fiasco/src/kern/arm/bootstrap.cpp +++ b/kernel/fiasco/src/kern/arm/bootstrap.cpp @@ -25,7 +25,7 @@ set_asid() {} //--------------------------------------------------------------------------- -IMPLEMENTATION [arm && armv6plus && (mpcore || armca9)]: +IMPLEMENTATION [arm && armv6plus && (mpcore || armca9 || armca15)]: enum { @@ -33,7 +33,7 @@ enum }; //--------------------------------------------------------------------------- -IMPLEMENTATION [arm && armv6plus && !(mpcore || armca9)]: +IMPLEMENTATION [arm && armv6plus && !(mpcore || armca9 || armca15)]: enum { diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos5/Modules b/kernel/fiasco/src/kern/arm/bsp/exynos5/Modules index 96ad09f2..c1e86c27 100644 --- a/kernel/fiasco/src/kern/arm/bsp/exynos5/Modules +++ b/kernel/fiasco/src/kern/arm/bsp/exynos5/Modules @@ -6,17 +6,20 @@ PREPROCESS_PARTS += exynos5 libuart PREPROCESS_PARTS += $(if $(CONFIG_PF_EXYNOS5_ARNDALE), exynos5_arndale pic_gic) CONFIG_KERNEL_LOAD_ADDR := 0x40000000 +#no memory mapped SCU on exynos5 +MPCORE_PHYS_BASE := 0x0 INTERFACES_KERNEL+= $(if $(CONFIG_PF_EXYNOS5_ARNDALE),gic) -bootstrap_IMPL += bootstrap-arm-exynos5 -clock_IMPL += clock-generic -config_IMPL += config-arm-exynos5 -kernel_uart_IMPL += kernel_uart-arm-exynos5 -mem_layout_IMPL += mem_layout-arm-exynos5 -pic_IMPL += pic-gic pic-arm-gic-exynos5 -reset_IMPL += reset-arm-exynos5 -timer_IMPL += timer-arm-exynos5 -timer_tick_IMPL += timer_tick-single-vector -uart_IMPL += uart-arm-exynos5 -warn_IMPL += warn warn-exynos5 +bootstrap_IMPL += bootstrap-arm-exynos5 +clock_IMPL += clock-generic +config_IMPL += config-arm-exynos5 +kernel_uart_IMPL += kernel_uart-arm-exynos5 +mem_layout_IMPL += mem_layout-arm-exynos5 +pic_IMPL += pic-gic pic-arm-gic-exynos5 +platform_control_IMPL += platform_control-arm-exynos5 +reset_IMPL += reset-arm-exynos5 +timer_IMPL += timer-arm-exynos5 +timer_tick_IMPL += timer_tick-multi-vector +uart_IMPL += uart-arm-exynos5 +warn_IMPL += warn warn-exynos5 diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos5/bootstrap-arm-exynos5.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos5/bootstrap-arm-exynos5.cpp index 0d32ba8f..53cda256 100644 --- a/kernel/fiasco/src/kern/arm/bsp/exynos5/bootstrap-arm-exynos5.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/exynos5/bootstrap-arm-exynos5.cpp @@ -16,4 +16,5 @@ map_hw(void *pd) map_dev(pd, 2); map_dev(pd, 3); map_dev(pd, 4); + map_dev(pd, 5); } diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos5/mem_layout-arm-exynos5.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos5/mem_layout-arm-exynos5.cpp index 32dcf13e..3a954315 100644 --- a/kernel/fiasco/src/kern/arm/bsp/exynos5/mem_layout-arm-exynos5.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/exynos5/mem_layout-arm-exynos5.cpp @@ -8,6 +8,7 @@ public: Devices2_phys_base = 0x12c00000, Devices3_phys_base = 0x10400000, Devices4_phys_base = 0x12d00000, + Devices5_phys_base = 0x02000000, }; enum Virt_layout_exynos5 : Address { diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos5/pic-arm-gic-exynos5.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos5/pic-arm-gic-exynos5.cpp index b0e118aa..00916a8c 100644 --- a/kernel/fiasco/src/kern/arm/bsp/exynos5/pic-arm-gic-exynos5.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/exynos5/pic-arm-gic-exynos5.cpp @@ -29,3 +29,11 @@ IMPLEMENT inline void Pic::restore_all(Status) {} +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && mp && pic_gic && exynos5]: + +PUBLIC static +void Pic::init_ap(unsigned) +{ + gic->init_ap(); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos5/platform_control-arm-exynos5.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos5/platform_control-arm-exynos5.cpp new file mode 100644 index 00000000..bcc73511 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/exynos5/platform_control-arm-exynos5.cpp @@ -0,0 +1,22 @@ +INTERFACE [arm && mp && exynos5]: +#include "types.h" + +IMPLEMENTATION [arm && mp && exynos5]: + +#include "io.h" +#include "kmem.h" +#include "stdio.h" + + +PUBLIC static +void +Platform_control::boot_ap_cpus(Address phys_tramp_mp_addr) +{ + // Write start address to iRam base (0x2020000). This is checked by the app + // cpus wihtin an wfe (wait-for event) loop. + printf("START CPUs\n"); + Io::write(phys_tramp_mp_addr, Kmem::Devices5_map_base + 0x20000); + // wake-up cpus + asm volatile("dsb; sev" : : : "memory"); +} + diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos5/timer-arm-exynos5.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos5/timer-arm-exynos5.cpp index 50e2e4d3..ea4a2586 100644 --- a/kernel/fiasco/src/kern/arm/bsp/exynos5/timer-arm-exynos5.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/exynos5/timer-arm-exynos5.cpp @@ -1,12 +1,13 @@ INTERFACE [arm & exynos5]: #include "kmem.h" +#include "processor.h" EXTENSION class Timer { public: enum { - BASE = Kmem::Timer_map_base, + BASE = Kmem::Timer_map_base, CFG0 = BASE, CFG1 = BASE + 0x4, TCON = BASE + 0x8, @@ -16,13 +17,15 @@ public: ONE_MS = 33000, /* HZ */ }; - static unsigned irq() { return 68; /* timer0 */ } + static unsigned irq() { return 68 + Proc::cpu_id(); } }; IMPLEMENTATION [arm && exynos5]: -#include "mmu.h" +#include "cpu.h" #include "io.h" +#include "irq_mgr.h" +#include "mmu.h" IMPLEMENT inline void @@ -31,25 +34,40 @@ Timer::update_one_shot(Unsigned64 wakeup) (void)wakeup; } +static inline +Mword +tcon_to_timer(Mword val, unsigned cpu_id) +{ + return cpu_id == 0 ? val : (val << (4 + (4 * cpu_id))); +} IMPLEMENT void Timer::init(unsigned) { - /* prescaler to one */ - Io::write(0x1, CFG0); - /* divider to 1 */ - Io::write(0x0, CFG1); + unsigned cpu_id = Proc::cpu_id(); - /* program 1ms */ - Io::write(ONE_MS, TCNTB0); - Io::write(0x0, TCMPB0); + if (!Cpu::boot_cpu()->phys_id() == cpu_id) + { + // prescaler to one + Io::write(0x1, CFG0); + // divider to 1 + Io::write(0x0, CFG1); + } + // program 1ms + Mword offset = 0xc * cpu_id; + Io::write(ONE_MS, TCNTB0 + offset); + Io::write(0x0, TCMPB0 + offset); - /* enable IRQ */ - Io::write(0x1, TINT_STAT); + // enable IRQ + Io::set(0x1 << cpu_id, TINT_STAT); - /* load and start timer in invterval mode*/ - Io::write(0xa, TCON); - Io::write(0x9, TCON); + // load and start timer in invterval mode + Mword tcon = Io::read(TCON); + Io::write(tcon | tcon_to_timer(0xa, cpu_id), TCON); + Io::write(tcon | tcon_to_timer(0x9, cpu_id), TCON); + + // route IRQ to this CPU + Irq_mgr::mgr->set_cpu(irq(), cpu_id); } IMPLEMENT inline NEEDS["config.h", "kip.h"] @@ -65,5 +83,6 @@ Timer::system_clock() PUBLIC static inline NEEDS["io.h"] void Timer::acknowledge() { - Io::set(0x20, TINT_STAT); + Mword stat = Io::read(TINT_STAT); + Io::write(stat & (0x1f | (0x20 << Proc::cpu_id())), TINT_STAT); } diff --git a/kernel/fiasco/src/kern/arm/cpu-arm.cpp b/kernel/fiasco/src/kern/arm/cpu-arm.cpp index 02823d7f..f6500923 100644 --- a/kernel/fiasco/src/kern/arm/cpu-arm.cpp +++ b/kernel/fiasco/src/kern/arm/cpu-arm.cpp @@ -309,7 +309,44 @@ Cpu::early_init_platform() } //--------------------------------------------------------------------------- -IMPLEMENTATION [arm && !(mpcore || armca9)]: +IMPLEMENTATION [arm && armca15]: +PRIVATE static inline void +Cpu::early_init_platform() +{ + Io::write(Io::read(Mem_layout::Gic_cpu_map_base + 0) | 1, + Mem_layout::Gic_cpu_map_base + 0); + Io::write(Io::read(Mem_layout::Gic_dist_map_base + 0) | 1, + Mem_layout::Gic_dist_map_base + 0); + + Mem_unit::clean_dcache(); + + enable_smp(); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && mp && (mpcore || armca9)]: + +PUBLIC static inline NEEDS["mem_layout.h", "io.h"] +int +Cpu::num_cpus() +{ + return (Io::read(Mem_layout::Mp_scu_map_base + 4) & 3) + 1; +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && mp && armca15]: + +PUBLIC static inline int +Cpu::num_cpus() +{ + unsigned num; + asm volatile ("mrc p15, 1, %0, c9, c0, 2" : "=r"(num)); + return ((num >> 24) & 0x3)+ 1; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && !(mpcore || armca9 || armca15)]: PRIVATE static inline void Cpu::early_init_platform() {} diff --git a/kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp b/kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp index 7c4184ac..c3326d5c 100644 --- a/kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp +++ b/kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp @@ -45,9 +45,9 @@ Kernel_thread::boot_app_cpus() extern volatile Mword _tramp_mp_startup_pdbr; extern volatile Mword _tramp_mp_start_dcr; - unsigned num_ap_cpus = (Io::read(Mem_layout::Mp_scu_map_base + 4) & 3); + unsigned num_ap_cpus = Cpu::num_cpus(); - printf("Number of CPUs: %d\n", num_ap_cpus + 1); + printf("Number of CPUs: %d\n", num_ap_cpus); _tramp_mp_startup_cp15_c1 = Config::Cache_enabled ? Cpu::Cp15_c1_cache_enabled : Cpu::Cp15_c1_cache_disabled; diff --git a/kernel/fiasco/src/kern/arm/pagetable-arch.cpp b/kernel/fiasco/src/kern/arm/pagetable-arch.cpp index fc0c2ddd..7e81734c 100644 --- a/kernel/fiasco/src/kern/arm/pagetable-arch.cpp +++ b/kernel/fiasco/src/kern/arm/pagetable-arch.cpp @@ -42,7 +42,7 @@ public: }; //--------------------------------------------------------------------------- -INTERFACE[arm && !(mpcore || armca9)]: +INTERFACE[arm && !(mpcore || armca9 || armca15)]: EXTENSION class Mem_page_attr { @@ -59,7 +59,7 @@ public: }; //--------------------------------------------------------------------------- -INTERFACE[arm && (mpcore || armca9)]: +INTERFACE[arm && (mpcore || armca9 || armca15)]: EXTENSION class Mem_page_attr { @@ -78,7 +78,7 @@ public: }; //--------------------------------------------------------------------------- -INTERFACE[arm && armca9]: +INTERFACE[arm && (armca9 || armca15)]: EXTENSION class Page_table { diff --git a/kernel/fiasco/src/kern/arm/perf_cnt-arm.cpp b/kernel/fiasco/src/kern/arm/perf_cnt-arm.cpp index cbb81d26..e3f45c0f 100644 --- a/kernel/fiasco/src/kern/arm/perf_cnt-arm.cpp +++ b/kernel/fiasco/src/kern/arm/perf_cnt-arm.cpp @@ -11,7 +11,7 @@ public: }; // ------------------------------------------------------------------------ -INTERFACE [arm && perf_cnt && !(mpcore || armca8 || armca9)]: +INTERFACE [arm && perf_cnt && !(mpcore || armca8 || armca9 || armca15)]: EXTENSION class Perf_cnt { @@ -81,7 +81,7 @@ private: }; // ------------------------------------------------------------------------ -INTERFACE [arm && perf_cnt && (armca8 || armca9)]: +INTERFACE [arm && perf_cnt && (armca8 || armca9 || armca15)]: EXTENSION class Perf_cnt { @@ -184,7 +184,7 @@ private: }; // ------------------------------------------------------------------------ -INTERFACE [arm && perf_cnt && armca9]: +INTERFACE [arm && perf_cnt && (armca9 || armca15)]: EXTENSION class Perf_cnt { @@ -199,7 +199,7 @@ private: IMPLEMENTATION [arm && perf_cnt]: // ------------------------------------------------------------------------ -IMPLEMENTATION [arm && perf_cnt && !(mpcore || armca8 || armca9)]: +IMPLEMENTATION [arm && perf_cnt && !(mpcore || armca8 || armca9 || armca15)]: char const *Perf_cnt::perf_type_str = "none"; @@ -284,7 +284,7 @@ Perf_cnt::mon_event_type(int nr) { return Io::read(mon_event_type_addr(nr)); } // ------------------------------------------------------------------------ -IMPLEMENTATION [arm && perf_cnt && (armca8 || armca9)]: +IMPLEMENTATION [arm && perf_cnt && (armca8 || armca9 || armca15)]: #include "cpu.h" diff --git a/kernel/fiasco/src/kern/arm/tramp-mp.S b/kernel/fiasco/src/kern/arm/tramp-mp.S index 736cb2d5..29af94e6 100644 --- a/kernel/fiasco/src/kern/arm/tramp-mp.S +++ b/kernel/fiasco/src/kern/arm/tramp-mp.S @@ -44,11 +44,13 @@ _tramp_mp_entry: msr cpsr_c, r0 // enable SMP +#ifndef CONFIG_ARM_CORTEX_A15 adr r0, .Lmpcore_phys_base ldr r0, [r0] ldr r1, [r0] orr r1, #1 str r1, [r0] +#endif #ifdef CONFIG_ARM_V7 bl invalidate_l1_v7 @@ -65,7 +67,7 @@ _tramp_mp_entry: #ifdef CONFIG_ARM_V7 // ACTRL is implementation defined mrc p15, 0, r0, c0, c0, 0 // read MIDR - adr r3, .Lactrl_cpuid_a9 // load addr + adr r3, .Lactrl_cpuid // load addr ldm r3, {r1,r2} // load mask + val and r0, r1 // apply mask teq r0, r2 // check value @@ -73,9 +75,11 @@ _tramp_mp_entry: #endif mrc p15, 0, r0, c1, c0, 1 -#ifdef CONFIG_ARM_V7 - tst r0, #0x40 - bne 2f +#ifdef CONFIG_ARM_CORTEX_A15 + orr r0, r0, #0x40 +#elif defined CONFIG_ARM_V7 + tst r0, #0x40 + bne 2f orr r0, r0, #0x41 #else orr r0, r0, #0x20 @@ -114,10 +118,20 @@ _tramp_mp_entry: .Lmpcore_phys_base: .long MPCORE_PHYS_BASE -// only one currently -.Lactrl_cpuid_a9: +#ifdef CONFIG_ARM_CORTEX_A9 +.Lactrl_cpuid: .long 0xff0ffff0 .long 0x410fc090 +#elif defined CONFIG_ARM_CORTEX_A15 +.Lactrl_cpuid: + .long 0xff0ffff0 + .long 0x410fc0f0 +#else +.Lactrl_cpuid: + .long 0xffffffff + .long 0x0 +#endif + // we run paged now _tramp_mp_virt: diff --git a/kernel/fiasco/src/kern/irq_mgr.cpp b/kernel/fiasco/src/kern/irq_mgr.cpp index a3974231..8210b170 100644 --- a/kernel/fiasco/src/kern/irq_mgr.cpp +++ b/kernel/fiasco/src/kern/irq_mgr.cpp @@ -124,5 +124,9 @@ IMPLEMENT void Irq_mgr::set_cpu(Mword irqnum, unsigned cpu) const { - WARNX(Warning, "IRQ%ld: ignoring CPU setting (%d).\n", irqnum, cpu); + Irq i = chip(irqnum); + if (!i.chip) + return; + + i.chip->set_cpu(i.pin, cpu); } diff --git a/kernel/fiasco/src/kern/timer_tick-multi-vector.cpp b/kernel/fiasco/src/kern/timer_tick-multi-vector.cpp new file mode 100644 index 00000000..7804545c --- /dev/null +++ b/kernel/fiasco/src/kern/timer_tick-multi-vector.cpp @@ -0,0 +1,55 @@ +INTERFACE: + +#include "types.h" +#include "per_cpu_data.h" + +EXTENSION class Timer_tick +{ +public: + static Per_cpu _glbl_timer; + + Timer_tick() + { + if (Proc::cpu_id()) + set_hit(&handler_app); + else + set_hit(&handler_sys_time); + } +}; + +IMPLEMENTATION: + +#include "timer.h" + +DEFINE_PER_CPU Per_cpu Timer_tick::_glbl_timer; + +IMPLEMENT void +Timer_tick::setup(unsigned cpu) +{ + if (!allocate_irq(&_glbl_timer.cpu(cpu), Timer::irq())) + panic("Could not allocate scheduling IRQ %d\n", Timer::irq()); + + _glbl_timer.cpu(cpu).set_mode(Timer::irq_mode()); +} + +IMPLEMENT +void +Timer_tick::enable(unsigned) +{ + _glbl_timer.current().chip()->unmask(_glbl_timer.current().pin()); +} + +IMPLEMENT +void +Timer_tick::disable(unsigned) +{ + _glbl_timer.current().chip()->mask(_glbl_timer.current().pin()); +} + +PUBLIC inline NEEDS["timer.h"] +void +Timer_tick::ack() +{ + Timer::acknowledge(); + Irq_base::ack(); +}