hw: restrict processor broadcast to TLB flushing
Removes the generic processor broadcast function call. By now, that call was used for cross processor TLB maintance operations only. When core/kernel gets its memory mapped on demand, and unmapped again, the previous cross processor flush routine doesn't work anymore, because of a hen-egg problem. The previous cross processor broadcast is realized using a thread constructed by core running on top of each processor core. When constructing threads in core, a dataspace for its thread context is constructed. Each constructed RAM dataspace gets attached, zeroed out, and detached again. The detach routine requires a TLB flush operation executed on each processor core. Instead of executing a thread on each processor core, now a thread waiting for a global TLB flush is removed from the scheduler queue, and gets attached to a TLB flush queue of each processor. The processor local queue gets checked whenever the kernel is entered. The last processor, which executed the TLB flush, re-attaches the blocked thread to its scheduler queue again. To ease uo the above described mechanism, a platform thread is now directly associated with a platform pd object, instead of just associate it with the kernel pd's id. Ref #723
This commit is contained in:
parent
b888a26d57
commit
34b18e9da2
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Platform specific part of a Genode protection domain
|
* \brief Platform specific part of a Genode protection domain
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-02-12
|
* \date 2012-02-12
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -45,14 +46,22 @@ namespace Genode
|
||||||
*/
|
*/
|
||||||
class Platform_pd : public Address_space
|
class Platform_pd : public Address_space
|
||||||
{
|
{
|
||||||
unsigned _id;
|
protected:
|
||||||
Native_capability _parent;
|
|
||||||
Native_thread_id _main_thread;
|
unsigned _id;
|
||||||
char const * const _label;
|
Native_capability _parent;
|
||||||
Tlb * _tlb;
|
Native_thread_id _main_thread;
|
||||||
|
char const * const _label;
|
||||||
|
Tlb * _tlb;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for core pd
|
||||||
|
*/
|
||||||
|
Platform_pd(Tlb * tlb)
|
||||||
|
: _main_thread(0), _label("core"), _tlb(tlb) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
|
@ -95,9 +104,9 @@ namespace Genode
|
||||||
{
|
{
|
||||||
/* annotate that we've got a main thread from now on */
|
/* annotate that we've got a main thread from now on */
|
||||||
_main_thread = t->id();
|
_main_thread = t->id();
|
||||||
return t->join_pd(_id, 1, Address_space::weak_ptr());
|
return t->join_pd(this, 1, Address_space::weak_ptr());
|
||||||
}
|
}
|
||||||
return t->join_pd(_id, 0, Address_space::weak_ptr());
|
return t->join_pd(this, 0, Address_space::weak_ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -118,6 +127,7 @@ namespace Genode
|
||||||
** Accessors **
|
** Accessors **
|
||||||
***************/
|
***************/
|
||||||
|
|
||||||
|
unsigned const id() { return _id; }
|
||||||
char const * const label() { return _label; }
|
char const * const label() { return _label; }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Userland interface for the management of kernel thread-objects
|
* \brief Userland interface for the management of kernel thread-objects
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-02-02
|
* \date 2012-02-02
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ namespace Genode {
|
||||||
enum { LABEL_MAX_LEN = 32 };
|
enum { LABEL_MAX_LEN = 32 };
|
||||||
|
|
||||||
size_t _stack_size;
|
size_t _stack_size;
|
||||||
unsigned _pd_id;
|
Platform_pd * _pd;
|
||||||
Weak_ptr<Address_space> _address_space;
|
Weak_ptr<Address_space> _address_space;
|
||||||
unsigned _id;
|
unsigned _id;
|
||||||
Rm_client * _rm_client;
|
Rm_client * _rm_client;
|
||||||
|
@ -81,11 +82,9 @@ namespace Genode {
|
||||||
* Constructor for core threads
|
* Constructor for core threads
|
||||||
*
|
*
|
||||||
* \param stack_size initial size of the stack
|
* \param stack_size initial size of the stack
|
||||||
* \param pd_id kernel name of targeted protection domain
|
|
||||||
* \param label debugging label
|
* \param label debugging label
|
||||||
*/
|
*/
|
||||||
Platform_thread(size_t const stack_size,
|
Platform_thread(size_t const stack_size, const char * const label);
|
||||||
unsigned const pd_id, const char * const label);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for threads outside of core
|
* Constructor for threads outside of core
|
||||||
|
@ -105,14 +104,14 @@ namespace Genode {
|
||||||
/**
|
/**
|
||||||
* Join a protection domain
|
* Join a protection domain
|
||||||
*
|
*
|
||||||
* \param pd_id kernel name of targeted protection domain
|
* \param pd platform pd object pointer
|
||||||
* \param main_thread wether thread is the first in protection domain
|
* \param main_thread wether thread is the first in protection domain
|
||||||
* \param address_space corresponding Genode address space
|
* \param address_space corresponding Genode address space
|
||||||
*
|
*
|
||||||
* \retval 0 succeeded
|
* \retval 0 succeeded
|
||||||
* \retval -1 failed
|
* \retval -1 failed
|
||||||
*/
|
*/
|
||||||
int join_pd(unsigned const pd_id, bool const main_thread,
|
int join_pd(Platform_pd * const pd, bool const main_thread,
|
||||||
Weak_ptr<Address_space> address_space);
|
Weak_ptr<Address_space> address_space);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -179,7 +178,7 @@ namespace Genode {
|
||||||
|
|
||||||
Pager_object * pager();
|
Pager_object * pager();
|
||||||
|
|
||||||
unsigned pd_id() const { return _pd_id; }
|
Platform_pd * pd() const { return _pd; }
|
||||||
|
|
||||||
Native_thread_id id() const { return _id; }
|
Native_thread_id id() const { return _id; }
|
||||||
|
|
||||||
|
|
|
@ -1,207 +0,0 @@
|
||||||
/*
|
|
||||||
* \brief Utility to execute a function on all available processors
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2014-03-07
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _PROCESSOR_BROADCAST_H_
|
|
||||||
#define _PROCESSOR_BROADCAST_H_
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <base/thread.h>
|
|
||||||
#include <base/signal.h>
|
|
||||||
|
|
||||||
namespace Genode {
|
|
||||||
|
|
||||||
enum { PROCESSOR_BROADCAST_RECEIVER_STACK_SIZE = 4 * 1024 };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Functionality that can be broadcasted on all available processors
|
|
||||||
*/
|
|
||||||
class Processor_broadcast_operation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper for the signalling between broadcast and receiver
|
|
||||||
*/
|
|
||||||
class Processor_broadcast_signal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processor local receiver of broadcasted functions
|
|
||||||
*/
|
|
||||||
class Processor_broadcast_receiver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes a function on all available processors
|
|
||||||
*/
|
|
||||||
class Processor_broadcast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return broadcast singleton
|
|
||||||
*/
|
|
||||||
Processor_broadcast * processor_broadcast();
|
|
||||||
}
|
|
||||||
|
|
||||||
class Genode::Processor_broadcast_operation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
typedef void (*Entry)(void * const);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Entry const _entry;
|
|
||||||
void * const _data;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* \param entry entry to the operation code
|
|
||||||
* \param data pointer to operation specific input/output data
|
|
||||||
*/
|
|
||||||
Processor_broadcast_operation(Entry const entry, void * const data)
|
|
||||||
:
|
|
||||||
_entry(entry), _data(data)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute operation processor-locally
|
|
||||||
*/
|
|
||||||
void execute() const { _entry(_data); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Genode::Processor_broadcast_signal
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Signal_context _context;
|
|
||||||
Signal_receiver _receiver;
|
|
||||||
Signal_transmitter _transmitter;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Processor_broadcast_signal()
|
|
||||||
:
|
|
||||||
_transmitter(_receiver.manage(&_context))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submit the signal
|
|
||||||
*/
|
|
||||||
void submit() { _transmitter.submit(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for signal submission
|
|
||||||
*/
|
|
||||||
void await() { _receiver.wait_for_signal(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Genode::Processor_broadcast_receiver
|
|
||||||
:
|
|
||||||
public Thread<PROCESSOR_BROADCAST_RECEIVER_STACK_SIZE>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
typedef Processor_broadcast_operation Operation;
|
|
||||||
typedef Processor_broadcast_signal Signal;
|
|
||||||
|
|
||||||
Operation const * _operation;
|
|
||||||
Signal _start;
|
|
||||||
Signal _end;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Processor_broadcast_receiver() : Thread("processor_broadcast") { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start receiver on a specific processor
|
|
||||||
*
|
|
||||||
* \param processor_id kernel name of targeted processor
|
|
||||||
*/
|
|
||||||
void init(unsigned const processor_id)
|
|
||||||
{
|
|
||||||
Thread::utcb()->core_start_info()->init(processor_id);
|
|
||||||
Thread::start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start remote execution of an operation
|
|
||||||
*
|
|
||||||
* \param operation desired operation
|
|
||||||
*/
|
|
||||||
void start_executing(Operation const * const operation)
|
|
||||||
{
|
|
||||||
_operation = operation;
|
|
||||||
_start.submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait until the remote execution of the current operation is done
|
|
||||||
*/
|
|
||||||
void end_executing() { _end.await(); }
|
|
||||||
|
|
||||||
|
|
||||||
/*****************
|
|
||||||
** Thread_base **
|
|
||||||
*****************/
|
|
||||||
|
|
||||||
void entry()
|
|
||||||
{
|
|
||||||
while (1) {
|
|
||||||
_start.await();
|
|
||||||
_operation->execute();
|
|
||||||
_end.submit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class Genode::Processor_broadcast
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
typedef Processor_broadcast_operation Operation;
|
|
||||||
typedef Processor_broadcast_receiver Receiver;
|
|
||||||
|
|
||||||
Receiver _receiver[PROCESSORS];
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Processor_broadcast()
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < PROCESSORS; i++) { _receiver[i].init(i); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute operation on all available processors
|
|
||||||
*
|
|
||||||
* \param operation desired operation
|
|
||||||
*/
|
|
||||||
void execute(Operation const * const operation)
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < PROCESSORS; i++) {
|
|
||||||
_receiver[i].start_executing(operation);
|
|
||||||
}
|
|
||||||
for (unsigned i = 0; i < PROCESSORS; i++) {
|
|
||||||
_receiver[i].end_executing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _PROCESSOR_BROADCAST_H_ */
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Singlethreaded minimalistic kernel
|
* \brief Singlethreaded minimalistic kernel
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2011-10-20
|
* \date 2011-10-20
|
||||||
*
|
*
|
||||||
* This kernel is the only code except the mode transition PIC, that runs in
|
* This kernel is the only code except the mode transition PIC, that runs in
|
||||||
|
@ -92,34 +93,28 @@ namespace Kernel
|
||||||
/**
|
/**
|
||||||
* Static kernel PD that describes core
|
* Static kernel PD that describes core
|
||||||
*/
|
*/
|
||||||
Pd * core()
|
Pd * core_pd()
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Core protection-domain
|
* Core protection-domain
|
||||||
*/
|
*/
|
||||||
class Core_pd : public Pd
|
struct Core_pd : public Platform_pd, public Pd
|
||||||
{
|
{
|
||||||
public:
|
/**
|
||||||
|
* Constructor
|
||||||
/**
|
*/
|
||||||
* Constructor
|
Core_pd(Tlb * const tlb)
|
||||||
*/
|
: Platform_pd(tlb),
|
||||||
Core_pd(Tlb * const tlb, Platform_pd * const platform_pd)
|
Pd(tlb, this)
|
||||||
:
|
{
|
||||||
Pd(tlb, platform_pd)
|
Platform_pd::_id = Pd::id();
|
||||||
{ }
|
}
|
||||||
};
|
};
|
||||||
constexpr int tlb_align = 1 << Core_tlb::ALIGNM_LOG2;
|
constexpr int tlb_align = 1 << Core_tlb::ALIGNM_LOG2;
|
||||||
Core_tlb * core_tlb = unmanaged_singleton<Core_tlb, tlb_align>();
|
Core_tlb * core_tlb = unmanaged_singleton<Core_tlb, tlb_align>();
|
||||||
Core_pd * core_pd = unmanaged_singleton<Core_pd>(core_tlb, nullptr);
|
return unmanaged_singleton<Core_pd>(core_tlb);
|
||||||
return core_pd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get core attributes
|
|
||||||
*/
|
|
||||||
unsigned core_id() { return core()->id(); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return wether an interrupt is private to the kernel
|
* Return wether an interrupt is private to the kernel
|
||||||
*
|
*
|
||||||
|
@ -189,8 +184,8 @@ extern "C" void init_kernel_uniprocessor()
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
/* calculate in advance as needed later when data writes aren't allowed */
|
/* calculate in advance as needed later when data writes aren't allowed */
|
||||||
core_tlb_base = core()->tlb()->base();
|
core_tlb_base = core_pd()->tlb()->base();
|
||||||
core_pd_id = core_id();
|
core_pd_id = core_pd()->id();
|
||||||
|
|
||||||
/* initialize all processor objects */
|
/* initialize all processor objects */
|
||||||
processor_pool();
|
processor_pool();
|
||||||
|
@ -275,7 +270,7 @@ extern "C" void init_kernel_multiprocessor()
|
||||||
_main_thread_utcb->start_info()->init(t.id(), Genode::Native_capability());
|
_main_thread_utcb->start_info()->init(t.id(), Genode::Native_capability());
|
||||||
t.ip = (addr_t)CORE_MAIN;;
|
t.ip = (addr_t)CORE_MAIN;;
|
||||||
t.sp = (addr_t)s + STACK_SIZE;
|
t.sp = (addr_t)s + STACK_SIZE;
|
||||||
t.init(processor_pool()->processor(processor_id), core(), &utcb, 1);
|
t.init(processor_pool()->processor(processor_id), core_pd(), &utcb, 1);
|
||||||
|
|
||||||
/* initialize interrupt objects */
|
/* initialize interrupt objects */
|
||||||
static Genode::uint8_t _irqs[Pic::MAX_INTERRUPT_ID * sizeof(Irq)];
|
static Genode::uint8_t _irqs[Pic::MAX_INTERRUPT_ID * sizeof(Irq)];
|
||||||
|
@ -312,6 +307,9 @@ extern "C" void kernel()
|
||||||
Processor_client * const old_occupant = scheduler->occupant();
|
Processor_client * const old_occupant = scheduler->occupant();
|
||||||
old_occupant->exception(processor_id);
|
old_occupant->exception(processor_id);
|
||||||
|
|
||||||
|
/* check for TLB maintainance requirements */
|
||||||
|
processor->flush_tlb();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The processor local as well as remote exception-handling may have
|
* The processor local as well as remote exception-handling may have
|
||||||
* changed the scheduling of the local activities. Hence we must update the
|
* changed the scheduling of the local activities. Hence we must update the
|
||||||
|
@ -338,5 +336,5 @@ Kernel::Cpu_context::Cpu_context()
|
||||||
_init(STACK_SIZE);
|
_init(STACK_SIZE);
|
||||||
sp = (addr_t)kernel_stack;
|
sp = (addr_t)kernel_stack;
|
||||||
ip = (addr_t)kernel;
|
ip = (addr_t)kernel;
|
||||||
core()->admit(this);
|
core_pd()->admit(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Singlethreaded minimalistic kernel
|
* \brief Singlethreaded minimalistic kernel
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2013-09-30
|
* \date 2013-09-30
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -14,6 +15,8 @@
|
||||||
#ifndef _KERNEL__KERNEL_H_
|
#ifndef _KERNEL__KERNEL_H_
|
||||||
#define _KERNEL__KERNEL_H_
|
#define _KERNEL__KERNEL_H_
|
||||||
|
|
||||||
namespace Kernel { unsigned core_id(); }
|
#include <kernel/pd.h>
|
||||||
|
|
||||||
|
namespace Kernel { Pd * core_pd(); }
|
||||||
|
|
||||||
#endif /* _KERNEL__KERNEL_H_ */
|
#endif /* _KERNEL__KERNEL_H_ */
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief A multiplexable common instruction processor
|
* \brief A multiplexable common instruction processor
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2014-01-14
|
* \date 2014-01-14
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <kernel/processor.h>
|
#include <kernel/processor.h>
|
||||||
|
#include <kernel/thread.h>
|
||||||
#include <kernel/irq.h>
|
#include <kernel/irq.h>
|
||||||
#include <pic.h>
|
#include <pic.h>
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
|
@ -59,6 +61,25 @@ void Kernel::Processor_client::_interrupt(unsigned const processor_id)
|
||||||
void Kernel::Processor_client::_schedule() { __processor->schedule(this); }
|
void Kernel::Processor_client::_schedule() { __processor->schedule(this); }
|
||||||
|
|
||||||
|
|
||||||
|
void Kernel::Processor_client::tlb_to_flush(unsigned pd_id)
|
||||||
|
{
|
||||||
|
/* initialize pd and reference counter, and remove client from scheduler */
|
||||||
|
_flush_tlb_pd_id = pd_id;
|
||||||
|
_flush_tlb_ref_cnt = PROCESSORS;
|
||||||
|
_unschedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Kernel::Processor_client::flush_tlb_by_id()
|
||||||
|
{
|
||||||
|
Processor::flush_tlb_by_pid(_flush_tlb_pd_id);
|
||||||
|
|
||||||
|
/* if reference counter reaches zero, add client to scheduler again */
|
||||||
|
if (--_flush_tlb_ref_cnt == 0)
|
||||||
|
_schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Kernel::Processor::schedule(Processor_client * const client)
|
void Kernel::Processor::schedule(Processor_client * const client)
|
||||||
{
|
{
|
||||||
if (_id != executing_id()) {
|
if (_id != executing_id()) {
|
||||||
|
@ -99,3 +120,28 @@ void Kernel::Processor_client::_yield()
|
||||||
assert(__processor->id() == Processor::executing_id());
|
assert(__processor->id() == Processor::executing_id());
|
||||||
__processor->scheduler()->yield_occupation();
|
__processor->scheduler()->yield_occupation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Kernel::Processor::flush_tlb(Processor_client * const client)
|
||||||
|
{
|
||||||
|
/* find the last working item in the TLB work queue */
|
||||||
|
Genode::List_element<Processor_client> * last = _ipi_scheduler.first();
|
||||||
|
while (last && last->next()) last = last->next();
|
||||||
|
|
||||||
|
/* insert new work item at the end of the work list */
|
||||||
|
_ipi_scheduler.insert(&client->_flush_tlb_li, last);
|
||||||
|
|
||||||
|
/* enforce kernel entry of the corresponding processor */
|
||||||
|
pic()->trigger_ip_interrupt(_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Kernel::Processor::flush_tlb()
|
||||||
|
{
|
||||||
|
/* iterate through the list of TLB work items, and proceed them */
|
||||||
|
for (Genode::List_element<Processor_client> * cli = _ipi_scheduler.first(); cli;
|
||||||
|
cli = _ipi_scheduler.first()) {
|
||||||
|
cli->object()->flush_tlb_by_id();
|
||||||
|
_ipi_scheduler.remove(cli);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief A multiplexable common instruction processor
|
* \brief A multiplexable common instruction processor
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2014-01-14
|
* \date 2014-01-14
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -18,6 +19,8 @@
|
||||||
#include <processor_driver.h>
|
#include <processor_driver.h>
|
||||||
#include <kernel/scheduler.h>
|
#include <kernel/scheduler.h>
|
||||||
|
|
||||||
|
#include <util/list.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -44,6 +47,14 @@ class Kernel::Processor_client : public Processor_scheduler::Item
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
using List_item = Genode::List_element<Processor_client>;
|
||||||
|
|
||||||
|
List_item _flush_tlb_li; /* TLB maintainance work list item */
|
||||||
|
unsigned _flush_tlb_pd_id; /* id of pd that TLB entries are flushed */
|
||||||
|
unsigned _flush_tlb_ref_cnt; /* reference counter */
|
||||||
|
|
||||||
|
friend class Processor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle an interrupt exception that occured during execution
|
* Handle an interrupt exception that occured during execution
|
||||||
*
|
*
|
||||||
|
@ -92,6 +103,18 @@ class Kernel::Processor_client : public Processor_scheduler::Item
|
||||||
*/
|
*/
|
||||||
virtual void proceed(unsigned const processor_id) = 0;
|
virtual void proceed(unsigned const processor_id) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the pd id, which TLB entries should be flushed
|
||||||
|
*
|
||||||
|
* \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
|
* Constructor
|
||||||
*
|
*
|
||||||
|
@ -101,7 +124,8 @@ class Kernel::Processor_client : public Processor_scheduler::Item
|
||||||
Processor_client(Processor * const processor, Priority const priority)
|
Processor_client(Processor * const processor, Priority const priority)
|
||||||
:
|
:
|
||||||
Processor_scheduler::Item(priority),
|
Processor_scheduler::Item(priority),
|
||||||
__processor(processor)
|
__processor(processor),
|
||||||
|
_flush_tlb_li(this)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -118,8 +142,11 @@ class Kernel::Processor : public Processor_driver
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
using Ipi_scheduler = Genode::List<Genode::List_element<Processor_client> >;
|
||||||
|
|
||||||
unsigned const _id;
|
unsigned const _id;
|
||||||
Processor_scheduler _scheduler;
|
Processor_scheduler _scheduler;
|
||||||
|
Ipi_scheduler _ipi_scheduler;
|
||||||
bool _ip_interrupt_pending;
|
bool _ip_interrupt_pending;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -157,6 +184,19 @@ class Kernel::Processor : public Processor_driver
|
||||||
void schedule(Processor_client * const client);
|
void schedule(Processor_client * const client);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add processor client to the TLB maintainance queue of the processor
|
||||||
|
*
|
||||||
|
* \param client targeted client
|
||||||
|
*/
|
||||||
|
void flush_tlb(Processor_client * const client);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform outstanding TLB maintainance work
|
||||||
|
*/
|
||||||
|
void flush_tlb();
|
||||||
|
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
** Accessors **
|
** Accessors **
|
||||||
***************/
|
***************/
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Provide a processor object for every available processor
|
* \brief Provide a processor object for every available processor
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2014-01-14
|
* \date 2014-01-14
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -18,15 +19,11 @@
|
||||||
#include <unmanaged_singleton.h>
|
#include <unmanaged_singleton.h>
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
|
#include <kernel/kernel.h>
|
||||||
#include <kernel/thread.h>
|
#include <kernel/thread.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Return kernel name of core domain
|
|
||||||
*/
|
|
||||||
Pd * core();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thread that consumes processor time if no other thread is available
|
* Thread that consumes processor time if no other thread is available
|
||||||
*/
|
*/
|
||||||
|
@ -75,7 +72,7 @@ class Kernel::Idle_thread : public Thread
|
||||||
{
|
{
|
||||||
ip = (addr_t)&_main;
|
ip = (addr_t)&_main;
|
||||||
sp = (addr_t)&_stack[STACK_SIZE];
|
sp = (addr_t)&_stack[STACK_SIZE];
|
||||||
init(processor, core(), 0, 0);
|
init(processor, core_pd(), 0, 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Kernel backend for execution contexts in userland
|
* \brief Kernel backend for execution contexts in userland
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2013-09-15
|
* \date 2013-09-15
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ typedef Genode::Thread_state Thread_state;
|
||||||
|
|
||||||
unsigned Thread::pd_id() const { return _pd ? _pd->id() : 0; }
|
unsigned Thread::pd_id() const { return _pd ? _pd->id() : 0; }
|
||||||
|
|
||||||
bool Thread::_core() const { return pd_id() == core_id(); }
|
bool Thread::_core() const { return pd_id() == core_pd()->id(); }
|
||||||
|
|
||||||
void Thread::_signal_context_kill_pending()
|
void Thread::_signal_context_kill_pending()
|
||||||
{
|
{
|
||||||
|
@ -536,8 +537,11 @@ void Thread::_call_access_thread_regs()
|
||||||
|
|
||||||
void Thread::_call_update_pd()
|
void Thread::_call_update_pd()
|
||||||
{
|
{
|
||||||
/* update hardware caches */
|
tlb_to_flush(user_arg_1());
|
||||||
Processor::flush_tlb_by_pid(user_arg_1());
|
|
||||||
|
/* inform other processors */
|
||||||
|
for (unsigned i = 0; i < PROCESSORS; i++)
|
||||||
|
Kernel::processor_pool()->processor(i)->flush_tlb(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Thread facility
|
* \brief Thread facility
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-02-12
|
* \date 2012-02-12
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -13,12 +14,14 @@
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <platform_thread.h>
|
#include <platform_thread.h>
|
||||||
|
#include <platform_pd.h>
|
||||||
#include <core_env.h>
|
#include <core_env.h>
|
||||||
#include <rm_session_component.h>
|
#include <rm_session_component.h>
|
||||||
|
|
||||||
using namespace Genode;
|
/* kernel includes */
|
||||||
|
#include <kernel/kernel.h>
|
||||||
|
|
||||||
namespace Kernel { unsigned core_id(); }
|
using namespace Genode;
|
||||||
|
|
||||||
void Platform_thread::_init() { }
|
void Platform_thread::_init() { }
|
||||||
|
|
||||||
|
@ -30,7 +33,7 @@ bool Platform_thread::_attaches_utcb_by_itself()
|
||||||
* virtual context area by itself, as it is done for other threads
|
* virtual context area by itself, as it is done for other threads
|
||||||
* through a sub RM-session.
|
* through a sub RM-session.
|
||||||
*/
|
*/
|
||||||
return _pd_id == Kernel::core_id() || !_main_thread;
|
return _pd == Kernel::core_pd()->platform_pd() || !_main_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +55,7 @@ Platform_thread::~Platform_thread()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* free UTCB */
|
/* free UTCB */
|
||||||
if (_pd_id == Kernel::core_id()) {
|
if (_pd == Kernel::core_pd()->platform_pd()) {
|
||||||
Range_allocator * const ram = platform()->ram_alloc();
|
Range_allocator * const ram = platform()->ram_alloc();
|
||||||
ram->free(_utcb_phys, sizeof(Native_utcb));
|
ram->free(_utcb_phys, sizeof(Native_utcb));
|
||||||
} else {
|
} else {
|
||||||
|
@ -76,11 +79,10 @@ Platform_thread::~Platform_thread()
|
||||||
|
|
||||||
|
|
||||||
Platform_thread::Platform_thread(size_t const stack_size,
|
Platform_thread::Platform_thread(size_t const stack_size,
|
||||||
unsigned const pd_id,
|
|
||||||
const char * const label)
|
const char * const label)
|
||||||
:
|
:
|
||||||
_stack_size(stack_size),
|
_stack_size(stack_size),
|
||||||
_pd_id(pd_id),
|
_pd(Kernel::core_pd()->platform_pd()),
|
||||||
_rm_client(0),
|
_rm_client(0),
|
||||||
_utcb_virt(0),
|
_utcb_virt(0),
|
||||||
_main_thread(0)
|
_main_thread(0)
|
||||||
|
@ -114,7 +116,7 @@ Platform_thread::Platform_thread(const char * const label,
|
||||||
addr_t const utcb)
|
addr_t const utcb)
|
||||||
:
|
:
|
||||||
_stack_size(0),
|
_stack_size(0),
|
||||||
_pd_id(0),
|
_pd(nullptr),
|
||||||
_rm_client(0),
|
_rm_client(0),
|
||||||
_utcb_virt((Native_utcb *)utcb),
|
_utcb_virt((Native_utcb *)utcb),
|
||||||
_main_thread(0)
|
_main_thread(0)
|
||||||
|
@ -147,16 +149,16 @@ Platform_thread::Platform_thread(const char * const label,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Platform_thread::join_pd(unsigned const pd_id, bool const main_thread,
|
int Platform_thread::join_pd(Platform_pd * pd, bool const main_thread,
|
||||||
Weak_ptr<Address_space> address_space)
|
Weak_ptr<Address_space> address_space)
|
||||||
{
|
{
|
||||||
/* check if thread is already in another protection domain */
|
/* check if thread is already in another protection domain */
|
||||||
if (_pd_id && _pd_id != pd_id) {
|
if (_pd && _pd != pd) {
|
||||||
PERR("thread already in another protection domain");
|
PERR("thread already in another protection domain");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* join protection domain */
|
/* join protection domain */
|
||||||
_pd_id = pd_id;
|
_pd = pd;
|
||||||
_main_thread = main_thread;
|
_main_thread = main_thread;
|
||||||
_address_space = address_space;
|
_address_space = address_space;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -206,7 +208,7 @@ int Platform_thread::start(void * const ip, void * const sp)
|
||||||
|
|
||||||
/* start executing new thread */
|
/* start executing new thread */
|
||||||
_utcb_phys->start_info()->init(_id, _utcb);
|
_utcb_phys->start_info()->init(_id, _utcb);
|
||||||
_tlb = Kernel::start_thread(_id, processor_id, _pd_id, _utcb_phys);
|
_tlb = Kernel::start_thread(_id, processor_id, _pd->id(), _utcb_phys);
|
||||||
if (!_tlb) {
|
if (!_tlb) {
|
||||||
PERR("failed to start thread");
|
PERR("failed to start thread");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* \brief Utility to execute a function on all available processors
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2014-03-07
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 <processor_broadcast.h>
|
|
||||||
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
|
|
||||||
Processor_broadcast * Genode::processor_broadcast()
|
|
||||||
{
|
|
||||||
static Processor_broadcast s;
|
|
||||||
return &s;
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief RM- and pager implementations specific for base-hw and core
|
* \brief RM- and pager implementations specific for base-hw and core
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-02-12
|
* \date 2012-02-12
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -19,7 +20,6 @@
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
#include <platform_thread.h>
|
#include <platform_thread.h>
|
||||||
#include <processor_broadcast.h>
|
|
||||||
#include <tlb.h>
|
#include <tlb.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
@ -58,9 +58,7 @@ void Rm_client::unmap(addr_t, addr_t virt_base, size_t size)
|
||||||
tlb->remove_region(virt_base, size);
|
tlb->remove_region(virt_base, size);
|
||||||
|
|
||||||
/* update translation caches of all processors */
|
/* update translation caches of all processors */
|
||||||
Update_pd_data data { pt->pd_id() };
|
Kernel::update_pd(pt->pd()->id());
|
||||||
Processor_broadcast_operation const operation(update_pd, &data);
|
|
||||||
processor_broadcast()->execute(&operation);
|
|
||||||
|
|
||||||
/* try to get back released memory from the translation table */
|
/* try to get back released memory from the translation table */
|
||||||
regain_ram_from_tlb(tlb);
|
regain_ram_from_tlb(tlb);
|
||||||
|
|
|
@ -54,7 +54,6 @@ SRC_CC += console.cc \
|
||||||
kernel/irq.cc \
|
kernel/irq.cc \
|
||||||
kernel/processor.cc \
|
kernel/processor.cc \
|
||||||
kernel/processor_pool.cc \
|
kernel/processor_pool.cc \
|
||||||
processor_broadcast.cc \
|
|
||||||
rm_session_support.cc \
|
rm_session_support.cc \
|
||||||
trustzone.cc \
|
trustzone.cc \
|
||||||
pager.cc \
|
pager.cc \
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <platform_thread.h>
|
#include <platform_thread.h>
|
||||||
|
#include <kernel/kernel.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ void Thread_base::_thread_start()
|
||||||
Thread_base::Thread_base(const char * const label, size_t const stack_size, Type)
|
Thread_base::Thread_base(const char * const label, size_t const stack_size, Type)
|
||||||
{
|
{
|
||||||
_tid.platform_thread = new (platform()->core_mem_alloc())
|
_tid.platform_thread = new (platform()->core_mem_alloc())
|
||||||
Platform_thread(stack_size, Kernel::core_id(), label);
|
Platform_thread(stack_size, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue