diff --git a/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk index 788be2348..cc1c4f4b0 100644 --- a/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk +++ b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk @@ -8,4 +8,6 @@ SRC_S += bootstrap/spec/arm_64/crt0.s vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw +NR_OF_CPUS = 4 + include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk index cc0dd41dd..87a026754 100644 --- a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk +++ b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk @@ -2,17 +2,17 @@ INC_DIR += $(REP_DIR)/src/core/spec/rpi3 INC_DIR += $(REP_DIR)/src/core/spec/arm_v8 # add C++ sources -SRC_CC += platform_services.cc +SRC_CC += kernel/cpu_mp.cc SRC_CC += kernel/vm_thread_off.cc -SRC_CC += kernel/cpu_up.cc -SRC_CC += kernel/lock.cc -SRC_CC += spec/arm_v8/cpu.cc -SRC_CC += spec/arm_v8/kernel/thread.cc -SRC_CC += spec/arm_v8/kernel/cpu.cc -SRC_CC += spec/arm/platform_support.cc +SRC_CC += platform_services.cc +SRC_CC += spec/64bit/memory_map.cc SRC_CC += spec/arm/bcm2837_pic.cc SRC_CC += spec/arm/generic_timer.cc -SRC_CC += spec/64bit/memory_map.cc +SRC_CC += spec/arm/kernel/lock.cc +SRC_CC += spec/arm/platform_support.cc +SRC_CC += spec/arm_v8/cpu.cc +SRC_CC += spec/arm_v8/kernel/cpu.cc +SRC_CC += spec/arm_v8/kernel/thread.cc #add assembly sources SRC_S += spec/arm_v8/exception_vector.s @@ -20,5 +20,7 @@ SRC_S += spec/arm_v8/crt0.s vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw +NR_OF_CPUS = 4 + # include less specific configuration include $(REP_DIR)/lib/mk/core-hw.inc diff --git a/repos/base-hw/src/bootstrap/spec/rpi3/board.h b/repos/base-hw/src/bootstrap/spec/rpi3/board.h index a8d911539..f6f3e1a94 100644 --- a/repos/base-hw/src/bootstrap/spec/rpi3/board.h +++ b/repos/base-hw/src/bootstrap/spec/rpi3/board.h @@ -23,7 +23,7 @@ namespace Board { struct Cpu : Hw::Arm_64_cpu { - static void wake_up_all_cpus(void*) {} + static void wake_up_all_cpus(void*); }; struct Pic { }; /* dummy object */ diff --git a/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc b/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc index 772147938..de7d6819f 100644 --- a/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc @@ -26,3 +26,12 @@ Bootstrap::Platform::Board::Board() ::Board::LOCAL_IRQ_CONTROLLER_SIZE }, Memory_region { ::Board::IRQ_CONTROLLER_BASE, ::Board::IRQ_CONTROLLER_SIZE }) {} + + +extern unsigned int _crt0_qemu_start_secondary_cpus; + +void Board::Cpu::wake_up_all_cpus(void *) +{ + _crt0_qemu_start_secondary_cpus = 1; + asm volatile("dsb #0; sev"); +} diff --git a/repos/base-hw/src/core/spec/arm/bcm2837_pic.cc b/repos/base-hw/src/core/spec/arm/bcm2837_pic.cc index 85894c625..14418c634 100644 --- a/repos/base-hw/src/core/spec/arm/bcm2837_pic.cc +++ b/repos/base-hw/src/core/spec/arm/bcm2837_pic.cc @@ -12,6 +12,7 @@ */ #include +#include #include @@ -21,41 +22,109 @@ Board::Pic::Pic() bool Board::Pic::take_request(unsigned & irq) { - Core0_irq_source::access_t src = read(); + unsigned cpu = Genode::Cpu::executing_id(); + Core_irq_source<0>::access_t src = 0; + switch (cpu) { + case 0: src = read>(); break; + case 1: src = read>(); break; + case 2: src = read>(); break; + case 3: src = read>(); break; + } + if ((1 << TIMER_IRQ) & src) { irq = TIMER_IRQ; return true; } + + if (0xf0 & src) { + irq = IPI; + switch (cpu) { + case 0: write>(1); break; + case 1: write>(1); break; + case 2: write>(1); break; + case 3: write>(1); break; + } + return true; + } + return false; } -void Board::Pic::mask() { } +void Board::Pic::_timer_irq(unsigned cpu, bool enable) +{ + unsigned v = enable ? 1 : 0; + switch (cpu) { + case 0: + write::Cnt_p_ns_irq>(v); + return; + case 1: + write::Cnt_p_ns_irq>(v); + return; + case 2: + write::Cnt_p_ns_irq>(v); + return; + case 3: + write::Cnt_p_ns_irq>(v); + return; + default: ; + } +} + + +void Board::Pic::_ipi(unsigned cpu, bool enable) +{ + unsigned v = enable ? 1 : 0; + switch (cpu) { + case 0: + write>(v); + return; + case 1: + write>(v); + return; + case 2: + write>(v); + return; + case 3: + write>(v); + return; + default: ; + } +} void Board::Pic::unmask(unsigned const i, unsigned cpu) { - if (cpu > 0) - Genode::raw("multi-core irq controller not implemented yet"); - - if (i == TIMER_IRQ) { - write(1); - return; + switch (i) { + case TIMER_IRQ: _timer_irq(cpu, true); return; + case IPI: _ipi(cpu, true); return; } - Genode::raw("irq of peripherals != timer not implemented yet!"); + Genode::raw("irq of peripherals != timer not implemented yet! (irq=", i, ")"); } void Board::Pic::mask(unsigned const i) { - if (i == TIMER_IRQ) { - write(0); - return; + unsigned cpu = Genode::Cpu::executing_id(); + switch (i) { + case TIMER_IRQ: _timer_irq(cpu, false); return; + case IPI: _ipi(cpu, false); return; } - Genode::raw("irq of peripherals != timer not implemented yet!"); + Genode::raw("irq of peripherals != timer not implemented yet! (irq=", i, ")"); } void Board::Pic::irq_mode(unsigned, unsigned, unsigned) { } + + +void Board::Pic::send_ipi(unsigned cpu_target) +{ + switch (cpu_target) { + case 0: write>(1); return; + case 1: write>(1); return; + case 2: write>(1); return; + case 3: write>(1); return; + } +} diff --git a/repos/base-hw/src/core/spec/arm/bcm2837_pic.h b/repos/base-hw/src/core/spec/arm/bcm2837_pic.h index 409919a3c..64e6fe2de 100644 --- a/repos/base-hw/src/core/spec/arm/bcm2837_pic.h +++ b/repos/base-hw/src/core/spec/arm/bcm2837_pic.h @@ -23,31 +23,34 @@ class Board::Pic : Genode::Mmio public: enum { + IPI = 0, NR_OF_IRQ = 64, - - /* - * dummy IPI value on non-SMP platform, - * only used in interrupt reservation within generic code - */ - IPI, }; private: - struct Core0_timer_irq_control : Register<0x40, 32> + template + struct Core_timer_irq_control : Register<0x40+CPU_NUM*0x4, 32> { - struct Cnt_p_ns_irq : Bitfield<1, 1> {}; + struct Cnt_p_ns_irq + : Register<0x40+CPU_NUM*0x4, 32>::template Bitfield<1, 1> {}; }; - struct Core1_timer_irq_control : Register<0x44, 32> {}; - struct Core2_timer_irq_control : Register<0x48, 32> {}; - struct Core3_timer_irq_control : Register<0x4c, 32> {}; + template + struct Core_mailbox_irq_control : Register<0x50+CPU_NUM*0x4, 32> {}; - struct Core0_irq_source : Register<0x60, 32> {}; - struct Core1_irq_source : Register<0x64, 32> {}; - struct Core2_irq_source : Register<0x68, 32> {}; - struct Core3_irq_source : Register<0x6c, 32> {}; + template + struct Core_irq_source : Register<0x60+CPU_NUM*0x4, 32> {}; + + template + struct Core_mailbox_set : Register<0x80+CPU_NUM*0x10, 32> {}; + + template + struct Core_mailbox_clear : Register<0xc0+CPU_NUM*0x10, 32> {}; + + void _ipi(unsigned cpu, bool enable); + void _timer_irq(unsigned cpu, bool enable); public: @@ -55,10 +58,10 @@ class Board::Pic : Genode::Mmio bool take_request(unsigned &irq); void finish_request() { } - void mask(); void unmask(unsigned const i, unsigned); void mask(unsigned const i); void irq_mode(unsigned, unsigned, unsigned); + void send_ipi(unsigned); static constexpr bool fast_interrupts() { return false; } };