diff --git a/repos/base-hw/lib/mk/spec/arm/core-hw.inc b/repos/base-hw/lib/mk/spec/arm/core-hw.inc index d8992ef3e6..83701473a0 100644 --- a/repos/base-hw/lib/mk/spec/arm/core-hw.inc +++ b/repos/base-hw/lib/mk/spec/arm/core-hw.inc @@ -10,7 +10,6 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/core/spec/arm # add C++ sources SRC_CC += spec/32bit/memory_map.cc SRC_CC += spec/arm/kernel/thread.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/x86_pc/core-hw.mk b/repos/base-hw/lib/mk/spec/x86_pc/core-hw.mk index 760a4cb0ab..53c5644081 100644 --- a/repos/base-hw/lib/mk/spec/x86_pc/core-hw.mk +++ b/repos/base-hw/lib/mk/spec/x86_pc/core-hw.mk @@ -16,7 +16,6 @@ SRC_S += spec/x86_64/exception_vector.s SRC_CC += kernel/vm_thread_off.cc SRC_CC += spec/x86_64/pic.cc SRC_CC += spec/x86_64/timer.cc -SRC_CC += spec/x86_64/kernel/cpu_exception.cc SRC_CC += spec/x86_64/kernel/thread_exception.cc SRC_CC += spec/x86_64/platform_support.cc SRC_CC += spec/x86/platform_services.cc diff --git a/repos/base-hw/src/core/irq_session_component.h b/repos/base-hw/src/core/irq_session_component.h index af54837a2b..5d7ff88161 100644 --- a/repos/base-hw/src/core/irq_session_component.h +++ b/repos/base-hw/src/core/irq_session_component.h @@ -19,6 +19,8 @@ #include #include +#include + namespace Genode { class Irq_session_component; } diff --git a/repos/base-hw/src/core/kernel/cpu.cc b/repos/base-hw/src/core/kernel/cpu.cc index 959aff4dac..5d77846205 100644 --- a/repos/base-hw/src/core/kernel/cpu.cc +++ b/repos/base-hw/src/core/kernel/cpu.cc @@ -120,17 +120,23 @@ Cpu_job::~Cpu_job() } -/************** - ** Cpu_idle ** - **************/ - -void Cpu_idle::_main() { while (1) { Genode::Cpu::wait_for_interrupt(); } } - - /********* ** Cpu ** *********/ +extern "C" void idle_thread_main(void); + +Cpu::Idle_thread::Idle_thread(Cpu * const cpu) +: Thread("idle") +{ + regs->ip = (addr_t)&idle_thread_main; + + affinity(cpu); + Thread::_pd = core_pd(); + Thread::_pd->admit(*regs); +} + + void Cpu::set_timeout(Timeout * const timeout, time_t const duration_us) { _timer.set_timeout(timeout, _timer.us_to_ticks(duration_us)); } @@ -185,8 +191,8 @@ Cpu_job & Cpu::schedule() Cpu::Cpu(unsigned const id) : - _id(id), _timer(_id), _idle(this), - _scheduler(&_idle, _quota(), _fill()), + _id(id), _timer(_id), + _scheduler(&_idle, _quota(), _fill()), _idle(this), _ipi_irq(*this), _timer_irq(_timer.interrupt_id(), *this) { } diff --git a/repos/base-hw/src/core/kernel/cpu.h b/repos/base-hw/src/core/kernel/cpu.h index c2b29f2696..48eb0b1510 100644 --- a/repos/base-hw/src/core/kernel/cpu.h +++ b/repos/base-hw/src/core/kernel/cpu.h @@ -16,30 +16,12 @@ #define _CORE__KERNEL__CPU_H_ /* core includes */ -#include -#include -#include +#include #include - -namespace Hw { class Page_table; } +#include namespace Kernel { - /** - * Context of a job (thread, VM, idle) that shall be executed by a CPU - */ - class Cpu_job; - - /** - * Ability to do a domain update on all CPUs - */ - class Cpu_domain_update; - - /** - * Execution context that is scheduled on CPU idle - */ - class Cpu_idle; - /** * Class for kernel data that is needed to manage a specific CPU */ @@ -56,158 +38,6 @@ namespace Kernel Cpu_pool * cpu_pool(); } -class Kernel::Cpu_domain_update : public Double_list_item -{ - friend class Cpu_domain_update_list; - - private: - - bool _pending[NR_OF_CPUS]; - unsigned _domain_id; - - /** - * Domain-update back-end - */ - void _domain_update(); - - /** - * Perform the domain update on the executing CPU - */ - void _do(); - - protected: - - Cpu_domain_update(); - - /** - * Do an update of domain 'id' on all CPUs and return if this blocks - */ - bool _do_global(unsigned const id); - - /** - * Notice that the update isn't pending on any CPU anymore - */ - virtual void _cpu_domain_update_unblocks() = 0; -}; - -class Kernel::Cpu_job : public Genode::Cpu::User_context, public Cpu_share -{ - protected: - - Cpu * _cpu; - - /** - * Handle interrupt exception that occured during execution on CPU 'id' - */ - void _interrupt(unsigned const id); - - /** - * Activate our own CPU-share - */ - void _activate_own_share(); - - /** - * Deactivate our own CPU-share - */ - void _deactivate_own_share(); - - /** - * Yield the currently scheduled CPU share of this context - */ - void _yield(); - - /** - * Return wether we are allowed to help job 'j' with our CPU-share - */ - bool _helping_possible(Cpu_job * const j) { return j->_cpu == _cpu; } - - public: - - /** - * Handle exception that occured during execution on CPU 'id' - */ - virtual void exception(unsigned const id) = 0; - - /** - * Continue execution on CPU 'id' - */ - virtual void proceed(unsigned const id) = 0; - - /** - * Return which job currently uses our CPU-share - */ - virtual Cpu_job * helping_sink() = 0; - - /** - * Construct a job with scheduling priority 'p' and time quota 'q' - */ - Cpu_job(Cpu_priority const p, unsigned const q); - - /** - * Destructor - */ - ~Cpu_job(); - - /** - * Link job to CPU 'cpu' - */ - void affinity(Cpu * const cpu); - - /** - * Set CPU quota of the job to 'q' - */ - void quota(unsigned const q); - - /** - * Return wether our CPU-share is currently active - */ - bool own_share_active() { return Cpu_share::ready(); } - - void timeout(Timeout * const timeout, time_t const duration_us); - - time_t timeout_age_us(Timeout const * const timeout) const; - - time_t timeout_max_us() const; - - time_t time() const; - - /*************** - ** Accessors ** - ***************/ - - void cpu(Cpu * const cpu) { _cpu = cpu; } -}; - -class Kernel::Cpu_idle : public Cpu_job -{ - private: - - static constexpr size_t stack_size = sizeof(addr_t) * 32; - - char _stack[stack_size] __attribute__((aligned(16))); - - /** - * Main function of all idle threads - */ - static void _main(); - - public: - - /** - * Construct idle context for CPU 'cpu' - */ - Cpu_idle(Cpu * const cpu); - - - /* - * Cpu_job interface - */ - - void exception(unsigned const cpu); - void proceed(unsigned const cpu_id); - Cpu_job * helping_sink() { return this; } -}; - class Kernel::Cpu : public Genode::Cpu, public Irq::Pool, private Timeout { private: @@ -243,10 +73,20 @@ class Kernel::Cpu : public Genode::Cpu, public Irq::Pool, private Timeout void trigger(unsigned const cpu_id); }; + + struct Idle_thread : Kernel::Thread + { + /** + * Construct idle context for CPU 'cpu' + */ + Idle_thread(Cpu * const cpu); + }; + + unsigned const _id; Timer _timer; - Cpu_idle _idle; Cpu_scheduler _scheduler; + Idle_thread _idle; Ipi _ipi_irq; Irq _timer_irq; /* timer IRQ implemented as empty event */ diff --git a/repos/base-hw/src/core/kernel/cpu_context.h b/repos/base-hw/src/core/kernel/cpu_context.h new file mode 100644 index 0000000000..7c86d18d6b --- /dev/null +++ b/repos/base-hw/src/core/kernel/cpu_context.h @@ -0,0 +1,160 @@ +/* + * \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-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _CORE__KERNEL__CPU_CONTEXT_H_ +#define _CORE__KERNEL__CPU_CONTEXT_H_ + +/* core includes */ +#include +#include +#include + +namespace Kernel +{ + class Cpu; + + /** + * Context of a job (thread, VM, idle) that shall be executed by a CPU + */ + class Cpu_job; + + /** + * Ability to do a domain update on all CPUs + */ + class Cpu_domain_update; +} + +class Kernel::Cpu_domain_update : public Double_list_item +{ + friend class Cpu_domain_update_list; + + private: + + bool _pending[NR_OF_CPUS]; + unsigned _domain_id; + + /** + * Domain-update back-end + */ + void _domain_update(); + + /** + * Perform the domain update on the executing CPU + */ + void _do(); + + protected: + + Cpu_domain_update(); + + /** + * Do an update of domain 'id' on all CPUs and return if this blocks + */ + bool _do_global(unsigned const id); + + /** + * Notice that the update isn't pending on any CPU anymore + */ + virtual void _cpu_domain_update_unblocks() = 0; +}; + +class Kernel::Cpu_job : public Genode::Cpu::User_context, public Cpu_share +{ + protected: + + Cpu * _cpu; + + /** + * Handle interrupt exception that occured during execution on CPU 'id' + */ + void _interrupt(unsigned const id); + + /** + * Activate our own CPU-share + */ + void _activate_own_share(); + + /** + * Deactivate our own CPU-share + */ + void _deactivate_own_share(); + + /** + * Yield the currently scheduled CPU share of this context + */ + void _yield(); + + /** + * Return wether we are allowed to help job 'j' with our CPU-share + */ + bool _helping_possible(Cpu_job * const j) { return j->_cpu == _cpu; } + + public: + + /** + * Handle exception that occured during execution on CPU 'id' + */ + virtual void exception(unsigned const id) = 0; + + /** + * Continue execution on CPU 'id' + */ + virtual void proceed(unsigned const id) = 0; + + /** + * Return which job currently uses our CPU-share + */ + virtual Cpu_job * helping_sink() = 0; + + /** + * Construct a job with scheduling priority 'p' and time quota 'q' + */ + Cpu_job(Cpu_priority const p, unsigned const q); + + /** + * Destructor + */ + ~Cpu_job(); + + /** + * Link job to CPU 'cpu' + */ + void affinity(Cpu * const cpu); + + /** + * Set CPU quota of the job to 'q' + */ + void quota(unsigned const q); + + /** + * Return wether our CPU-share is currently active + */ + bool own_share_active() { return Cpu_share::ready(); } + + void timeout(Timeout * const timeout, time_t const duration_us); + + time_t timeout_age_us(Timeout const * const timeout) const; + + time_t timeout_max_us() const; + + time_t time() const; + + /*************** + ** Accessors ** + ***************/ + + void cpu(Cpu * const cpu) { _cpu = cpu; } +}; + +#endif /* _CORE__KERNEL__CPU_CONTEXT_H_ */ diff --git a/repos/base-hw/src/core/kernel/cpu_scheduler.cc b/repos/base-hw/src/core/kernel/cpu_scheduler.cc index 9db8e91f41..5595636712 100644 --- a/repos/base-hw/src/core/kernel/cpu_scheduler.cc +++ b/repos/base-hw/src/core/kernel/cpu_scheduler.cc @@ -160,6 +160,7 @@ bool Cpu_scheduler::ready_check(Share * const s1) void Cpu_scheduler::ready(Share * const s) { assert(!s->_ready && s != _idle); + s->_ready = 1; s->_fill = _fill; _fills.insert_tail(s); diff --git a/repos/base-hw/src/core/kernel/init.cc b/repos/base-hw/src/core/kernel/init.cc index c57add6ddb..20195fbc7e 100644 --- a/repos/base-hw/src/core/kernel/init.cc +++ b/repos/base-hw/src/core/kernel/init.cc @@ -14,6 +14,7 @@ /* core includes */ #include +#include #include #include #include diff --git a/repos/base-hw/src/core/kernel/pd.h b/repos/base-hw/src/core/kernel/pd.h index 2e6e67428b..f5e8a307f2 100644 --- a/repos/base-hw/src/core/kernel/pd.h +++ b/repos/base-hw/src/core/kernel/pd.h @@ -16,7 +16,8 @@ #define _CORE__KERNEL__PD_H_ /* core includes */ -#include +#include +#include #include #include @@ -33,7 +34,7 @@ namespace Kernel } -class Kernel::Pd : public Cpu::Pd, +class Kernel::Pd : public Genode::Cpu::Pd, public Kernel::Object { public: @@ -65,7 +66,7 @@ class Kernel::Pd : public Cpu::Pd, /** * Let the CPU context 'c' join the PD */ - void admit(Cpu::Context & c); + void admit(Genode::Cpu::Context & c); static capid_t syscall_create(void * const dst, diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc index d46cac7bfa..6e845aa623 100644 --- a/repos/base-hw/src/core/kernel/thread.cc +++ b/repos/base-hw/src/core/kernel/thread.cc @@ -24,6 +24,7 @@ /* core includes */ #include +#include #include #include #include diff --git a/repos/base-hw/src/core/kernel/thread.h b/repos/base-hw/src/core/kernel/thread.h index c97f0403b5..4a9ad52ed1 100644 --- a/repos/base-hw/src/core/kernel/thread.h +++ b/repos/base-hw/src/core/kernel/thread.h @@ -17,7 +17,7 @@ /* core includes */ #include #include -#include +#include #include #include @@ -36,8 +36,6 @@ class Kernel::Thread public Ipc_node, public Signal_context_killer, public Signal_handler, private Timeout { - friend class Core_thread; - private: enum { START_VERBOSE = 0 }; @@ -85,11 +83,15 @@ class Kernel::Thread int _route_event(unsigned const event_id, Signal_context * const signal_context_id); + protected: + /** * Switch from an inactive state to the active state */ void _become_active(); + private: + /** * Switch from the active state to the inactive state 's' */ @@ -241,7 +243,7 @@ class Kernel::Thread * \param label debugging label */ Thread(char const * const label) - : Thread(Cpu_priority::MAX, 0, label, true) { } + : Thread(Cpu_priority::MIN, 0, label, true) { } /** * Syscall to create a thread diff --git a/repos/base-hw/src/core/kernel/vm.h b/repos/base-hw/src/core/kernel/vm.h index cbed428c68..0d8999cc38 100644 --- a/repos/base-hw/src/core/kernel/vm.h +++ b/repos/base-hw/src/core/kernel/vm.h @@ -17,6 +17,7 @@ #include /* core includes */ +#include #include #include #include diff --git a/repos/base-hw/src/core/spec/arm/cpu.cc b/repos/base-hw/src/core/spec/arm/cpu.cc index acc2f6ec32..3217086f43 100644 --- a/repos/base-hw/src/core/spec/arm/cpu.cc +++ b/repos/base-hw/src/core/spec/arm/cpu.cc @@ -22,4 +22,5 @@ void Genode::Arm_cpu::User_context::init(bool privileged) Psr::F::set(v, 1); Psr::A::set(v, 1); regs->cpsr = v; + regs->cpu_exception = Genode::Arm_cpu::Context::RESET; } diff --git a/repos/base-hw/src/core/spec/arm/cpu_support.h b/repos/base-hw/src/core/spec/arm/cpu_support.h index fe0c05f139..7fa39bc719 100644 --- a/repos/base-hw/src/core/spec/arm/cpu_support.h +++ b/repos/base-hw/src/core/spec/arm/cpu_support.h @@ -123,18 +123,6 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu Kernel::Call_arg user_arg_3() const { return regs->r3; } Kernel::Call_arg user_arg_4() const { return regs->r4; } - /** - * Initialize thread context - * - * \param table physical base of appropriate translation table - * \param pd_id kernel name of appropriate protection domain - */ - void init_thread(addr_t const table, unsigned const pd_id) - { - regs->protection_domain(pd_id); - regs->translation_table(table); - } - /** * Return if the context is in a page fault due to translation miss * @@ -245,8 +233,6 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu for (; base < top; base += line_size) { Icimvau::write(base); } } - static void wait_for_interrupt(); - /************* ** Dummies ** diff --git a/repos/base-hw/src/core/spec/arm/cpu_trustzone.cc b/repos/base-hw/src/core/spec/arm/cpu_trustzone.cc index 948d24de6f..a938b833c1 100644 --- a/repos/base-hw/src/core/spec/arm/cpu_trustzone.cc +++ b/repos/base-hw/src/core/spec/arm/cpu_trustzone.cc @@ -22,4 +22,5 @@ void Genode::Arm_cpu::User_context::init(bool privileged) Psr::I::set(v, 1); Psr::A::set(v, 1); regs->cpsr = v; + regs->cpu_exception = Cpu::Context::RESET; } diff --git a/repos/base-hw/src/core/spec/arm/exception_vector.s b/repos/base-hw/src/core/spec/arm/exception_vector.s index 9cf92419d4..d77e2d54b9 100644 --- a/repos/base-hw/src/core/spec/arm/exception_vector.s +++ b/repos/base-hw/src/core/spec/arm/exception_vector.s @@ -121,3 +121,15 @@ _kernel_entry: .long kernel + + +.section .text + + /******************************* + ** idle loop for idle thread ** + *******************************/ + + .global idle_thread_main + idle_thread_main: + wfi + b idle_thread_main 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 deleted file mode 100644 index 97e1dc5b6a..0000000000 --- a/repos/base-hw/src/core/spec/arm/kernel/cpu_idle.cc +++ /dev/null @@ -1,58 +0,0 @@ -/* - * \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-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* 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); - regs->cpu_exception = Cpu::Context::RESET; - regs->ip = (addr_t)&_main; - regs->sp = (addr_t)&_stack[stack_size]; - init_thread((addr_t)core_pd()->translation_table(), core_pd()->asid); - init(true); -} - - -void Cpu_idle::exception(unsigned const cpu) -{ - switch (regs->cpu_exception) { - case Cpu::Context::INTERRUPT_REQUEST: _interrupt(cpu); return; - case Cpu::Context::FAST_INTERRUPT_REQUEST: _interrupt(cpu); return; - case Cpu::Context::RESET: return; - default: Genode::raw("Unknown exception in idle thread"); } -} - - -extern void * kernel_stack; - -void Cpu_idle::proceed(unsigned const cpu) -{ - regs->cpu_exception = (addr_t)&kernel_stack + Cpu::KERNEL_STACK_SIZE * (cpu+1); - - asm volatile("mov sp, %0 \n" - "msr spsr_cxsf, %1 \n" - "mov lr, %2 \n" - "ldm sp, {r0-r14}^ \n" - "subs pc, lr, #0 \n" - :: "r" (static_cast(&*regs)), - "r" (regs->cpsr), "r" (regs->ip)); -} diff --git a/repos/base-hw/src/core/spec/arm/kernel/pd.cc b/repos/base-hw/src/core/spec/arm/kernel/pd.cc index 5297d2a319..e40e1805db 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/pd.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/pd.cc @@ -16,6 +16,7 @@ /* core includes */ #include +#include #include using Asid_allocator = Genode::Bit_allocator<256>; diff --git a/repos/base-hw/src/core/spec/arm/kernel/thread.cc b/repos/base-hw/src/core/spec/arm/kernel/thread.cc index 65da234938..b3a6d6c60f 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/thread.cc @@ -12,16 +12,16 @@ * under the terms of the GNU Affero General Public License version 3. */ -#include -#include +#include #include +#include +#include using namespace Kernel; void Kernel::Thread::_init() { init(_core); - regs->cpu_exception = Cpu::Context::RESET; } diff --git a/repos/base-hw/src/core/spec/arm/kernel/thread_update_pd.cc b/repos/base-hw/src/core/spec/arm/kernel/thread_update_pd.cc index 2b52aa300c..011d4deec5 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/thread_update_pd.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/thread_update_pd.cc @@ -12,6 +12,7 @@ */ /* core includes */ #include +#include #include void Kernel::Thread::_call_update_pd() 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 2812d621d1..be43ad7628 100644 --- a/repos/base-hw/src/core/spec/arm_v6/cpu.cc +++ b/repos/base-hw/src/core/spec/arm_v6/cpu.cc @@ -17,6 +17,3 @@ void Genode::Arm_cpu::clean_invalidate_data_cache() { asm volatile ("mcr p15, 0, %[rd], c7, c14, 0" :: [rd]"r"(0) : ); } - - -void Genode::Arm_cpu::wait_for_interrupt() { /* FIXME */ } diff --git a/repos/base-hw/src/core/spec/arm_v7/cpu_support.h b/repos/base-hw/src/core/spec/arm_v7/cpu_support.h index 4faa43e8bb..c7ecc99708 100644 --- a/repos/base-hw/src/core/spec/arm_v7/cpu_support.h +++ b/repos/base-hw/src/core/spec/arm_v7/cpu_support.h @@ -22,11 +22,6 @@ namespace Genode { struct Arm_v7_cpu; } struct Genode::Arm_v7_cpu : Arm_cpu { - /** - * Wait for the next interrupt as cheap as possible - */ - static void wait_for_interrupt() { asm volatile ("wfi"); } - /** * Write back dirty lines of inner data cache and invalidate all */ 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 7fb6517d89..2cd916fe4f 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 @@ -15,6 +15,7 @@ #include #include +#include #include namespace Kernel diff --git a/repos/base-hw/src/core/spec/cortex_a15/cpu.h b/repos/base-hw/src/core/spec/cortex_a15/cpu.h index b52b7c22a0..8f5eab89c5 100644 --- a/repos/base-hw/src/core/spec/cortex_a15/cpu.h +++ b/repos/base-hw/src/core/spec/cortex_a15/cpu.h @@ -163,6 +163,7 @@ class Genode::Cpu : public Arm_v7_cpu Psr::F::set(v, 1); Psr::A::set(v, 1); regs->cpsr = v; + regs->cpu_exception = Cpu::Context::RESET; } /** @@ -179,18 +180,6 @@ class Genode::Cpu : public Arm_v7_cpu Kernel::Call_arg user_arg_3() const { return regs->r3; } Kernel::Call_arg user_arg_4() const { return regs->r4; } - /** - * Initialize thread context - * - * \param table physical base of appropriate translation table - * \param pd_id kernel name of appropriate protection domain - */ - void init_thread(addr_t const table, unsigned const pd_id) - { - regs->protection_domain(pd_id); - regs->translation_table(table); - } - /** * Return if the context is in a page fault due to translation miss * diff --git a/repos/base-hw/src/core/spec/cortex_a15/kernel/cpu.cc b/repos/base-hw/src/core/spec/cortex_a15/kernel/cpu.cc index ea33314aec..de4585de22 100644 --- a/repos/base-hw/src/core/spec/cortex_a15/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/cortex_a15/kernel/cpu.cc @@ -12,6 +12,7 @@ */ /* core includes */ +#include #include #include #include @@ -29,7 +30,7 @@ extern "C" void * _start_secondary_cpus; static volatile bool primary_cpu = true; -void Kernel::Cpu::init(Kernel::Pic &pic/*, Kernel::Pd & core_pd, Genode::Board & board*/) +void Kernel::Cpu::init(Kernel::Pic &pic) { { Lock::Guard guard(data_lock()); diff --git a/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc b/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc index 33c92b3c4b..7ea1b13c91 100644 --- a/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc @@ -14,6 +14,7 @@ /* core includes */ #include #include +#include #include #include #include diff --git a/repos/base-hw/src/core/spec/riscv/cpu.h b/repos/base-hw/src/core/spec/riscv/cpu.h index 3a3261769e..5f6de03352 100644 --- a/repos/base-hw/src/core/spec/riscv/cpu.h +++ b/repos/base-hw/src/core/spec/riscv/cpu.h @@ -80,10 +80,14 @@ class Genode::Cpu : public Hw::Riscv_cpu { Align_at regs; - /** - * Constructor - */ - User_context(); + User_context() + { + /* + * initialize cpu_exception with something that gets ignored in + * Thread::exception + */ + regs->cpu_exception = IRQ_FLAG; + } /** * Support for kernel calls @@ -98,22 +102,8 @@ class Genode::Cpu : public Hw::Riscv_cpu Kernel::Call_arg user_arg_2() const { return regs->a2; } Kernel::Call_arg user_arg_3() const { return regs->a3; } Kernel::Call_arg user_arg_4() const { return regs->a4; } - - /** - * Initialize thread context - * - * \param table physical base of appropriate translation table - * \param pd_id kernel name of appropriate protection domain - */ - void init_thread(addr_t const table, unsigned const pd_id) - { - regs->protection_domain(pd_id); - regs->translation_table(table); - } }; - static void wait_for_interrupt() { asm volatile ("wfi"); }; - /** * From the manual * diff --git a/repos/base-hw/src/core/spec/riscv/exception_vector.s b/repos/base-hw/src/core/spec/riscv/exception_vector.s index 261ed09112..fbf8a26a12 100644 --- a/repos/base-hw/src/core/spec/riscv/exception_vector.s +++ b/repos/base-hw/src/core/spec/riscv/exception_vector.s @@ -52,3 +52,15 @@ _kernel_entry: la x30, kernel jalr x30 + + +.section .text + + /******************************* + ** idle loop for idle thread ** + *******************************/ + + .global idle_thread_main + idle_thread_main: + wfi + j idle_thread_main diff --git a/repos/base-hw/src/core/spec/riscv/kernel/cpu.cc b/repos/base-hw/src/core/spec/riscv/kernel/cpu.cc index eec93e1e8a..dc6647db4e 100644 --- a/repos/base-hw/src/core/spec/riscv/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/riscv/kernel/cpu.cc @@ -12,50 +12,8 @@ */ /* core includes */ -#include #include -#include - #include -using namespace Kernel; - void Kernel::Cpu::init(Kernel::Pic &pic) { Stvec::write(Hw::Mm::supervisor_exception_vector().base); } - - -Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::MIN, 0) -{ - Cpu_job::cpu(cpu); - regs->cpu_exception = Cpu::Context::RESET; - regs->ip = (addr_t)&_main; - regs->sp = (addr_t)&_stack[stack_size]; - init_thread((addr_t)core_pd()->translation_table(), core_pd()->asid); -} - - -void Cpu_idle::exception(unsigned const cpu) -{ - if (regs->is_irq()) { - _interrupt(cpu); - return; - } else if (regs->cpu_exception == Cpu::Context::RESET) return; - - ASSERT_NEVER_CALLED; -} - - -void Cpu_idle::proceed(unsigned const) -{ - asm volatile("csrw sscratch, %1 \n" - "mv x31, %0 \n" - "ld x30, (x31) \n" - "csrw sepc, x30 \n" - ".irp reg,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17," - "18,19,20,21,22,23,24,25,26,27,28,29,30 \n" - " ld x\\reg, 8 * (\\reg + 1)(x31) \n" - ".endr \n" - "csrrw x31, sscratch, x31 \n" - "sret \n" - :: "r" (&*regs), "r" (regs->t6) : "x30", "x31"); -} diff --git a/repos/base-hw/src/core/spec/riscv/kernel/pd.cc b/repos/base-hw/src/core/spec/riscv/kernel/pd.cc index fc14a2f06b..b964765055 100644 --- a/repos/base-hw/src/core/spec/riscv/kernel/pd.cc +++ b/repos/base-hw/src/core/spec/riscv/kernel/pd.cc @@ -11,9 +11,11 @@ * under the terms of the GNU Affero General Public License version 3. */ -#include +#include +#include #include +#include #include using Asid_allocator = Genode::Bit_allocator<256>; diff --git a/repos/base-hw/src/core/spec/riscv/kernel/thread.cc b/repos/base-hw/src/core/spec/riscv/kernel/thread.cc index 4a76df9510..7bdd7523ff 100644 --- a/repos/base-hw/src/core/spec/riscv/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/riscv/kernel/thread.cc @@ -21,24 +21,26 @@ void Kernel::Thread::_init() { } void Thread::exception(unsigned const cpu) { + using Context = Genode::Cpu::Context; + if (regs->is_irq()) return; switch(regs->cpu_exception) { - case Cpu::Context::ECALL_FROM_USER: - case Cpu::Context::ECALL_FROM_SUPERVISOR: + case Context::ECALL_FROM_USER: + case Context::ECALL_FROM_SUPERVISOR: _call(); regs->ip += 4; /* set to next instruction */ break; - case Cpu::Context::INSTRUCTION_PAGE_FAULT: - case Cpu::Context::STORE_PAGE_FAULT: - case Cpu::Context::LOAD_PAGE_FAULT: + case Context::INSTRUCTION_PAGE_FAULT: + case Context::STORE_PAGE_FAULT: + case Context::LOAD_PAGE_FAULT: _mmu_exception(); break; default: Genode::error(*this, ": unhandled exception ", regs->cpu_exception, " at ip=", (void*)regs->ip, - " addr=", Genode::Hex(Cpu::Sbadaddr::read())); + " addr=", Genode::Hex(Genode::Cpu::Sbadaddr::read())); _die(); } } @@ -48,7 +50,7 @@ void Thread::_mmu_exception() { _become_inactive(AWAITS_RESTART); _fault_pd = (addr_t)_pd->platform_pd(); - _fault_addr = Cpu::Sbadaddr::read(); + _fault_addr = Genode::Cpu::Sbadaddr::read(); if (_pager) _pager->submit(1); } @@ -56,13 +58,13 @@ void Thread::_mmu_exception() void Thread::_call_update_pd() { - Cpu::sfence(); + Genode::Cpu::sfence(); } void Thread::_call_update_data_region() { - Cpu::sfence(); + Genode::Cpu::sfence(); } diff --git a/repos/base-hw/src/core/spec/riscv/platform_support.cc b/repos/base-hw/src/core/spec/riscv/platform_support.cc index cb7c02b715..18c1241a9a 100644 --- a/repos/base-hw/src/core/spec/riscv/platform_support.cc +++ b/repos/base-hw/src/core/spec/riscv/platform_support.cc @@ -21,8 +21,6 @@ using namespace Genode; -Cpu::User_context::User_context() { } - void Platform::_init_io_port_alloc() { } void Platform::_init_additional() { } diff --git a/repos/base-hw/src/core/spec/x86_64/cpu.h b/repos/base-hw/src/core/spec/x86_64/cpu.h index 6ebef8e067..7740c42bcd 100644 --- a/repos/base-hw/src/core/spec/x86_64/cpu.h +++ b/repos/base-hw/src/core/spec/x86_64/cpu.h @@ -128,11 +128,6 @@ class Genode::Cpu Fpu & fpu() { return _fpu; } - /** - * Wait for the next interrupt as cheap as possible - */ - static void wait_for_interrupt() { asm volatile ("pause"); } - /** * Return wether to retry an undefined user instruction after this call */ diff --git a/repos/base-hw/src/core/spec/x86_64/exception_vector.s b/repos/base-hw/src/core/spec/x86_64/exception_vector.s index 8f289ea1e1..747a88c916 100644 --- a/repos/base-hw/src/core/spec/x86_64/exception_vector.s +++ b/repos/base-hw/src/core/spec/x86_64/exception_vector.s @@ -167,3 +167,15 @@ .space 64 _define_gdt TSS + + +.section .text + + /******************************* + ** idle loop for idle thread ** + *******************************/ + + .global idle_thread_main + idle_thread_main: + pause + jmp idle_thread_main diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc b/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc index 2938a41bcf..d6fe35e3e4 100644 --- a/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc @@ -12,59 +12,15 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* Genode includes */ -#include - /* core includes */ #include #include #include -using namespace Kernel; - - -Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::MIN, 0) -{ - Cpu::Gdt::init(); - Cpu_job::cpu(cpu); - regs->ip = (addr_t)&_main; - regs->sp = (addr_t)&_stack[stack_size]; - regs->cs = 0x8; - regs->ss = 0x10; - regs->init((addr_t)core_pd()->translation_table(), true); -} - -extern void * __tss_client_context_ptr; - -void Cpu_idle::proceed(unsigned const) -{ - void * * tss_stack_ptr = (&__tss_client_context_ptr); - *tss_stack_ptr = ®s->cr3; - - asm volatile("mov %0, %%rsp \n" - "popq %%r8 \n" - "popq %%r9 \n" - "popq %%r10 \n" - "popq %%r11 \n" - "popq %%r12 \n" - "popq %%r13 \n" - "popq %%r14 \n" - "popq %%r15 \n" - "popq %%rax \n" - "popq %%rbx \n" - "popq %%rcx \n" - "popq %%rdx \n" - "popq %%rdi \n" - "popq %%rsi \n" - "popq %%rbp \n" - "add $16, %%rsp \n" - "iretq \n" - :: "r" (®s->r8)); -} - void Kernel::Cpu::init(Pic &pic) { + Cpu::Gdt::init(); Idt::init(); Tss::init(); @@ -78,4 +34,4 @@ void Kernel::Cpu::init(Pic &pic) } -void Cpu_domain_update::_domain_update() { } +void Kernel::Cpu_domain_update::_domain_update() { } diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/cpu_exception.cc b/repos/base-hw/src/core/spec/x86_64/kernel/cpu_exception.cc deleted file mode 100644 index e3114dca96..0000000000 --- a/repos/base-hw/src/core/spec/x86_64/kernel/cpu_exception.cc +++ /dev/null @@ -1,32 +0,0 @@ -/* - * \brief Kernel backend for protection domains - * \author Reto Buerki - * \author Stefan Kalkowski - * \date 2016-01-11 - */ - -/* - * Copyright (C) 2016-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#include -#include - -void Kernel::Cpu_idle::exception(unsigned const cpu) -{ - if (regs->trapno == Cpu::Context::RESET) return; - - if (regs->trapno >= Cpu::Context::INTERRUPTS_START && - regs->trapno <= Cpu::Context::INTERRUPTS_END) { - _interrupt(cpu); - return; - } - - Genode::warning("Unknown exception ", regs->trapno, " with error code ", - regs->errcode, " at ip=", (void *)regs->ip); - - ASSERT_NEVER_CALLED; -} diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/pd.cc b/repos/base-hw/src/core/spec/x86_64/kernel/pd.cc index 837f2d3ac0..2c5392b0c7 100644 --- a/repos/base-hw/src/core/spec/x86_64/kernel/pd.cc +++ b/repos/base-hw/src/core/spec/x86_64/kernel/pd.cc @@ -32,5 +32,5 @@ Kernel::Pd::~Pd() } -void Kernel::Pd::admit(Kernel::Cpu::Context & c) { +void Kernel::Pd::admit(Genode::Cpu::Context & c) { c.init((addr_t)translation_table(), this == Kernel::core_pd()); } diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/thread.cc b/repos/base-hw/src/core/spec/x86_64/kernel/thread.cc index c2da5aaea5..c167e45f13 100644 --- a/repos/base-hw/src/core/spec/x86_64/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/x86_64/kernel/thread.cc @@ -41,7 +41,7 @@ void Kernel::Thread::_mmu_exception() { _become_inactive(AWAITS_RESTART); _fault_pd = (addr_t)_pd->platform_pd(); - _fault_addr = Cpu::Cr2::read(); + _fault_addr = Genode::Cpu::Cr2::read(); _fault_writes = (regs->errcode & ERR_P) && (regs->errcode & ERR_W); _fault_exec = (regs->errcode & ERR_P) && (regs->errcode & ERR_I); diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/thread_exception.cc b/repos/base-hw/src/core/spec/x86_64/kernel/thread_exception.cc index 6a215f349a..8e4f51b0cd 100644 --- a/repos/base-hw/src/core/spec/x86_64/kernel/thread_exception.cc +++ b/repos/base-hw/src/core/spec/x86_64/kernel/thread_exception.cc @@ -14,6 +14,7 @@ */ /* core includes */ +#include #include using namespace Kernel; diff --git a/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu_exception.cc b/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu_exception.cc deleted file mode 100644 index 3257dbe6e0..0000000000 --- a/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu_exception.cc +++ /dev/null @@ -1,33 +0,0 @@ -/* - * \brief Kernel backend for protection domains - * \author Reto Buerki - * \author Stefan Kalkowski - * \date 2016-01-11 - */ - -/* - * Copyright (C) 2016-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#include -#include - -void Kernel::Cpu_idle::exception(unsigned const cpu) -{ - if (regs->trapno == Cpu::Context::RESET) return; - - if (regs->trapno >= Cpu::Context::INTERRUPTS_START && - regs->trapno <= Cpu::Context::INTERRUPTS_END) { - pic()->irq_occurred(regs->trapno); - _interrupt(cpu); - return; - } - - Genode::warning("Unknown exception ", regs->trapno, " with error code ", - regs->errcode, " at ip=", (void *)regs->ip); - - ASSERT_NEVER_CALLED; -}