diff --git a/repos/base-hw/lib/mk/core.inc b/repos/base-hw/lib/mk/core.inc index 56c2dfd8c..d20e062b3 100644 --- a/repos/base-hw/lib/mk/core.inc +++ b/repos/base-hw/lib/mk/core.inc @@ -55,7 +55,6 @@ SRC_CC += kernel/signal_receiver.cc SRC_CC += kernel/irq.cc SRC_CC += kernel/pd.cc SRC_CC += kernel/processor.cc -SRC_CC += kernel/processor_pool.cc # add assembly sources SRC_S += boot_modules.s diff --git a/repos/base-hw/src/core/include/kernel/processor.h b/repos/base-hw/src/core/include/kernel/processor.h index 8af8def8f..5dd9728c6 100644 --- a/repos/base-hw/src/core/include/kernel/processor.h +++ b/repos/base-hw/src/core/include/kernel/processor.h @@ -20,6 +20,9 @@ #include #include +/* base includes */ +#include + namespace Kernel { /** @@ -32,6 +35,11 @@ namespace Kernel */ class Processor_domain_update; + /** + * Execution context that is scheduled on CPU idle + */ + class Cpu_idle; + /** * Multiplexes a single processor to multiple processor clients */ @@ -41,6 +49,16 @@ namespace Kernel * A multiplexable common instruction processor */ class Processor; + + /** + * Provides a processor object for every available processor + */ + class Processor_pool; + + /** + * Return Processor_pool singleton + */ + Processor_pool * processor_pool(); } class Kernel::Processor_domain_update @@ -184,11 +202,50 @@ class Kernel::Processor_client : public Processor_scheduler::Item unsigned tics_consumed() { return _tics_consumed; } }; +class Kernel::Cpu_idle : public Cpu::User_context, public Processor_client +{ + 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() { while (1) { Cpu::wait_for_interrupt(); } } + + public: + + /** + * Construct idle context for CPU 'cpu' + */ + Cpu_idle(Processor * const cpu); + + /** + * Handle exception that occured during execution on CPU 'cpu' + */ + void 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); } + } + + /** + * Continue execution on CPU 'cpu_id' + */ + void proceed(unsigned const cpu_id); +}; + class Kernel::Processor : public Cpu { private: unsigned const _id; + Cpu_idle _idle; Processor_scheduler _scheduler; bool _ip_interrupt_pending; Timer * const _timer; @@ -212,15 +269,13 @@ class Kernel::Processor : public Cpu /** * Constructor * - * \param id kernel name of the processor object - * \param idle_client client that gets scheduled on idle - * \param timer timer that is used for scheduling the processor + * \param id kernel name of the processor + * \param timer scheduling timer */ - Processor(unsigned const id, Processor_client * const idle_client, - Timer * const timer) + Processor(unsigned const id, Timer * const timer) : - _id(id), _scheduler(idle_client), _ip_interrupt_pending(false), - _timer(timer) + _id(id), _idle(this), _scheduler(&_idle), + _ip_interrupt_pending(false), _timer(timer) { } /** @@ -273,4 +328,39 @@ class Kernel::Processor : public Cpu Processor_scheduler * scheduler() { return &_scheduler; } }; +class Kernel::Processor_pool +{ + private: + + Timer _timer; + char _processors[PROCESSORS][sizeof(Processor)]; + + public: + + /** + * Constructor + */ + Processor_pool() + { + for (unsigned id = 0; id < PROCESSORS; id++) { + new (_processors[id]) Processor(id, &_timer); } + } + + /** + * Return the kernel object of processor 'id' + */ + Processor * processor(unsigned const id) const + { + assert(id < PROCESSORS); + char * const p = const_cast(_processors[id]); + return reinterpret_cast(p); + } + + /** + * Return the object of the primary processor + */ + Processor * primary_processor() const { + return processor(Processor::primary_id()); } +}; + #endif /* _KERNEL__PROCESSOR_H_ */ diff --git a/repos/base-hw/src/core/include/kernel/processor_pool.h b/repos/base-hw/src/core/include/kernel/processor_pool.h deleted file mode 100644 index 4eef15379..000000000 --- a/repos/base-hw/src/core/include/kernel/processor_pool.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * \brief Provide a processor object for every available processor - * \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. - */ - -#ifndef _KERNEL__PROCESSOR_POOL_H_ -#define _KERNEL__PROCESSOR_POOL_H_ - -/* base includes */ -#include - -/* core includes */ -#include -#include - -namespace Kernel -{ - /** - * Thread that consumes processor time if no other thread is available - */ - class Idle_thread; - - /** - * Provides a processor object for every available processor - */ - class Processor_pool; - - /** - * Return Processor_pool singleton - */ - Processor_pool * processor_pool(); -} - -class Kernel::Idle_thread : public Thread -{ - private: - - enum { - STACK_SIZE = sizeof(addr_t) * 32, - STACK_ALIGNM = Cpu::data_access_align, - }; - - char _stack[STACK_SIZE] __attribute__((aligned(STACK_ALIGNM))); - - /** - * Main function of all idle threads - */ - static void _main() { while (1) { Cpu::wait_for_interrupt(); } } - - public: - - /** - * Constructor - * - * \param processor kernel object of targeted processor - */ - Idle_thread(Processor * const processor) - : - Thread(Priority::MAX, "idle") - { - ip = (addr_t)&_main; - sp = (addr_t)&_stack[STACK_SIZE]; - init(processor, core_pd(), 0, 0); - } -}; - -class Kernel::Processor_pool -{ - private: - - Timer _timer; - char _processors[PROCESSORS][sizeof(Processor)]; - char _idle_threads[PROCESSORS][sizeof(Idle_thread)]; - - /** - * Return idle thread of a specific processor - * - * \param processor_id kernel name of the targeted processor - */ - Idle_thread * _idle_thread(unsigned const processor_id) const - { - char * const p = const_cast(_idle_threads[processor_id]); - return reinterpret_cast(p); - } - - public: - - /** - * Constructor - */ - Processor_pool() - { - for (unsigned i = 0; i < PROCESSORS; i++) { - new (_idle_threads[i]) Idle_thread(processor(i)); - new (_processors[i]) Processor(i, _idle_thread(i), &_timer); - } - } - - /** - * Return the object of a specific processor - * - * \param id kernel name of the targeted processor - */ - Processor * processor(unsigned const id) const - { - assert(id < PROCESSORS); - char * const p = const_cast(_processors[id]); - return reinterpret_cast(p); - } - - /** - * Return the object of the primary processor - */ - Processor * primary_processor() const - { - return processor(Processor::primary_id()); - } -}; - -#endif /* _KERNEL__PROCESSOR_POOL_H_ */ diff --git a/repos/base-hw/src/core/include/kernel/vm.h b/repos/base-hw/src/core/include/kernel/vm.h index 76cc9dcd4..e34e021de 100644 --- a/repos/base-hw/src/core/include/kernel/vm.h +++ b/repos/base-hw/src/core/include/kernel/vm.h @@ -20,7 +20,6 @@ /* core includes */ #include #include -#include #include namespace Kernel diff --git a/repos/base-hw/src/core/kernel/processor.cc b/repos/base-hw/src/core/kernel/processor.cc index 72afa12a0..be83bc57f 100644 --- a/repos/base-hw/src/core/kernel/processor.cc +++ b/repos/base-hw/src/core/kernel/processor.cc @@ -14,12 +14,14 @@ /* core includes */ #include -#include +#include #include #include #include #include +using namespace Kernel; + namespace Kernel { /** @@ -29,6 +31,9 @@ namespace Kernel Pic * pic(); Timer * timer(); + + Processor_pool * processor_pool() { + return unmanaged_singleton(); } } class Kernel::Processor_domain_update_list @@ -53,11 +58,8 @@ namespace Kernel /** * Return singleton of the processor domain-udpate list */ - Processor_domain_update_list * processor_domain_update_list() - { - static Processor_domain_update_list s; - return &s; - } + Processor_domain_update_list * processor_domain_update_list() { + return unmanaged_singleton(); } } @@ -65,7 +67,7 @@ namespace Kernel ** Processor_client ** **********************/ -void Kernel::Processor_client::_interrupt(unsigned const processor_id) +void Processor_client::_interrupt(unsigned const processor_id) { /* determine handling for specific interrupt */ unsigned irq_id; @@ -94,14 +96,29 @@ void Kernel::Processor_client::_interrupt(unsigned const processor_id) } -void Kernel::Processor_client::_schedule() { _processor->schedule(this); } +void Processor_client::_schedule() { _processor->schedule(this); } + + +/******************** + ** Processor_idle ** + ********************/ + +Cpu_idle::Cpu_idle(Processor * const cpu) : Processor_client(cpu, 0) +{ + cpu_exception = RESET; + ip = (addr_t)&_main; + sp = (addr_t)&_stack[stack_size]; + init_thread((addr_t)core_pd()->translation_table(), core_pd()->id()); +} + +void Cpu_idle::proceed(unsigned const cpu) { mtc()->continue_user(this, cpu); } /*************** ** Processor ** ***************/ -void Kernel::Processor::schedule(Processor_client * const client) +void Processor::schedule(Processor_client * const client) { if (_id != executing_id()) { @@ -127,7 +144,7 @@ void Kernel::Processor::schedule(Processor_client * const client) } -void Kernel::Processor::trigger_ip_interrupt() +void Processor::trigger_ip_interrupt() { if (!_ip_interrupt_pending) { pic()->trigger_ip_interrupt(_id); @@ -136,14 +153,14 @@ void Kernel::Processor::trigger_ip_interrupt() } -void Kernel::Processor_client::_unschedule() +void Processor_client::_unschedule() { assert(_processor->id() == Processor::executing_id()); _processor->scheduler()->remove(this); } -void Kernel::Processor_client::_yield() +void Processor_client::_yield() { assert(_processor->id() == Processor::executing_id()); _processor->scheduler()->yield_occupation(); @@ -154,7 +171,7 @@ void Kernel::Processor_client::_yield() ** Processor_domain_update ** *****************************/ -void Kernel::Processor_domain_update::_perform_locally() +void Processor_domain_update::_perform_locally() { /* perform domain update locally and get pending bit */ unsigned const processor_id = Processor::executing_id(); @@ -173,7 +190,7 @@ void Kernel::Processor_domain_update::_perform_locally() } -bool Kernel::Processor_domain_update::_perform(unsigned const domain_id) +bool Processor_domain_update::_perform(unsigned const domain_id) { /* perform locally and leave it at that if in uniprocessor mode */ _domain_id = domain_id; diff --git a/repos/base-hw/src/core/kernel/processor_pool.cc b/repos/base-hw/src/core/kernel/processor_pool.cc deleted file mode 100644 index 987dbab0a..000000000 --- a/repos/base-hw/src/core/kernel/processor_pool.cc +++ /dev/null @@ -1,21 +0,0 @@ -/* - * \brief Provide a processor object for every available processor - * \author Martin Stein - * \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 - -using namespace Kernel; - - -Processor_pool * Kernel::processor_pool() { - return unmanaged_singleton(); }