/* * \brief A multiplexable common instruction 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_H_ #define _KERNEL__PROCESSOR_H_ /* core includes */ #include #include #include namespace Kernel { /** * A single user of a multiplexable processor */ class Processor_client; /** * Multiplexes a single processor to multiple processor clients */ typedef Scheduler Processor_scheduler; /** * A multiplexable common instruction processor */ class Processor; } class Kernel::Processor_client : public Processor_scheduler::Item { private: Processor * __processor; protected: using List_item = Genode::List_element; List_item _flush_tlb_li; /* TLB maintainance work list item */ unsigned _flush_tlb_pd_id; /* id of pd that TLB entries are flushed */ bool _flush_tlb_ref_cnt[PROCESSORS]; /* reference counters */ /** * Handle an interrupt exception that occured during execution * * \param processor_id kernel name of targeted processor */ void _interrupt(unsigned const processor_id); /** * Insert context into the processor scheduling */ void _schedule(); /** * Remove context from the processor scheduling */ void _unschedule(); /** * Yield currently scheduled processor share of the context */ void _yield(); /*************** ** Accessors ** ***************/ void _processor(Processor * const processor) { __processor = processor; } public: /** * Handle an exception that occured during execution * * \param processor_id kernel name of targeted processor */ virtual void exception(unsigned const processor_id) = 0; /** * Continue execution * * \param processor_id kernel name of targeted processor */ virtual void proceed(unsigned const processor_id) = 0; /** * Enqueues TLB maintainance work into queue of the processors * * \param pd_id protection domain kernel object's id */ void tlb_to_flush(unsigned pd_id); /** * Flush TLB entries requested by this client on the current processor */ void flush_tlb_by_id(); /** * Constructor * * \param processor kernel object of targeted processor * \param priority scheduling priority */ Processor_client(Processor * const processor, Priority const priority) : Processor_scheduler::Item(priority), __processor(processor), _flush_tlb_li(this) { } /** * Destructor */ ~Processor_client() { if (!_scheduled()) { return; } _unschedule(); } }; class Kernel::Processor : public Processor_driver { private: unsigned const _id; Processor_scheduler _scheduler; bool _ip_interrupt_pending; public: /** * Constructor * * \param id kernel name of the processor object * \param idle_client client that gets scheduled on idle */ Processor(unsigned const id, Processor_client * const idle_client) : _id(id), _scheduler(idle_client), _ip_interrupt_pending(false) { } /** * Perform outstanding TLB maintainance work */ void flush_tlb(); /** * Notice that the inter-processor interrupt isn't pending anymore */ void ip_interrupt() { /* * This interrupt solely denotes that another processor has * modified the scheduling plan of this processor and thus * a more prior user context than the current one might be * available. */ _ip_interrupt_pending = false; flush_tlb(); } /** * Add a processor client to the scheduling plan of the processor * * \param client targeted client */ void schedule(Processor_client * const client); /*************** ** Accessors ** ***************/ unsigned id() const { return _id; } Processor_scheduler * scheduler() { return &_scheduler; } }; #endif /* _KERNEL__PROCESSOR_H_ */