mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-23 17:17:38 +00:00
Assign threads to PD at its creation time
This patch replaces the former 'Pd_session::bind_thread' function by a PD-capability argument of the 'Cpu_session::create_thread' function, and removes the ancient thread-start protocol via 'Rm_session::add_client' and 'Cpu_session::set_pager'. Threads are now bound to PDs at their creation time and implicitly paged according to the address space of the PD. Note the API change: This patch changes the signature of the 'Child' and 'Process' constructors. There is a new 'address_space' argument, which represents the region map representing the child's address space. It is supplied separately to the PD session capability (which principally can be invoked to obtain the PD's address space) to allow the population of the address space without relying on an 'Pd_session::address_space' RPC call. Furthermore, a new (optional) env_pd argument allows the explicit overriding of the PD capability handed out to the child as part of its environment. It can be used to intercept the interaction of the child with its PD session at core. This is used by Noux. Issue #1938
This commit is contained in:
committed by
Christian Helmuth
parent
2bc8a0f76a
commit
b49e588c1c
@ -28,22 +28,21 @@ namespace Genode {
|
||||
explicit Cpu_session_client(Cpu_session_capability session)
|
||||
: Rpc_client<Nova_cpu_session>(static_cap_cast<Nova_cpu_session>(session)) { }
|
||||
|
||||
Thread_capability create_thread(size_t weight, Name const &name, addr_t utcb = 0) {
|
||||
return call<Rpc_create_thread>(weight, name, utcb); }
|
||||
Thread_capability
|
||||
create_thread(Capability<Pd_session> pd, size_t quota, Name const &name,
|
||||
Affinity::Location affinity, addr_t utcb = 0) override {
|
||||
return call<Rpc_create_thread>(pd, quota, name, affinity, utcb); }
|
||||
|
||||
Ram_dataspace_capability utcb(Thread_capability thread) {
|
||||
Ram_dataspace_capability utcb(Thread_capability thread) override {
|
||||
return call<Rpc_utcb>(thread); }
|
||||
|
||||
void kill_thread(Thread_capability thread) {
|
||||
void kill_thread(Thread_capability thread) override {
|
||||
call<Rpc_kill_thread>(thread); }
|
||||
|
||||
int set_pager(Thread_capability thread, Pager_capability pager) {
|
||||
return call<Rpc_set_pager>(thread, pager); }
|
||||
|
||||
int start(Thread_capability thread, addr_t ip, addr_t sp) {
|
||||
int start(Thread_capability thread, addr_t ip, addr_t sp) override {
|
||||
return call<Rpc_start>(thread, ip, sp); }
|
||||
|
||||
void pause(Thread_capability thread)
|
||||
void pause(Thread_capability thread) override
|
||||
{
|
||||
Native_capability block = call<Rpc_pause_sync>(thread);
|
||||
if (!block.valid())
|
||||
@ -52,22 +51,22 @@ namespace Genode {
|
||||
Nova::sm_ctrl(block.local_name(), Nova::SEMAPHORE_DOWN);
|
||||
}
|
||||
|
||||
void resume(Thread_capability thread) {
|
||||
void resume(Thread_capability thread) override {
|
||||
call<Rpc_resume>(thread); }
|
||||
|
||||
void cancel_blocking(Thread_capability thread) {
|
||||
void cancel_blocking(Thread_capability thread) override {
|
||||
call<Rpc_cancel_blocking>(thread); }
|
||||
|
||||
Thread_state state(Thread_capability thread) {
|
||||
Thread_state state(Thread_capability thread) override {
|
||||
return call<Rpc_get_state>(thread); }
|
||||
|
||||
void state(Thread_capability thread, Thread_state const &state) {
|
||||
void state(Thread_capability thread, Thread_state const &state) override {
|
||||
call<Rpc_set_state>(thread, state); }
|
||||
|
||||
void exception_handler(Thread_capability thread, Signal_context_capability handler) {
|
||||
void exception_handler(Thread_capability thread, Signal_context_capability handler) override {
|
||||
call<Rpc_exception_handler>(thread, handler); }
|
||||
|
||||
void single_step(Thread_capability thread, bool enable)
|
||||
void single_step(Thread_capability thread, bool enable) override
|
||||
{
|
||||
Native_capability block = call<Rpc_single_step_sync>(thread, enable);
|
||||
if (!block.valid())
|
||||
@ -76,28 +75,28 @@ namespace Genode {
|
||||
Nova::sm_ctrl(block.local_name(), Nova::SEMAPHORE_DOWN);
|
||||
}
|
||||
|
||||
Affinity::Space affinity_space() const {
|
||||
Affinity::Space affinity_space() const override {
|
||||
return call<Rpc_affinity_space>(); }
|
||||
|
||||
void affinity(Thread_capability thread, Affinity::Location location) {
|
||||
void affinity(Thread_capability thread, Affinity::Location location) override {
|
||||
call<Rpc_affinity>(thread, location); }
|
||||
|
||||
Dataspace_capability trace_control() {
|
||||
Dataspace_capability trace_control() override {
|
||||
return call<Rpc_trace_control>(); }
|
||||
|
||||
unsigned trace_control_index(Thread_capability thread) {
|
||||
unsigned trace_control_index(Thread_capability thread) override {
|
||||
return call<Rpc_trace_control_index>(thread); }
|
||||
|
||||
Dataspace_capability trace_buffer(Thread_capability thread) {
|
||||
Dataspace_capability trace_buffer(Thread_capability thread) override {
|
||||
return call<Rpc_trace_buffer>(thread); }
|
||||
|
||||
Dataspace_capability trace_policy(Thread_capability thread) {
|
||||
Dataspace_capability trace_policy(Thread_capability thread) override {
|
||||
return call<Rpc_trace_policy>(thread); }
|
||||
|
||||
int ref_account(Cpu_session_capability session) {
|
||||
int ref_account(Cpu_session_capability session) override {
|
||||
return call<Rpc_ref_account>(session); }
|
||||
|
||||
int transfer_quota(Cpu_session_capability session, size_t amount) {
|
||||
int transfer_quota(Cpu_session_capability session, size_t amount) override {
|
||||
return call<Rpc_transfer_quota>(session, amount); }
|
||||
|
||||
Quota quota() override { return call<Rpc_quota>(); }
|
||||
|
@ -35,6 +35,8 @@ struct Genode::Native_thread
|
||||
/* receive window for capability selectors received at the server side */
|
||||
Receive_window rcv_window;
|
||||
|
||||
Native_capability pager_cap;
|
||||
|
||||
Native_thread() : ec_sel(INVALID_INDEX),
|
||||
exc_pt_sel(INVALID_INDEX), is_vcpu(false) { }
|
||||
};
|
||||
|
32
repos/base-nova/include/nova_native_cpu/client.h
Normal file
32
repos/base-nova/include/nova_native_cpu/client.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* \brief Client-side NOVA-specific CPU session interface
|
||||
* \author Norman Feske
|
||||
* \date 2016-04-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 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 _INCLUDE__NOVA_NATIVE_CPU__CLIENT_H_
|
||||
#define _INCLUDE__NOVA_NATIVE_CPU__CLIENT_H_
|
||||
|
||||
#include <nova_native_cpu/nova_native_cpu.h>
|
||||
#include <base/rpc_client.h>
|
||||
|
||||
namespace Genode { struct Nova_native_cpu_client; }
|
||||
|
||||
|
||||
struct Genode::Nova_native_cpu_client : Rpc_client<Nova_native_cpu>
|
||||
{
|
||||
explicit Nova_native_cpu_client(Capability<Native_cpu> cap)
|
||||
: Rpc_client<Nova_native_cpu>(static_cap_cast<Nova_native_cpu>(cap)) { }
|
||||
|
||||
Native_capability pager_cap(Thread_capability cap) {
|
||||
return call<Rpc_pager_cap>(cap); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__NOVA_NATIVE_CPU__CLIENT_H_ */
|
36
repos/base-nova/include/nova_native_cpu/nova_native_cpu.h
Normal file
36
repos/base-nova/include/nova_native_cpu/nova_native_cpu.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* \brief NOVA-specific part of the CPU session interface
|
||||
* \author Norman Feske
|
||||
* \date 2016-04-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 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 _INCLUDE__NOVA_NATIVE_CPU__FOC_NATIVE_CPU_H_
|
||||
#define _INCLUDE__NOVA_NATIVE_CPU__FOC_NATIVE_CPU_H_
|
||||
|
||||
#include <base/rpc.h>
|
||||
#include <cpu_session/cpu_session.h>
|
||||
|
||||
namespace Genode { struct Nova_native_cpu; }
|
||||
|
||||
|
||||
struct Genode::Nova_native_cpu : Cpu_session::Native_cpu
|
||||
{
|
||||
virtual Native_capability pager_cap(Thread_capability) = 0;
|
||||
|
||||
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
GENODE_RPC(Rpc_pager_cap, Native_capability, pager_cap, Thread_capability);
|
||||
GENODE_RPC_INTERFACE(Rpc_pager_cap);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__NOVA_NATIVE_CPU__FOC_NATIVE_CPU_H_ */
|
@ -1,6 +1,7 @@
|
||||
SRC_CC += pager.cc
|
||||
|
||||
INC_DIR = $(REP_DIR)/src/core/include \
|
||||
$(BASE_DIR)/src/core/include
|
||||
$(BASE_DIR)/src/core/include \
|
||||
$(BASE_DIR)/src/include
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/core/spec/x86_32
|
||||
|
@ -1,5 +1,6 @@
|
||||
SRC_CC += pager.cc
|
||||
|
||||
INC_DIR = $(REP_DIR)/src/core/include
|
||||
INC_DIR = $(REP_DIR)/src/core/include \
|
||||
$(BASE_DIR)/src/include
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/core/spec/x86_64
|
||||
|
@ -20,6 +20,7 @@ using namespace Genode;
|
||||
Region_map_client::Region_map_client(Capability<Region_map> session)
|
||||
: Rpc_client<Region_map>(session) { }
|
||||
|
||||
|
||||
Region_map::Local_addr
|
||||
Region_map_client::attach(Dataspace_capability ds, size_t size, off_t offset,
|
||||
bool use_local_addr, Local_addr local_addr,
|
||||
@ -29,21 +30,17 @@ Region_map_client::attach(Dataspace_capability ds, size_t size, off_t offset,
|
||||
executable);
|
||||
}
|
||||
|
||||
|
||||
void Region_map_client::detach(Local_addr local_addr) {
|
||||
call<Rpc_detach>(local_addr); }
|
||||
|
||||
Pager_capability Region_map_client::add_client(Thread_capability thread)
|
||||
{
|
||||
return call<Rpc_add_client>(thread);
|
||||
}
|
||||
|
||||
void Region_map_client::remove_client(Pager_capability pager) {
|
||||
call<Rpc_remove_client>(pager); }
|
||||
|
||||
void Region_map_client::fault_handler(Signal_context_capability cap) {
|
||||
call<Rpc_fault_handler>(cap); }
|
||||
|
||||
Region_map::State Region_map_client::state() { return call<Rpc_state>(); }
|
||||
|
||||
Region_map::State Region_map_client::state() { return call<Rpc_state>(); }
|
||||
|
||||
|
||||
Dataspace_capability Region_map_client::dataspace()
|
||||
{
|
||||
|
@ -219,23 +219,13 @@ Rpc_entrypoint::Rpc_entrypoint(Pd_session *pd_session, size_t stack_size,
|
||||
const char *name, bool start_on_construction,
|
||||
Affinity::Location location)
|
||||
:
|
||||
Thread_base(Cpu_session::DEFAULT_WEIGHT, name, stack_size),
|
||||
Thread_base(Cpu_session::DEFAULT_WEIGHT, name, stack_size, location),
|
||||
_delay_start(Lock::LOCKED),
|
||||
_pd_session(*pd_session)
|
||||
{
|
||||
/* when not running in core set the affinity via cpu session */
|
||||
if (native_thread().ec_sel == Native_thread::INVALID_INDEX) {
|
||||
|
||||
/* place new thread on the specified CPU */
|
||||
if (location.valid())
|
||||
_cpu_session->affinity(_thread_cap, location);
|
||||
|
||||
/* magic value evaluated by thread_nova.cc to start a local thread */
|
||||
/* set magic value evaluated by thread_nova.cc to start a local thread */
|
||||
if (native_thread().ec_sel == Native_thread::INVALID_INDEX)
|
||||
native_thread().ec_sel = Native_thread::INVALID_INDEX - 1;
|
||||
} else {
|
||||
/* tell affinity CPU in 'core' via stack */
|
||||
reinterpret_cast<Affinity::Location *>(stack_base())[0] = location;
|
||||
}
|
||||
|
||||
/* required to create a 'local' EC */
|
||||
Thread_base::start();
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <base/env.h>
|
||||
#include <base/rpc_client.h>
|
||||
#include <session/session.h>
|
||||
#include <nova_native_cpu/client.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
@ -82,12 +83,11 @@ void Thread_base::_init_platform_thread(size_t weight, Type type)
|
||||
_thread_cap = env()->parent()->main_thread_cap();
|
||||
|
||||
Genode::Native_capability pager_cap(Nova::PT_SEL_MAIN_PAGER);
|
||||
_pager_cap = reinterpret_cap_cast<Pager_object>(pager_cap);
|
||||
|
||||
native_thread().exc_pt_sel = 0;
|
||||
native_thread().ec_sel = Nova::PT_SEL_MAIN_EC;
|
||||
|
||||
request_native_ec_cap(_pager_cap, native_thread().ec_sel);
|
||||
request_native_ec_cap(pager_cap, native_thread().ec_sel);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -116,12 +116,9 @@ void Thread_base::_init_platform_thread(size_t weight, Type type)
|
||||
char buf[48];
|
||||
name(buf, sizeof(buf));
|
||||
|
||||
_thread_cap = _cpu_session->create_thread(weight, buf);
|
||||
_thread_cap = _cpu_session->create_thread(env()->pd_session_cap(), weight, buf, _affinity);
|
||||
if (!_thread_cap.valid())
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
|
||||
/* assign thread to protection domain */
|
||||
env()->pd_session()->bind_thread(_thread_cap);
|
||||
}
|
||||
|
||||
|
||||
@ -139,9 +136,6 @@ void Thread_base::_deinit_platform_thread()
|
||||
_cpu_session->kill_thread(_thread_cap);
|
||||
|
||||
cap_map()->remove(native_thread().exc_pt_sel, NUM_INITIAL_PT_LOG2);
|
||||
|
||||
if (_pager_cap.valid())
|
||||
env()->rm_session()->remove_client(_pager_cap);
|
||||
}
|
||||
|
||||
|
||||
@ -158,12 +152,12 @@ void Thread_base::start()
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
/* create new pager object and assign it to the new thread */
|
||||
_pager_cap = env()->rm_session()->add_client(_thread_cap);
|
||||
if (!_pager_cap.valid())
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
/* obtain interface to NOVA-specific CPU session operations */
|
||||
Nova_native_cpu_client native_cpu(_cpu_session->native_cpu());
|
||||
|
||||
if (_cpu_session->set_pager(_thread_cap, _pager_cap))
|
||||
/* create new pager object and assign it to the new thread */
|
||||
Native_capability pager_cap = native_cpu.pager_cap(_thread_cap);
|
||||
if (!pager_cap.valid())
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
|
||||
/* create EC at core */
|
||||
@ -187,13 +181,13 @@ void Thread_base::start()
|
||||
|
||||
/* requested pager cap used by request_native_ec_cap in Signal_source_client */
|
||||
enum { MAP_PAGER_CAP = 1 };
|
||||
request_native_ec_cap(_pager_cap, native_thread().ec_sel, MAP_PAGER_CAP);
|
||||
request_native_ec_cap(pager_cap, native_thread().ec_sel, MAP_PAGER_CAP);
|
||||
|
||||
using namespace Nova;
|
||||
|
||||
/* request exception portals for normal threads */
|
||||
if (!native_thread().is_vcpu) {
|
||||
request_event_portal(_pager_cap, native_thread().exc_pt_sel, 0, NUM_INITIAL_PT_LOG2);
|
||||
request_event_portal(pager_cap, native_thread().exc_pt_sel, 0, NUM_INITIAL_PT_LOG2);
|
||||
|
||||
/* default: we don't accept any mappings or translations */
|
||||
Utcb * utcb_obj = reinterpret_cast<Utcb *>(utcb());
|
||||
|
@ -86,7 +86,7 @@ Core_region_map::attach(Dataspace_capability ds_cap, size_t size,
|
||||
|
||||
return virt_ptr;
|
||||
};
|
||||
return _ds_ep->apply(ds_cap, lambda);
|
||||
return _ep.apply(ds_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
/* Genode includes */
|
||||
#include <base/stdint.h>
|
||||
|
||||
/* Core includes */
|
||||
/* core-local includes */
|
||||
#include <cpu_session_component.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* \brief Core-local region map
|
||||
* \author Norman Feske
|
||||
* \date 2009-10-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-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 _CORE__INCLUDE__CORE_REGION_MAP_H_
|
||||
#define _CORE__INCLUDE__CORE_REGION_MAP_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <region_map/region_map.h>
|
||||
|
||||
/* core includes */
|
||||
#include <dataspace_component.h>
|
||||
|
||||
namespace Genode { class Core_region_map; }
|
||||
|
||||
|
||||
class Genode::Core_region_map : public Region_map
|
||||
{
|
||||
private:
|
||||
|
||||
Rpc_entrypoint *_ds_ep;
|
||||
|
||||
public:
|
||||
|
||||
Core_region_map(Rpc_entrypoint *ds_ep) : _ds_ep(ds_ep) { }
|
||||
|
||||
Local_addr attach(Dataspace_capability ds_cap, size_t size=0,
|
||||
off_t offset=0, bool use_local_addr = false,
|
||||
Local_addr local_addr = 0,
|
||||
bool executable = false) override;
|
||||
|
||||
void detach(Local_addr) override;
|
||||
|
||||
Pager_capability add_client(Thread_capability thread) override {
|
||||
return Pager_capability(); }
|
||||
|
||||
void remove_client(Pager_capability) override { }
|
||||
|
||||
void fault_handler(Signal_context_capability handler) override { }
|
||||
|
||||
State state() override { return State(); }
|
||||
|
||||
Dataspace_capability dataspace() override {
|
||||
return Dataspace_capability(); }
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__CORE_REGION_MAP_H_ */
|
@ -26,6 +26,8 @@
|
||||
|
||||
/* core includes */
|
||||
#include <pager.h>
|
||||
#include <cpu_thread_allocator.h>
|
||||
#include <pd_session_component.h>
|
||||
#include <platform_thread.h>
|
||||
#include <trace/control_area.h>
|
||||
#include <trace/source_registry.h>
|
||||
@ -57,31 +59,120 @@ namespace Genode {
|
||||
|
||||
private:
|
||||
|
||||
Rpc_entrypoint &_ep;
|
||||
Pager_entrypoint &_pager_ep;
|
||||
Capability<Pd_session> _pd;
|
||||
Region_map_component &_address_space_region_map;
|
||||
size_t const _weight;
|
||||
Session_label const _session_label;
|
||||
Thread_name const _name;
|
||||
Platform_thread _platform_thread;
|
||||
bool _bound; /* pd binding flag */
|
||||
bool const _bound_to_pd;
|
||||
|
||||
bool _bind_to_pd(Pd_session_component &pd)
|
||||
{
|
||||
if (!pd.bind_thread(_platform_thread))
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
return true;
|
||||
}
|
||||
|
||||
Signal_context_capability _sigh; /* exception handler */
|
||||
unsigned const _trace_control_index;
|
||||
Trace::Source _trace_source;
|
||||
|
||||
struct Trace_control_slot
|
||||
{
|
||||
unsigned index = 0;
|
||||
Trace::Control_area &trace_control_area;
|
||||
|
||||
Trace_control_slot(Trace::Control_area &trace_control_area)
|
||||
: trace_control_area(trace_control_area)
|
||||
{
|
||||
if (!trace_control_area.alloc(index))
|
||||
throw Cpu_session::Out_of_metadata();
|
||||
}
|
||||
|
||||
~Trace_control_slot()
|
||||
{
|
||||
trace_control_area.free(index);
|
||||
}
|
||||
|
||||
Trace::Control &control()
|
||||
{
|
||||
return *trace_control_area.at(index);
|
||||
}
|
||||
};
|
||||
|
||||
Trace_control_slot _trace_control_slot;
|
||||
|
||||
Trace::Source _trace_source { *this, _trace_control_slot.control() };
|
||||
|
||||
Weak_ptr<Address_space> _address_space = _platform_thread.address_space();
|
||||
|
||||
Rm_client _rm_client;
|
||||
|
||||
public:
|
||||
|
||||
Cpu_thread_component(size_t const weight,
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param ep entrypoint used for managing the thread RPC
|
||||
* object
|
||||
* \param pager_ep pager entrypoint used for handling the page
|
||||
* faults of the thread
|
||||
* \param pd PD session where the thread is executed
|
||||
* \param weight weighting regarding the CPU session quota
|
||||
* \param quota initial quota counter-value of the weight
|
||||
* \param labal label of the threads session
|
||||
* \param name name for the thread
|
||||
* \param priority scheduling priority
|
||||
* \param utcb user-local UTCB base
|
||||
* \param sigh initial exception handler
|
||||
*/
|
||||
Cpu_thread_component(Cpu_session_capability cpu_session_cap,
|
||||
Rpc_entrypoint &ep,
|
||||
Pager_entrypoint &pager_ep,
|
||||
Pd_session_component &pd,
|
||||
Trace::Control_area &trace_control_area,
|
||||
size_t const weight,
|
||||
size_t const quota,
|
||||
Affinity::Location affinity,
|
||||
Session_label const &label,
|
||||
Thread_name const &name,
|
||||
unsigned priority, addr_t utcb,
|
||||
Signal_context_capability sigh,
|
||||
unsigned trace_control_index,
|
||||
Trace::Control &trace_control)
|
||||
Signal_context_capability sigh)
|
||||
:
|
||||
_ep(ep), _pager_ep(pager_ep), _pd(pd.cap()),
|
||||
_address_space_region_map(pd.address_space_region_map()),
|
||||
_weight(weight),
|
||||
_session_label(label), _name(name),
|
||||
_platform_thread(name.string(), priority, utcb), _bound(false),
|
||||
_sigh(sigh), _trace_control_index(trace_control_index),
|
||||
_trace_source(*this, trace_control)
|
||||
_platform_thread(name.string(), priority, affinity, utcb),
|
||||
_bound_to_pd(_bind_to_pd(pd)),
|
||||
_sigh(sigh),
|
||||
_trace_control_slot(trace_control_area),
|
||||
_rm_client(cpu_session_cap, _ep.manage(this),
|
||||
&_address_space_region_map,
|
||||
_platform_thread.pager_object_badge(),
|
||||
_address_space, _platform_thread.affinity())
|
||||
{
|
||||
update_exception_sigh();
|
||||
|
||||
_address_space_region_map.add_client(_rm_client);
|
||||
|
||||
/* acquaint thread with its pager object */
|
||||
_pager_ep.manage(&_rm_client);
|
||||
_platform_thread.pager(&_rm_client);
|
||||
}
|
||||
|
||||
~Cpu_thread_component()
|
||||
{
|
||||
_pager_ep.dissolve(&_rm_client);
|
||||
_ep.dissolve(this);
|
||||
|
||||
_address_space_region_map.remove_client(_rm_client);
|
||||
}
|
||||
|
||||
void affinity(Affinity::Location affinity)
|
||||
{
|
||||
_platform_thread.affinity(affinity);
|
||||
}
|
||||
|
||||
|
||||
@ -102,8 +193,6 @@ namespace Genode {
|
||||
************************/
|
||||
|
||||
Platform_thread *platform_thread() { return &_platform_thread; }
|
||||
bool bound() const { return _bound; }
|
||||
void bound(bool b) { _bound = b; }
|
||||
Trace::Source *trace_source() { return &_trace_source; }
|
||||
|
||||
size_t weight() const { return Cpu_session::DEFAULT_WEIGHT; }
|
||||
@ -122,7 +211,7 @@ namespace Genode {
|
||||
/**
|
||||
* Return index within the CPU-session's trace control area
|
||||
*/
|
||||
unsigned trace_control_index() const { return _trace_control_index; }
|
||||
unsigned trace_control_index() const { return _trace_control_slot.index; }
|
||||
};
|
||||
|
||||
|
||||
@ -134,12 +223,6 @@ namespace Genode {
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Allocator used for managing the CPU threads associated with the
|
||||
* CPU session
|
||||
*/
|
||||
typedef Tslab<Cpu_thread_component, 1024> Cpu_thread_allocator;
|
||||
|
||||
Session_label _label;
|
||||
Rpc_entrypoint *_session_ep;
|
||||
Rpc_entrypoint *_thread_ep;
|
||||
@ -167,7 +250,7 @@ namespace Genode {
|
||||
List<Cpu_session_component> _ref_members;
|
||||
Lock _ref_members_lock;
|
||||
|
||||
Native_cpu_component _native_cpu;
|
||||
Native_cpu_component _native_cpu;
|
||||
|
||||
friend class Native_cpu_component;
|
||||
|
||||
@ -201,6 +284,11 @@ namespace Genode {
|
||||
*/
|
||||
void _unsynchronized_kill_thread(Thread_capability cap);
|
||||
|
||||
/**
|
||||
* Convert session-local affinity location to physical location
|
||||
*/
|
||||
Affinity::Location _thread_affinity(Affinity::Location) const;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -229,37 +317,37 @@ namespace Genode {
|
||||
** CPU session interface **
|
||||
***************************/
|
||||
|
||||
Thread_capability create_thread(size_t, Name const &, addr_t);
|
||||
Ram_dataspace_capability utcb(Thread_capability thread);
|
||||
void kill_thread(Thread_capability);
|
||||
int set_pager(Thread_capability, Pager_capability);
|
||||
int start(Thread_capability, addr_t, addr_t);
|
||||
void pause(Thread_capability thread_cap);
|
||||
void resume(Thread_capability thread_cap);
|
||||
void single_step(Thread_capability thread_cap, bool enable);
|
||||
void cancel_blocking(Thread_capability);
|
||||
int name(Thread_capability, char *, size_t);
|
||||
Thread_state state(Thread_capability);
|
||||
void state(Thread_capability, Thread_state const &);
|
||||
void exception_handler(Thread_capability, Signal_context_capability);
|
||||
Affinity::Space affinity_space() const;
|
||||
void affinity(Thread_capability, Affinity::Location);
|
||||
Dataspace_capability trace_control();
|
||||
unsigned trace_control_index(Thread_capability);
|
||||
Dataspace_capability trace_buffer(Thread_capability);
|
||||
Dataspace_capability trace_policy(Thread_capability);
|
||||
int ref_account(Cpu_session_capability c);
|
||||
int transfer_quota(Cpu_session_capability, size_t);
|
||||
Thread_capability create_thread(Capability<Pd_session>, size_t, Name const &,
|
||||
Affinity::Location, addr_t) override;
|
||||
Ram_dataspace_capability utcb(Thread_capability thread) override;
|
||||
void kill_thread(Thread_capability) override;
|
||||
int start(Thread_capability, addr_t, addr_t) override;
|
||||
void pause(Thread_capability thread_cap) override;
|
||||
void resume(Thread_capability thread_cap) override;
|
||||
void single_step(Thread_capability thread_cap, bool enable) override;
|
||||
void cancel_blocking(Thread_capability) override;
|
||||
Thread_state state(Thread_capability) override;
|
||||
void state(Thread_capability, Thread_state const &) override;
|
||||
void exception_handler(Thread_capability, Signal_context_capability) override;
|
||||
Affinity::Space affinity_space() const override;
|
||||
void affinity(Thread_capability, Affinity::Location) override;
|
||||
Dataspace_capability trace_control() override;
|
||||
unsigned trace_control_index(Thread_capability) override;
|
||||
Dataspace_capability trace_buffer(Thread_capability) override;
|
||||
Dataspace_capability trace_policy(Thread_capability) override;
|
||||
int ref_account(Cpu_session_capability c) override;
|
||||
int transfer_quota(Cpu_session_capability, size_t) override;
|
||||
Quota quota() override;
|
||||
Capability<Native_cpu> native_cpu() { return Capability<Native_cpu>(); }
|
||||
|
||||
Capability<Native_cpu> native_cpu() { return _native_cpu.cap(); }
|
||||
|
||||
|
||||
/******************************
|
||||
** NOVA specific extensions **
|
||||
******************************/
|
||||
|
||||
Native_capability pause_sync(Thread_capability);
|
||||
Native_capability single_step_sync(Thread_capability, bool);
|
||||
Native_capability pause_sync(Thread_capability) override;
|
||||
Native_capability single_step_sync(Thread_capability, bool) override;
|
||||
};
|
||||
}
|
||||
|
||||
|
44
repos/base-nova/src/core/include/native_cpu_component.h
Normal file
44
repos/base-nova/src/core/include/native_cpu_component.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* \brief Kernel-specific part of the CPU-session interface
|
||||
* \author Norman Feske
|
||||
* \date 2016-04-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 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 _CORE__INCLUDE__NATIVE_CPU_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__NATIVE_CPU_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/rpc_server.h>
|
||||
#include <nova_native_cpu/nova_native_cpu.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Cpu_session_component;
|
||||
class Native_cpu_component;
|
||||
}
|
||||
|
||||
|
||||
class Genode::Native_cpu_component : public Rpc_object<Nova_native_cpu,
|
||||
Native_cpu_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Cpu_session_component &_cpu_session;
|
||||
Rpc_entrypoint &_thread_ep;
|
||||
|
||||
public:
|
||||
|
||||
Native_cpu_component(Cpu_session_component &, char const *);
|
||||
~Native_cpu_component();
|
||||
|
||||
Native_capability pager_cap(Thread_capability) override;
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__NATIVE_CPU_COMPONENT_H_ */
|
@ -118,8 +118,9 @@ namespace Genode {
|
||||
inline void skip_reset() { _status &= ~SKIP_EXCEPTION; }
|
||||
} _state;
|
||||
|
||||
Thread_capability _thread_cap;
|
||||
Exception_handlers _exceptions;
|
||||
Cpu_session_capability _cpu_session_cap;
|
||||
Thread_capability _thread_cap;
|
||||
Exception_handlers _exceptions;
|
||||
|
||||
addr_t _pd;
|
||||
|
||||
@ -149,7 +150,9 @@ namespace Genode {
|
||||
|
||||
const Affinity::Location location;
|
||||
|
||||
Pager_object(unsigned long badge, Affinity::Location location);
|
||||
Pager_object(Cpu_session_capability cpu_session_cap,
|
||||
Thread_capability thread_cap,
|
||||
unsigned long badge, Affinity::Location location);
|
||||
|
||||
virtual ~Pager_object();
|
||||
|
||||
@ -283,11 +286,17 @@ namespace Genode {
|
||||
}
|
||||
|
||||
/**
|
||||
* Remember thread cap so that rm_session can tell thread that
|
||||
* rm_client is gone.
|
||||
* Return CPU session that was used to created the thread
|
||||
*/
|
||||
Thread_capability thread_cap() { return _thread_cap; } const
|
||||
void thread_cap(Thread_capability cap) { _thread_cap = cap; }
|
||||
Cpu_session_capability cpu_session_cap() const { return _cpu_session_cap; }
|
||||
|
||||
/**
|
||||
* Return thread capability
|
||||
*
|
||||
* This function enables the destructor of the thread's
|
||||
* address-space region map to kill the thread.
|
||||
*/
|
||||
Thread_capability thread_cap() const { return _thread_cap; }
|
||||
|
||||
/**
|
||||
* Note in the thread state that an unresolved page
|
||||
|
@ -51,7 +51,7 @@ namespace Genode {
|
||||
/**
|
||||
* Bind thread to protection domain
|
||||
*/
|
||||
void bind_thread(Platform_thread *thread);
|
||||
bool bind_thread(Platform_thread *thread);
|
||||
|
||||
/**
|
||||
* Unbind thread from protection domain
|
||||
|
@ -70,6 +70,7 @@ namespace Genode {
|
||||
*/
|
||||
Platform_thread(const char *name = 0,
|
||||
unsigned priority = 0,
|
||||
Affinity::Location affinity = Affinity::Location(),
|
||||
int thread_id = THREAD_INVALID);
|
||||
|
||||
/**
|
||||
@ -172,15 +173,6 @@ namespace Genode {
|
||||
if (main_thread) _features |= MAIN_THREAD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return pointer to the thread's PD
|
||||
*
|
||||
* Used to validate the success of the bind operation.
|
||||
*
|
||||
* XXX to be removed
|
||||
*/
|
||||
Platform_pd *pd() { return _pd; }
|
||||
|
||||
Native_capability single_step_sync(bool on);
|
||||
|
||||
/**
|
||||
|
@ -18,10 +18,11 @@
|
||||
#include <rm_session/rm_session.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/page_size.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
constexpr size_t get_page_size_log2() { return 12; }
|
||||
constexpr size_t get_page_size() { return 1 << get_page_size_log2(); }
|
||||
constexpr size_t get_super_page_size_log2() { return 22; }
|
||||
constexpr size_t get_super_page_size() { return 1 << get_super_page_size_log2(); }
|
||||
inline addr_t trunc_page(addr_t addr) { return addr & _align_mask(get_page_size_log2()); }
|
||||
|
48
repos/base-nova/src/core/native_cpu_component.cc
Normal file
48
repos/base-nova/src/core/native_cpu_component.cc
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* \brief Core implementation of the CPU session interface extension
|
||||
* \author Norman Feske
|
||||
* \date 2016-04-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/stdint.h>
|
||||
|
||||
/* core-local includes */
|
||||
#include <native_cpu_component.h>
|
||||
#include <cpu_session_component.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Native_capability
|
||||
Native_cpu_component::pager_cap(Thread_capability thread_cap)
|
||||
{
|
||||
auto lambda = [] (Cpu_thread_component *thread) {
|
||||
if (!thread)
|
||||
return Native_capability();
|
||||
|
||||
return thread->platform_thread()->pager()->cap();
|
||||
};
|
||||
return _thread_ep.apply(thread_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
Native_cpu_component::Native_cpu_component(Cpu_session_component &cpu_session, char const *)
|
||||
:
|
||||
_cpu_session(cpu_session), _thread_ep(*_cpu_session._thread_ep)
|
||||
{
|
||||
_thread_ep.manage(this);
|
||||
}
|
||||
|
||||
|
||||
Genode::Native_cpu_component::~Native_cpu_component()
|
||||
{
|
||||
_thread_ep.dissolve(this);
|
||||
}
|
@ -399,6 +399,10 @@ void Pager_object::cleanup_call()
|
||||
{
|
||||
_state.mark_dissolved();
|
||||
|
||||
/* revoke ec and sc cap of client before the sm cap */
|
||||
if (_state.sel_client_ec != Native_thread::INVALID_INDEX)
|
||||
revoke(Obj_crd(_state.sel_client_ec, 2));
|
||||
|
||||
/* revoke all portals handling the client. */
|
||||
revoke(Obj_crd(exc_pt_sel_client(), NUM_INITIAL_PT_LOG2));
|
||||
|
||||
@ -502,12 +506,15 @@ Exception_handlers::Exception_handlers(Pager_object *obj)
|
||||
******************/
|
||||
|
||||
|
||||
Pager_object::Pager_object(unsigned long badge, Affinity::Location location)
|
||||
Pager_object::Pager_object(Cpu_session_capability cpu_session_cap,
|
||||
Thread_capability thread_cap, unsigned long badge,
|
||||
Affinity::Location location)
|
||||
:
|
||||
_badge(badge),
|
||||
_selectors(cap_map()->insert(2)),
|
||||
_client_exc_pt_sel(cap_map()->insert(NUM_INITIAL_PT_LOG2)),
|
||||
_client_exc_vcpu(Native_thread::INVALID_INDEX),
|
||||
_cpu_session_cap(cpu_session_cap), _thread_cap(thread_cap),
|
||||
_exceptions(this),
|
||||
location(location)
|
||||
{
|
||||
@ -815,12 +822,10 @@ addr_t Pager_object::get_oom_portal()
|
||||
|
||||
Pager_activation_base::Pager_activation_base(const char *name, size_t stack_size)
|
||||
:
|
||||
Thread_base(Cpu_session::DEFAULT_WEIGHT, name, stack_size),
|
||||
Thread_base(Cpu_session::DEFAULT_WEIGHT, name, stack_size,
|
||||
Affinity::Location(which_cpu(this), 0)),
|
||||
_cap(Native_capability()), _ep(0), _cap_valid(Lock::LOCKED)
|
||||
{
|
||||
/* tell thread starting code on which CPU to let run the pager */
|
||||
reinterpret_cast<Affinity::Location *>(stack_base())[0] = Affinity::Location(which_cpu(this), 0);
|
||||
|
||||
/* creates local EC */
|
||||
Thread_base::start();
|
||||
|
||||
|
@ -25,10 +25,11 @@ using namespace Genode;
|
||||
** Public object members **
|
||||
***************************/
|
||||
|
||||
void Platform_pd::bind_thread(Platform_thread *thread)
|
||||
bool Platform_pd::bind_thread(Platform_thread *thread)
|
||||
{
|
||||
thread->bind_to_pd(this, _thread_cnt == 0);
|
||||
_thread_cnt++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,12 +39,7 @@ using namespace Genode;
|
||||
|
||||
void Platform_thread::affinity(Affinity::Location location)
|
||||
{
|
||||
if (_sel_exc_base != Native_thread::INVALID_INDEX) {
|
||||
PERR("Failure - affinity of thread could not be set");
|
||||
return;
|
||||
}
|
||||
|
||||
_location = location;
|
||||
PERR("dynamic affinity change not supported on NOVA");
|
||||
}
|
||||
|
||||
|
||||
@ -350,10 +345,11 @@ unsigned long long Platform_thread::execution_time() const
|
||||
}
|
||||
|
||||
|
||||
Platform_thread::Platform_thread(const char *name, unsigned prio, int thread_id)
|
||||
Platform_thread::Platform_thread(const char *name, unsigned prio,
|
||||
Affinity::Location affinity, int thread_id)
|
||||
:
|
||||
_pd(0), _pager(0), _id_base(cap_map()->insert(2)),
|
||||
_sel_exc_base(Native_thread::INVALID_INDEX), _location(boot_cpu(), 0, 0, 0),
|
||||
_sel_exc_base(Native_thread::INVALID_INDEX), _location(affinity),
|
||||
_features(0),
|
||||
_priority(Cpu_session::scale_priority(Nova::Qpd::DEFAULT_PRIORITY, prio)),
|
||||
_name(name)
|
||||
|
@ -23,6 +23,7 @@ SRC_CC = stack_area.cc \
|
||||
pager.cc \
|
||||
pd_session_component.cc \
|
||||
native_pd_component.cc \
|
||||
native_cpu_component.cc \
|
||||
pd_upgrade_ram_quota.cc \
|
||||
pd_assign_pci.cc \
|
||||
rpc_cap_factory.cc \
|
||||
|
@ -95,11 +95,7 @@ void Thread_base::start()
|
||||
Utcb * utcb_obj = reinterpret_cast<Utcb *>(&_stack->utcb());
|
||||
addr_t pd_sel = Platform_pd::pd_core_sel();
|
||||
|
||||
/*
|
||||
* In core, the affinity location has been written to the stack base by
|
||||
* the server or pager code. So - read the value from there.
|
||||
*/
|
||||
Affinity::Location location = reinterpret_cast<Affinity::Location *>(stack_base())[0];
|
||||
Affinity::Location location = _affinity;
|
||||
|
||||
if (!location.valid())
|
||||
location = Affinity::Location(boot_cpu(), 0);
|
||||
|
Reference in New Issue
Block a user