From e05d26567d53ba5886de96c19e0427baf4efecdb Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Wed, 9 Dec 2015 12:02:00 +0100 Subject: [PATCH] hw: make 'smp' property an aspect (Ref #1312) This commit separates certain SMP aspects into 'spec/smp' subdirectories. Thereby it simplifies non-SMP implementations again, where no locking and several platform specific maintainance operations are not needed. Moreover, it moves several platform specifics to appropriated places, removes dead code from x86, and starts to turn global static pointers into references that are handed over. --- repos/base-hw/lib/mk/core.inc | 2 +- repos/base-hw/lib/mk/spec/arm/core.inc | 2 +- repos/base-hw/lib/mk/spec/arm_v6/core.inc | 2 + repos/base-hw/lib/mk/spec/cortex_a15/core.inc | 6 + repos/base-hw/lib/mk/spec/cortex_a8/core.inc | 2 + repos/base-hw/lib/mk/spec/cortex_a9/core.inc | 2 + repos/base-hw/lib/mk/spec/x86/core.inc | 3 +- repos/base-hw/src/core/include/kernel/cpu.h | 18 ++- .../core/include/spec/arm/macros_support.s | 14 ++ .../src/core/include/spec/arm_v6/cpu.h | 4 +- .../core/include/spec/arm_v7/cpu_support.h | 13 +- .../src/core/include/spec/cortex_a15/cpu.h | 2 +- .../core/include/{ => spec/smp}/kernel/lock.h | 0 .../src/core/include/spec/x86/cpu_support.h | 110 ++----------- .../core/include/spec/x86/kernel/vm_state.h | 25 --- repos/base-hw/src/core/include/spec/x86/pic.h | 1 - repos/base-hw/src/core/include/trustzone.h | 2 +- repos/base-hw/src/core/kernel/cpu.cc | 18 +-- repos/base-hw/src/core/kernel/init.cc | 69 ++++++++ repos/base-hw/src/core/kernel/kernel.cc | 148 +----------------- repos/base-hw/src/core/kernel/pd.cc | 4 - repos/base-hw/src/core/platform.cc | 2 +- repos/base-hw/src/core/spec/arm/kernel/cpu.cc | 50 +++--- .../src/core/spec/arm/kernel/cpu_idle.cc | 41 +++++ repos/base-hw/src/core/spec/arm/kernel/crt0.s | 39 +---- .../src/core/spec/arm/smp/kernel/crt0.s | 42 +++++ repos/base-hw/src/core/spec/arm_v6/cpu.cc | 6 +- repos/base-hw/src/core/spec/arm_v7/cpu.cc | 6 +- .../src/core/spec/arm_v7/smp/kernel/cpu.cc | 99 ++++++++++++ .../spec/arm_v7/virtualization/kernel/vm.cc | 4 +- repos/base-hw/src/core/spec/cortex_a15/cpu.cc | 6 +- .../src/core/spec/smp/kernel/kernel.cc | 37 +++++ repos/base-hw/src/core/spec/x86/cpu.cc | 14 -- repos/base-hw/src/core/spec/x86/kernel/cpu.cc | 22 +++ repos/base-hw/src/core/spec/x86/kernel/vm.cc | 22 --- .../src/core/spec/x86_64/kernel/crt0.s | 19 +-- 36 files changed, 436 insertions(+), 420 deletions(-) rename repos/base-hw/src/core/include/{ => spec/smp}/kernel/lock.h (100%) delete mode 100644 repos/base-hw/src/core/include/spec/x86/kernel/vm_state.h create mode 100644 repos/base-hw/src/core/kernel/init.cc create mode 100644 repos/base-hw/src/core/spec/arm/kernel/cpu_idle.cc create mode 100644 repos/base-hw/src/core/spec/arm/smp/kernel/crt0.s create mode 100644 repos/base-hw/src/core/spec/arm_v7/smp/kernel/cpu.cc create mode 100644 repos/base-hw/src/core/spec/smp/kernel/kernel.cc delete mode 100644 repos/base-hw/src/core/spec/x86/kernel/vm.cc diff --git a/repos/base-hw/lib/mk/core.inc b/repos/base-hw/lib/mk/core.inc index 8e925c005..8fb2f0686 100644 --- a/repos/base-hw/lib/mk/core.inc +++ b/repos/base-hw/lib/mk/core.inc @@ -47,7 +47,7 @@ SRC_CC += pager.cc SRC_CC += _main.cc SRC_CC += kernel/cpu_scheduler.cc SRC_CC += kernel/double_list.cc -SRC_CC += kernel/kernel.cc +SRC_CC += kernel/init.cc SRC_CC += kernel/thread.cc SRC_CC += kernel/signal_receiver.cc SRC_CC += kernel/ipc_node.cc diff --git a/repos/base-hw/lib/mk/spec/arm/core.inc b/repos/base-hw/lib/mk/spec/arm/core.inc index e9400e91e..0753249a6 100644 --- a/repos/base-hw/lib/mk/spec/arm/core.inc +++ b/repos/base-hw/lib/mk/spec/arm/core.inc @@ -9,7 +9,7 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/arm # add C++ sources SRC_CC += spec/arm/kernel/thread.cc -SRC_CC += spec/arm/kernel/cpu.cc +SRC_CC += spec/arm/kernel/cpu_idle.cc SRC_CC += spec/arm/kernel/pd.cc SRC_CC += spec/arm/platform_support.cc diff --git a/repos/base-hw/lib/mk/spec/arm_v6/core.inc b/repos/base-hw/lib/mk/spec/arm_v6/core.inc index eb1dca1f9..ad61c26fb 100644 --- a/repos/base-hw/lib/mk/spec/arm_v6/core.inc +++ b/repos/base-hw/lib/mk/spec/arm_v6/core.inc @@ -12,6 +12,8 @@ SRC_CC += spec/arm/cpu.cc SRC_CC += spec/arm/kernel/cpu_context.cc SRC_CC += kernel/vm_thread.cc SRC_CC += spec/arm_v6/cpu.cc +SRC_CC += spec/arm/kernel/cpu.cc +SRC_CC += kernel/kernel.cc # add assembly sources SRC_S += spec/arm_v6/mode_transition.s diff --git a/repos/base-hw/lib/mk/spec/cortex_a15/core.inc b/repos/base-hw/lib/mk/spec/cortex_a15/core.inc index ebaae46f5..ab1332890 100644 --- a/repos/base-hw/lib/mk/spec/cortex_a15/core.inc +++ b/repos/base-hw/lib/mk/spec/cortex_a15/core.inc @@ -7,9 +7,15 @@ # add include paths INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a15 INC_DIR += $(REP_DIR)/src/core/include/spec/arm_gic +INC_DIR += $(REP_DIR)/src/core/include/spec/smp # add C++ sources SRC_CC += spec/cortex_a15/cpu.cc +SRC_CC += spec/arm_v7/smp/kernel/cpu.cc +SRC_CC += spec/smp/kernel/kernel.cc + +# add assembler sources +SRC_S += spec/arm/smp/kernel/crt0.s # include less specific configuration include $(REP_DIR)/lib/mk/spec/arm_v7/core.inc diff --git a/repos/base-hw/lib/mk/spec/cortex_a8/core.inc b/repos/base-hw/lib/mk/spec/cortex_a8/core.inc index faeec0d11..1fed9aab1 100644 --- a/repos/base-hw/lib/mk/spec/cortex_a8/core.inc +++ b/repos/base-hw/lib/mk/spec/cortex_a8/core.inc @@ -10,6 +10,8 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a8 # add C++ sources SRC_CC += spec/arm/cpu.cc SRC_CC += spec/arm/kernel/cpu_context.cc +SRC_CC += spec/arm/kernel/cpu.cc +SRC_CC += kernel/kernel.cc # include less specific configuration include $(REP_DIR)/lib/mk/spec/arm_v7/core.inc diff --git a/repos/base-hw/lib/mk/spec/cortex_a9/core.inc b/repos/base-hw/lib/mk/spec/cortex_a9/core.inc index 5bf853563..6223590bb 100644 --- a/repos/base-hw/lib/mk/spec/cortex_a9/core.inc +++ b/repos/base-hw/lib/mk/spec/cortex_a9/core.inc @@ -13,6 +13,8 @@ SRC_CC += spec/arm/cpu.cc SRC_CC += spec/arm_gic/pic.cc SRC_CC += spec/arm/kernel/cpu_context.cc SRC_CC += kernel/vm_thread.cc +SRC_CC += spec/arm/kernel/cpu.cc +SRC_CC += kernel/kernel.cc # include less specific configuration include $(REP_DIR)/lib/mk/spec/arm_v7/core.inc diff --git a/repos/base-hw/lib/mk/spec/x86/core.inc b/repos/base-hw/lib/mk/spec/x86/core.inc index 08cb3a669..8a0d8ce35 100644 --- a/repos/base-hw/lib/mk/spec/x86/core.inc +++ b/repos/base-hw/lib/mk/spec/x86/core.inc @@ -9,11 +9,12 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/x86 # add C++ sources +SRC_CC += kernel/kernel.cc +SRC_CC += kernel/vm_thread.cc SRC_CC += spec/x86/platform_support.cc SRC_CC += spec/x86/kernel/pd.cc SRC_CC += spec/x86/cpu.cc SRC_CC += spec/x86/bios_data_area.cc -SRC_CC += kernel/vm_thread.cc SRC_CC += spec/x86/io_port_session_component.cc SRC_CC += spec/x86/platform_services.cc diff --git a/repos/base-hw/src/core/include/kernel/cpu.h b/repos/base-hw/src/core/include/kernel/cpu.h index e60736e2c..74acd7b27 100644 --- a/repos/base-hw/src/core/include/kernel/cpu.h +++ b/repos/base-hw/src/core/include/kernel/cpu.h @@ -269,7 +269,7 @@ class Kernel::Cpu : public Genode::Cpu, Cpu_idle _idle; Timer * const _timer; Cpu_scheduler _scheduler; - Ipi _ipi_irq; + Ipi _ipi_irq; Irq _timer_irq; /* timer irq implemented as empty event */ unsigned _quota() const { return _timer->ms_to_tics(cpu_quota_ms); } @@ -282,6 +282,14 @@ class Kernel::Cpu : public Genode::Cpu, */ Cpu(unsigned const id, Timer * const timer); + /** + * Initialize primary cpu object + * + * \param pic interrupt controller object + * \param core_pd core's pd object + */ + void init(Pic &pic, Kernel::Pd &core_pd); + /** * Raise the IPI of the CPU */ @@ -301,9 +309,9 @@ class Kernel::Cpu : public Genode::Cpu, void schedule(Job * const job); /** - * Handle recent exception of the CPU and proceed its user execution + * Return the job that should be executed at next */ - void exception(); + Cpu_job& schedule(); /*************** @@ -313,8 +321,8 @@ class Kernel::Cpu : public Genode::Cpu, /** * Returns the currently active job */ - Job * scheduled_job() const { - return static_cast(_scheduler.head())->helping_sink(); } + Job & scheduled_job() const { + return *static_cast(_scheduler.head())->helping_sink(); } unsigned id() const { return _id; } Cpu_scheduler * scheduler() { return &_scheduler; } diff --git a/repos/base-hw/src/core/include/spec/arm/macros_support.s b/repos/base-hw/src/core/include/spec/arm/macros_support.s index 838447619..37d84a157 100644 --- a/repos/base-hw/src/core/include/spec/arm/macros_support.s +++ b/repos/base-hw/src/core/include/spec/arm/macros_support.s @@ -11,6 +11,20 @@ * under the terms of the GNU General Public License version 2. */ +/** + * Get base of the first kernel-stack and the common kernel-stack size + * + * \param base_dst_reg register that shall receive the stack-area base + * \param size_dst_reg register that shall receive the size of a kernel stack + */ +.macro _get_constraints_of_kernel_stacks base_dst_reg, size_dst_reg + + ldr \base_dst_reg, =kernel_stack + ldr \size_dst_reg, =kernel_stack_size + ldr \size_dst_reg, [\size_dst_reg] +.endm + + /** * Calculate and apply kernel SP for a given kernel-stacks area * diff --git a/repos/base-hw/src/core/include/spec/arm_v6/cpu.h b/repos/base-hw/src/core/include/spec/arm_v6/cpu.h index 93811c927..47300393e 100644 --- a/repos/base-hw/src/core/include/spec/arm_v6/cpu.h +++ b/repos/base-hw/src/core/include/spec/arm_v6/cpu.h @@ -125,15 +125,13 @@ class Genode::Cpu : public Arm * * \param pd kernel's pd object */ - static void init_virt_kernel(Kernel::Pd* pd); + static void init_virt_kernel(Kernel::Pd& pd); /** * Ensure that TLB insertions get applied */ static void tlb_insertions() { flush_tlb(); } - static void start_secondary_cpus(void *) { assert(!Board::is_smp()); } - /** * Return wether to retry an undefined user instruction after this call */ diff --git a/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h b/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h index f6aa43a05..2d1cab8ca 100644 --- a/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h +++ b/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h @@ -155,7 +155,7 @@ class Genode::Arm_v7 : public Arm * * \param pd kernel's pd object */ - static void init_virt_kernel(Kernel::Pd* pd); + static void init_virt_kernel(Kernel::Pd& pd); inline static void finish_init_phys_kernel(); @@ -176,17 +176,6 @@ class Genode::Arm_v7 : public Arm */ static void data_synchronization_barrier() { asm volatile ("dsb"); } - /** - * Enable secondary CPUs with instr. pointer 'ip' - */ - static void start_secondary_cpus(void * const ip) - { - if (!(NR_OF_CPUS > 1)) { return; } - Board::secondary_cpus_ip(ip); - data_synchronization_barrier(); - asm volatile ("sev\n"); - } - /** * Wait for the next interrupt as cheap as possible */ diff --git a/repos/base-hw/src/core/include/spec/cortex_a15/cpu.h b/repos/base-hw/src/core/include/spec/cortex_a15/cpu.h index ad9e3f448..a472fbf58 100644 --- a/repos/base-hw/src/core/include/spec/cortex_a15/cpu.h +++ b/repos/base-hw/src/core/include/spec/cortex_a15/cpu.h @@ -427,7 +427,7 @@ class Genode::Cpu : public Arm_v7 * * \param pd kernel pd object pointer */ - static void init_virt_kernel(Kernel::Pd * pd); + static void init_virt_kernel(Kernel::Pd & pd); /************* diff --git a/repos/base-hw/src/core/include/kernel/lock.h b/repos/base-hw/src/core/include/spec/smp/kernel/lock.h similarity index 100% rename from repos/base-hw/src/core/include/kernel/lock.h rename to repos/base-hw/src/core/include/spec/smp/kernel/lock.h diff --git a/repos/base-hw/src/core/include/spec/x86/cpu_support.h b/repos/base-hw/src/core/include/spec/x86/cpu_support.h index ff6a7abda..b1a9c118e 100644 --- a/repos/base-hw/src/core/include/spec/x86/cpu_support.h +++ b/repos/base-hw/src/core/include/spec/x86/cpu_support.h @@ -144,7 +144,7 @@ class Genode::Cpu { friend class Cpu_lazy_state; - private: + protected: Idt *_idt; Tss *_tss; @@ -311,96 +311,6 @@ class Genode::Cpu Kernel::Call_arg user_arg_7() const { return r11; } }; - /** - * Returns true if current execution context is running in user mode - */ - static bool is_user() - { - PDBG("not implemented"); - return false; - } - - /** - * Invalidate all entries of all instruction caches - */ - __attribute__((always_inline)) static void invalidate_instr_caches() { } - - /** - * Flush all entries of all data caches - */ - inline static void flush_data_caches() { } - - /** - * Invalidate all entries of all data caches - */ - inline static void invalidate_data_caches() { } - - /** - * Flush all caches - */ - static void flush_caches() - { - flush_data_caches(); - invalidate_instr_caches(); - } - - /** - * Invalidate all TLB entries of the address space named 'pid' - */ - static void flush_tlb_by_pid(unsigned const pid) - { - flush_caches(); - } - - /** - * Invalidate all TLB entries - */ - static void flush_tlb() - { - flush_caches(); - } - - /** - * Flush data-cache entries for virtual region ['base', 'base + size') - */ - static void - flush_data_caches_by_virt_region(addr_t base, size_t const size) { } - - /** - * Bin instr.-cache entries for virtual region ['base', 'base + size') - */ - static void - invalidate_instr_caches_by_virt_region(addr_t base, size_t const size) - { } - - static void inval_branch_predicts() { }; - - /** - * Switch to the virtual mode in kernel - * - * \param pd kernel's pd object - */ - static void init_virt_kernel(Kernel::Pd * pd); - - /** - * Configure this module appropriately for the first kernel run - */ - static void init_phys_kernel() - { - Timer::disable_pit(); - _init_fpu(); - }; - - /** - * Finish all previous data transfers - */ - static void data_synchronization_barrier() { } - - /** - * Enable secondary CPUs with instr. pointer 'ip' - */ - static void start_secondary_cpus(void * const ip) { } - /** * Wait for the next interrupt as cheap as possible */ @@ -455,12 +365,22 @@ class Genode::Cpu _disable_fpu(); } - /************* - ** Dummies ** - *************/ - static void tlb_insertions() { inval_branch_predicts(); } + /********************************************* + ** Dummy implementations not needed on x86 ** + *********************************************/ + + static void tlb_insertions() { } static void translation_added(addr_t, size_t) { } + static void flush_data_caches() { } + static void flush_caches() { } + static void flush_tlb_by_pid(unsigned const pid) { } + static void flush_data_caches_by_virt_region(addr_t base, + size_t const size) { } + static void invalidate_instr_caches() { } + static void invalidate_data_caches() { } + static void invalidate_instr_caches_by_virt_region(addr_t base, + size_t const size) {} }; struct Genode::Cpu::Cr0 : Register<64> diff --git a/repos/base-hw/src/core/include/spec/x86/kernel/vm_state.h b/repos/base-hw/src/core/include/spec/x86/kernel/vm_state.h deleted file mode 100644 index d440dc20e..000000000 --- a/repos/base-hw/src/core/include/spec/x86/kernel/vm_state.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * \brief CPU context of a virtual machine - * \author Martin Stein - * \date 2013-10-30 - */ - -/* - * Copyright (C) 2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KERNEL__VM_STATE_H_ -#define _KERNEL__VM_STATE_H_ - -namespace Kernel -{ - /** - * Dummy - */ - struct Vm_state { }; -} - -#endif /* _KERNEL__VM_STATE_H_ */ \ No newline at end of file diff --git a/repos/base-hw/src/core/include/spec/x86/pic.h b/repos/base-hw/src/core/include/spec/x86/pic.h index dd7c7c71d..50d7b2a82 100644 --- a/repos/base-hw/src/core/include/spec/x86/pic.h +++ b/repos/base-hw/src/core/include/spec/x86/pic.h @@ -274,7 +274,6 @@ class Genode::Pic : public Mmio */ void mask() { } - void init_cpu_local() { } bool is_ip_interrupt(unsigned, unsigned) { return false; } void trigger_ip_interrupt(unsigned) { } }; diff --git a/repos/base-hw/src/core/include/trustzone.h b/repos/base-hw/src/core/include/trustzone.h index f92e7031d..f4e6065be 100644 --- a/repos/base-hw/src/core/include/trustzone.h +++ b/repos/base-hw/src/core/include/trustzone.h @@ -18,7 +18,7 @@ #include namespace Kernel { - void init_trustzone(Pic * pic); + void init_trustzone(Pic & pic); } #endif /* _CORE__INCLUDE__TRUSTZONE_H_ */ diff --git a/repos/base-hw/src/core/kernel/cpu.cc b/repos/base-hw/src/core/kernel/cpu.cc index 8f21b3470..c9da9f98f 100644 --- a/repos/base-hw/src/core/kernel/cpu.cc +++ b/repos/base-hw/src/core/kernel/cpu.cc @@ -177,12 +177,10 @@ bool Cpu::interrupt(unsigned const irq_id) } -void Cpu::exception() +Cpu_job & Cpu::schedule() { - /* update old job */ - Job * const old_job = scheduled_job(); - - old_job->exception(_id); + /* get new job */ + Job & old_job = scheduled_job(); /* update scheduler */ unsigned const old_time = _scheduler.head_quota(); @@ -191,18 +189,18 @@ void Cpu::exception() _scheduler.update(quota); /* get new job */ - Job * const new_job = scheduled_job(); + Job & new_job = scheduled_job(); quota = _scheduler.head_quota(); assert(quota); _timer->start_one_shot(quota, _id); /* switch between lazy state of old and new job */ - Cpu_lazy_state * const old_state = old_job->lazy_state(); - Cpu_lazy_state * const new_state = new_job->lazy_state(); + Cpu_lazy_state * const old_state = old_job.lazy_state(); + Cpu_lazy_state * const new_state = new_job.lazy_state(); prepare_proceeding(old_state, new_state); - /* resume new job */ - new_job->proceed(_id); + /* return new job */ + return new_job; } diff --git a/repos/base-hw/src/core/kernel/init.cc b/repos/base-hw/src/core/kernel/init.cc new file mode 100644 index 000000000..3871335f1 --- /dev/null +++ b/repos/base-hw/src/core/kernel/init.cc @@ -0,0 +1,69 @@ +/* + * \brief Common kernel initialization + * \author Martin Stein + * \author Stefan Kalkowski + * \date 2011-10-20 + */ + +/* + * Copyright (C) 2011-2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* core includes */ +#include +#include +#include +#include +#include +#include + +/* base includes */ +#include +#include + +using namespace Kernel; + +static_assert(sizeof(Genode::sizet_arithm_t) >= 2 * sizeof(size_t), + "Bad result type for size_t arithmetics."); + +Pd * Kernel::core_pd() { + return unmanaged_singleton()->kernel_pd(); } + + +Pic * Kernel::pic() { return unmanaged_singleton(); } + + +/** + * Setup kernel environment + */ +extern "C" void init_kernel() +{ + /* + * As atomic operations are broken in physical mode on some platforms + * we must avoid the use of 'cmpxchg' by now (includes not using any + * local static objects. + */ + + /* calculate in advance as needed later when data writes aren't allowed */ + core_pd(); + + /* initialize cpu pool */ + cpu_pool(); + + /* initialize PIC */ + pic(); + + /* initialize current cpu */ + cpu_pool()->cpu(Cpu::executing_id())->init(*pic(), *core_pd()); + + Core_thread::singleton(); + + Genode::printf("kernel initialized\n"); + + test(); + + kernel(); +} diff --git a/repos/base-hw/src/core/kernel/kernel.cc b/repos/base-hw/src/core/kernel/kernel.cc index a0ccb1103..67058103f 100644 --- a/repos/base-hw/src/core/kernel/kernel.cc +++ b/repos/base-hw/src/core/kernel/kernel.cc @@ -1,19 +1,8 @@ /* - * \brief Singlethreaded minimalistic kernel + * \brief Kernel entrypoint * \author Martin Stein * \author Stefan Kalkowski * \date 2011-10-20 - * - * This kernel is the only code except the mode transition PIC, that runs in - * privileged CPU mode. It has two tasks. First it initializes the process - * 'core', enriches it with the whole identically mapped address range, - * joins and applies it, assigns one thread to it with a userdefined - * entrypoint (the core main thread) and starts this thread in userland. - * Afterwards it is called each time an exception occurs in userland to do - * a minimum of appropriate exception handling. Thus it holds a CPU context - * for itself as for any other thread. But due to the fact that it never - * relies on prior kernel runs this context only holds some constant pointers - * such as SP and IP. */ /* @@ -24,137 +13,14 @@ */ /* core includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* base includes */ -#include -#include - -/* base-hw includes */ -#include - -using namespace Kernel; - -extern void * _start_secondary_cpus; - -static_assert(sizeof(Genode::sizet_arithm_t) >= 2 * sizeof(size_t), - "Bad result type for size_t arithmetics."); - -Lock & Kernel::data_lock() { return *unmanaged_singleton(); } - - -Pd * Kernel::core_pd() { - return unmanaged_singleton()->kernel_pd(); } - - -Pic * Kernel::pic() { return unmanaged_singleton(); } - - -/** - * Setup kernel environment before activating secondary CPUs - */ -extern "C" void init_kernel_up() -{ - /* - * As atomic operations are broken in physical mode on some platforms - * we must avoid the use of 'cmpxchg' by now (includes not using any - * local static objects. - */ - - /* calculate in advance as needed later when data writes aren't allowed */ - core_pd(); - - /* initialize all CPU objects */ - cpu_pool(); - - /* initialize PIC */ - pic(); - - /* go multiprocessor mode */ - Cpu::start_secondary_cpus(&_start_secondary_cpus); -} - - -/** - * Setup kernel enviroment after activating secondary CPUs as primary CPU - */ -void init_kernel_mp_primary() -{ - Core_thread::singleton(); - Genode::printf("kernel initialized\n"); - test(); -} - - -/** - * Setup kernel enviroment after activating secondary CPUs - */ -extern "C" void init_kernel_mp() -{ - /* - * As updates on a cached kernel lock might not be visible to CPUs that - * have not enabled caches, we can't synchronize the activation of MMU and - * caches. Hence we must avoid write access to kernel data by now. - */ - - /* synchronize data view of all CPUs */ - Cpu::invalidate_data_caches(); - Cpu::invalidate_instr_caches(); - Cpu::data_synchronization_barrier(); - - /* locally initialize interrupt controller */ - pic()->init_cpu_local(); - - /* initialize CPU in physical mode */ - Cpu::init_phys_kernel(); - - /* switch to core address space */ - Cpu::init_virt_kernel(core_pd()); - - /* - * Now it's safe to use 'cmpxchg' - */ - - Lock::Guard guard(data_lock()); - - /* - * Now it's save to write to kernel data - */ - - /* - * TrustZone initialization code - * - * FIXME This is a plattform specific feature - */ - init_trustzone(pic()); - - /* - * Enable performance counter - * - * FIXME This is an optional CPU specific feature - */ - perf_counter()->enable(); - - /* enable timer interrupt */ - unsigned const cpu = Cpu::executing_id(); - pic()->unmask(Timer::interrupt_id(cpu), cpu); - - /* do further initialization only as primary CPU */ - if (Cpu::primary_id() != cpu) { return; } - init_kernel_mp_primary(); -} +#include extern "C" void kernel() { - data_lock().lock(); - cpu_pool()->cpu(Cpu::executing_id())->exception(); + using namespace Kernel; + + Cpu * const cpu = cpu_pool()->cpu(Cpu::executing_id()); + cpu->scheduled_job().exception(cpu->id()); + cpu->schedule().proceed(cpu->id()); } diff --git a/repos/base-hw/src/core/kernel/pd.cc b/repos/base-hw/src/core/kernel/pd.cc index 279d692d2..35821d327 100644 --- a/repos/base-hw/src/core/kernel/pd.cc +++ b/repos/base-hw/src/core/kernel/pd.cc @@ -13,7 +13,6 @@ */ /* core includes */ -#include #include /* Genode includes */ @@ -69,9 +68,6 @@ void Mode_transition_control::switch_to(Cpu::Context * const context, addr_t const entry_raw, addr_t const context_ptr_base) { - /* unlock kernel data */ - data_lock().unlock(); - /* override client-context pointer of the executing CPU */ size_t const context_ptr_offset = cpu * sizeof(context); addr_t const context_ptr = context_ptr_base + context_ptr_offset; diff --git a/repos/base-hw/src/core/platform.cc b/repos/base-hw/src/core/platform.cc index 9701534b4..8980a3779 100644 --- a/repos/base-hw/src/core/platform.cc +++ b/repos/base-hw/src/core/platform.cc @@ -34,7 +34,7 @@ using namespace Genode; extern int _prog_img_beg; extern int _prog_img_end; -void __attribute__((weak)) Kernel::init_trustzone(Pic * pic) { } +void __attribute__((weak)) Kernel::init_trustzone(Pic & pic) { } /** * Format of a boot-module header diff --git a/repos/base-hw/src/core/spec/arm/kernel/cpu.cc b/repos/base-hw/src/core/spec/arm/kernel/cpu.cc index b41ec50fe..c4f678690 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/cpu.cc @@ -13,29 +13,39 @@ */ /* core includes */ -#include #include -#include #include +#include +#include +#include -using namespace Kernel; - - -Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::MIN, 0) +void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd) { - Cpu_job::cpu(cpu); - cpu_exception = RESET; - ip = (addr_t)&_main; - sp = (addr_t)&_stack[stack_size]; - init_thread((addr_t)core_pd()->translation_table(), core_pd()->asid); + /* locally initialize interrupt controller */ + pic.init_cpu_local(); + + /* initialize CPU in physical mode */ + Cpu::init_phys_kernel(); + + /* switch to core address space */ + Cpu::init_virt_kernel(core_pd); + + /* + * TrustZone initialization code + * + * FIXME This is a plattform specific feature + */ + init_trustzone(pic); + + /* + * Enable performance counter + * + * FIXME This is an optional CPU specific feature + */ + perf_counter()->enable(); + + /* enable timer interrupt */ + unsigned const cpu = Cpu::executing_id(); + pic.unmask(Timer::interrupt_id(cpu), cpu); } - -void Cpu_idle::exception(unsigned const cpu) -{ - switch (cpu_exception) { - case INTERRUPT_REQUEST: _interrupt(cpu); return; - case FAST_INTERRUPT_REQUEST: _interrupt(cpu); return; - case RESET: return; - default: assert(0); } -} diff --git a/repos/base-hw/src/core/spec/arm/kernel/cpu_idle.cc b/repos/base-hw/src/core/spec/arm/kernel/cpu_idle.cc new file mode 100644 index 000000000..b41ec50fe --- /dev/null +++ b/repos/base-hw/src/core/spec/arm/kernel/cpu_idle.cc @@ -0,0 +1,41 @@ +/* + * \brief Class for kernel data that is needed to manage a specific CPU + * \author Martin Stein + * \author Stefan Kalkowski + * \date 2014-01-14 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* core includes */ +#include +#include +#include +#include + +using namespace Kernel; + + +Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::MIN, 0) +{ + Cpu_job::cpu(cpu); + cpu_exception = RESET; + ip = (addr_t)&_main; + sp = (addr_t)&_stack[stack_size]; + init_thread((addr_t)core_pd()->translation_table(), core_pd()->asid); +} + + +void Cpu_idle::exception(unsigned const cpu) +{ + switch (cpu_exception) { + case INTERRUPT_REQUEST: _interrupt(cpu); return; + case FAST_INTERRUPT_REQUEST: _interrupt(cpu); return; + case RESET: return; + default: assert(0); } +} diff --git a/repos/base-hw/src/core/spec/arm/kernel/crt0.s b/repos/base-hw/src/core/spec/arm/kernel/crt0.s index 6c8d58dba..52889d30b 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/crt0.s +++ b/repos/base-hw/src/core/spec/arm/kernel/crt0.s @@ -20,20 +20,6 @@ .include "macros.s" -/** - * Get base of the first kernel-stack and the common kernel-stack size - * - * \param base_dst_reg register that shall receive the stack-area base - * \param size_dst_reg register that shall receive the size of a kernel stack - */ -.macro _get_constraints_of_kernel_stacks base_dst_reg, size_dst_reg - - ldr \base_dst_reg, =kernel_stack - ldr \size_dst_reg, =kernel_stack_size - ldr \size_dst_reg, [\size_dst_reg] -.endm - - .section ".text.crt0" /********************************** @@ -65,29 +51,12 @@ b 1b 2: - /* setup temporary stack pointer for uniprocessor mode */ + /* setup temporary stack pointer */ _get_constraints_of_kernel_stacks r0, r1 add sp, r0, r1 - /* uniprocessor kernel-initialization which activates multiprocessor */ - bl init_kernel_up + /* kernel-initialization */ + bl init_kernel - /********************************************* - ** Startup code that is common to all CPUs ** - *********************************************/ - - .global _start_secondary_cpus - _start_secondary_cpus: - - /* setup multiprocessor-aware kernel stack-pointer */ - _get_constraints_of_kernel_stacks r0, r1 - _init_kernel_sp r0, r1 - - /* do multiprocessor kernel-initialization */ - bl init_kernel_mp - - /* call the kernel main-routine */ - bl kernel - - /* catch erroneous return of the kernel main-routine */ + /* catch erroneous return of the kernel initialization routine */ 1: b 1b diff --git a/repos/base-hw/src/core/spec/arm/smp/kernel/crt0.s b/repos/base-hw/src/core/spec/arm/smp/kernel/crt0.s new file mode 100644 index 000000000..a0b751679 --- /dev/null +++ b/repos/base-hw/src/core/spec/arm/smp/kernel/crt0.s @@ -0,0 +1,42 @@ +/* + * \brief Startup code for SMP kernel + * \author Martin Stein + * \author Stefan Kalkowski + * \date 2015-12-08 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/************ + ** Macros ** + ************/ + +/* core includes */ +.include "macros.s" + +.section ".text.crt0" + +/********************************************* + ** Startup code that is common to all CPUs ** + *********************************************/ + +.global _start_secondary_cpus +_start_secondary_cpus: + +/* setup multiprocessor-aware kernel stack-pointer */ +_get_constraints_of_kernel_stacks r0, r1 +_init_kernel_sp r0, r1 + +/* do multiprocessor kernel-initialization */ +bl init_kernel_mp + +/* call the kernel main-routine */ +bl kernel + +/* catch erroneous return of the kernel main-routine */ +1: b 1b diff --git a/repos/base-hw/src/core/spec/arm_v6/cpu.cc b/repos/base-hw/src/core/spec/arm_v6/cpu.cc index 5161c1960..fca4949cc 100644 --- a/repos/base-hw/src/core/spec/arm_v6/cpu.cc +++ b/repos/base-hw/src/core/spec/arm_v6/cpu.cc @@ -23,11 +23,11 @@ void Genode::Arm::invalidate_data_caches() { asm volatile ("mcr p15, 0, %[rd], c7, c6, 0" :: [rd]"r"(0) : ); } -void Genode::Cpu::init_virt_kernel(Kernel::Pd* pd) +void Genode::Cpu::init_virt_kernel(Kernel::Pd& pd) { - Cidr::write(pd->asid); + Cidr::write(pd.asid); Dacr::write(Dacr::init_virt_kernel()); - Ttbr0::write(Ttbr0::init((Genode::addr_t)pd->translation_table())); + Ttbr0::write(Ttbr0::init((Genode::addr_t)pd.translation_table())); Ttbcr::write(0); Sctlr::write(Sctlr::init_virt_kernel()); } diff --git a/repos/base-hw/src/core/spec/arm_v7/cpu.cc b/repos/base-hw/src/core/spec/arm_v7/cpu.cc index 3f01d5c9e..432192ed5 100644 --- a/repos/base-hw/src/core/spec/arm_v7/cpu.cc +++ b/repos/base-hw/src/core/spec/arm_v7/cpu.cc @@ -159,11 +159,11 @@ Genode::Arm::Psr::access_t Genode::Arm::Psr::init_user_with_trustzone() } -void Genode::Arm_v7::init_virt_kernel(Kernel::Pd * pd) +void Genode::Arm_v7::init_virt_kernel(Kernel::Pd & pd) { - Cidr::write(pd->asid); + Cidr::write(pd.asid); Dacr::write(Dacr::init_virt_kernel()); - Ttbr0::write(Ttbr0::init((Genode::addr_t)pd->translation_table())); + Ttbr0::write(Ttbr0::init((Genode::addr_t)pd.translation_table())); Ttbcr::write(0); Sctlr::write(Sctlr::init_virt_kernel()); inval_branch_predicts(); diff --git a/repos/base-hw/src/core/spec/arm_v7/smp/kernel/cpu.cc b/repos/base-hw/src/core/spec/arm_v7/smp/kernel/cpu.cc new file mode 100644 index 000000000..dec28516b --- /dev/null +++ b/repos/base-hw/src/core/spec/arm_v7/smp/kernel/cpu.cc @@ -0,0 +1,99 @@ +/* + * \brief Cpu class implementation specific to Armv7 SMP + * \author Martin Stein + * \author Stefan Kalkowski + * \date 2015-12-09 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* core includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* base includes */ +#include +#include + +/* base-hw includes */ +#include + +using namespace Kernel; + +extern "C" void * _start_secondary_cpus; + +Lock & Kernel::data_lock() { return *unmanaged_singleton(); } + + +/** + * Setup kernel enviroment after activating secondary CPUs + */ +extern "C" void init_kernel_mp() +{ + /* + * As updates on a cached kernel lock might not be visible to CPUs that + * have not enabled caches, we can't synchronize the activation of MMU and + * caches. Hence we must avoid write access to kernel data by now. + */ + + /* synchronize data view of all CPUs */ + Cpu::invalidate_data_caches(); + Cpu::invalidate_instr_caches(); + Cpu::data_synchronization_barrier(); + + /* locally initialize interrupt controller */ + pic()->init_cpu_local(); + + /* initialize CPU in physical mode */ + Cpu::init_phys_kernel(); + + /* switch to core address space */ + Cpu::init_virt_kernel(*core_pd()); + + /* + * Now it's safe to use 'cmpxchg' + */ + { + Lock::Guard guard(data_lock()); + + /* + * Now it's save to write to kernel data + */ + + /* TrustZone initialization code */ + init_trustzone(*pic()); + + /* enable performance counter */ + perf_counter()->enable(); + + /* enable timer interrupt */ + unsigned const cpu = Cpu::executing_id(); + pic()->unmask(Timer::interrupt_id(cpu), cpu); + PINF("ok CPU awake"); + } +} + + +void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd) +{ + if (NR_OF_CPUS > 1) { + Genode::Board::secondary_cpus_ip(&_start_secondary_cpus); + data_synchronization_barrier(); + asm volatile ("sev\n"); + } + + init_kernel_mp(); +} diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc index 38406f874..fd31aa592 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc @@ -56,8 +56,8 @@ struct Kernel::Vm_irq : Kernel::Irq */ void occurred() { - Cpu_job * job = cpu_pool()->executing_cpu()->scheduled_job(); - Vm *vm = dynamic_cast(job); + Cpu_job & job = cpu_pool()->executing_cpu()->scheduled_job(); + Vm *vm = dynamic_cast(&job); if (!vm) PERR("VM timer interrupt while VM is not runnning!"); else diff --git a/repos/base-hw/src/core/spec/cortex_a15/cpu.cc b/repos/base-hw/src/core/spec/cortex_a15/cpu.cc index 226916873..2eec39ec0 100644 --- a/repos/base-hw/src/core/spec/cortex_a15/cpu.cc +++ b/repos/base-hw/src/core/spec/cortex_a15/cpu.cc @@ -15,12 +15,12 @@ #include #include -void Genode::Cpu::init_virt_kernel(Kernel::Pd * pd) +void Genode::Cpu::init_virt_kernel(Kernel::Pd & pd) { Mair0::write(Mair0::init_virt_kernel()); Dacr::write(Dacr::init_virt_kernel()); - Ttbr0::write(Ttbr0::init((Genode::addr_t)pd->translation_table(), - pd->asid)); + Ttbr0::write(Ttbr0::init((Genode::addr_t)pd.translation_table(), + pd.asid)); Ttbcr::write(Ttbcr::init_virt_kernel()); Sctlr::write(Sctlr::init_virt_kernel()); inval_branch_predicts(); diff --git a/repos/base-hw/src/core/spec/smp/kernel/kernel.cc b/repos/base-hw/src/core/spec/smp/kernel/kernel.cc new file mode 100644 index 000000000..e57aa09fd --- /dev/null +++ b/repos/base-hw/src/core/spec/smp/kernel/kernel.cc @@ -0,0 +1,37 @@ +/* + * \brief Kernel entrypoint + * \author Martin Stein + * \author Stefan Kalkowski + * \date 2011-10-20 + */ + +/* + * Copyright (C) 2011-2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* core includes */ +#include +#include + + +extern "C" void kernel() +{ + using namespace Kernel; + + Cpu_job * new_job; + unsigned cpu_id; + + { + Lock::Guard guard(data_lock()); + + cpu_id = Cpu::executing_id(); + Cpu * const cpu = cpu_pool()->cpu(cpu_id); + cpu->scheduled_job().exception(cpu_id); + new_job = &cpu->schedule(); + } + + new_job->proceed(cpu_id); +} diff --git a/repos/base-hw/src/core/spec/x86/cpu.cc b/repos/base-hw/src/core/spec/x86/cpu.cc index 895a17102..d6f27528e 100644 --- a/repos/base-hw/src/core/spec/x86/cpu.cc +++ b/repos/base-hw/src/core/spec/x86/cpu.cc @@ -15,20 +15,6 @@ #include #include -void Genode::Cpu::init_virt_kernel(Kernel::Pd * pd) -{ - /* - * Please do not remove the PINF(), because the serial constructor requires - * access to the Bios Data Area, which is available in the initial - * translation table set, but not in the final tables used after - * Cr3::write(). - */ - PINF("Switch to core's final translation table"); - - Cr3::write(Cr3::init((addr_t)pd->translation_table())); -} - - void Genode::Cpu::_init_fpu() { Cr0::access_t cr0_value = Cr0::read(); diff --git a/repos/base-hw/src/core/spec/x86/kernel/cpu.cc b/repos/base-hw/src/core/spec/x86/kernel/cpu.cc index eaf28f75b..c3619c4a5 100644 --- a/repos/base-hw/src/core/spec/x86/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/x86/kernel/cpu.cc @@ -40,3 +40,25 @@ void Cpu_idle::exception(unsigned const cpu) errcode, (void *)ip); assert(0); } + + +void Kernel::Cpu::init(Pic &pic, Kernel::Pd &core_pd) +{ + Timer::disable_pit(); + + _init_fpu(); + + /* + * Please do not remove the PINF(), because the serial constructor requires + * access to the Bios Data Area, which is available in the initial + * translation table set, but not in the final tables used after + * Cr3::write(). + */ + PINF("Switch to core's final translation table"); + + Cr3::write(Cr3::init((addr_t)core_pd.translation_table())); + + /* enable timer interrupt */ + unsigned const cpu = Cpu::executing_id(); + pic.unmask(Timer::interrupt_id(cpu), cpu); +} diff --git a/repos/base-hw/src/core/spec/x86/kernel/vm.cc b/repos/base-hw/src/core/spec/x86/kernel/vm.cc deleted file mode 100644 index 6c0e41c48..000000000 --- a/repos/base-hw/src/core/spec/x86/kernel/vm.cc +++ /dev/null @@ -1,22 +0,0 @@ -/* - * \brief Kernel backend for virtual machines - * \author Martin Stein - * \date 2013-10-30 - */ - -/* - * Copyright (C) 2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* core includes */ -#include - -using namespace Kernel; - - -void Vm::exception(unsigned const cpu) { - PDBG("not implemented"); } - diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/crt0.s b/repos/base-hw/src/core/spec/x86_64/kernel/crt0.s index 3968ce691..178c4f266 100644 --- a/repos/base-hw/src/core/spec/x86_64/kernel/crt0.s +++ b/repos/base-hw/src/core/spec/x86_64/kernel/crt0.s @@ -94,23 +94,10 @@ movq __initial_bx@GOTPCREL(%rip),%rax movq %rbx, (%rax) - /* uniprocessor kernel-initialization which activates multiprocessor */ - call init_kernel_up + /* kernel-initialization */ + call init_kernel - /********************************************* - ** Startup code that is common to all CPUs ** - *********************************************/ - - .global _start_secondary_cpus - _start_secondary_cpus: - - /* do multiprocessor kernel-initialization */ - call init_kernel_mp - - /* call the kernel main-routine */ - call kernel - - /* catch erroneous return of the kernel main-routine */ + /* catch erroneous return of the kernel initialization */ 1: jmp 1b