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