mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 08:25:38 +00:00
NOVA: extend cpu_session for base-nova
This commit is contained in:
parent
cb859a4785
commit
0a89d8dbb4
81
base-nova/include/nova_cpu_session/client.h
Normal file
81
base-nova/include/nova_cpu_session/client.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* \brief Client-side cpu session NOVA extension
|
||||
* \author Alexander Boettcher
|
||||
* \date 2012-07-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2012 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_CPU_SESSION__CLIENT_H_
|
||||
#define _INCLUDE__NOVA_CPU_SESSION__CLIENT_H_
|
||||
|
||||
#include <cpu_session/client.h>
|
||||
#include <nova_cpu_session/nova_cpu_session.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Nova_cpu_session_client : Rpc_client<Nova_cpu_session>
|
||||
{
|
||||
explicit Nova_cpu_session_client(Cpu_session_capability session)
|
||||
: Rpc_client<Nova_cpu_session>(static_cap_cast<Nova_cpu_session>(session)) { }
|
||||
|
||||
Thread_capability create_thread(Name const &name, addr_t utcb = 0) {
|
||||
return call<Rpc_create_thread>(name, utcb); }
|
||||
|
||||
Ram_dataspace_capability utcb(Thread_capability thread) {
|
||||
return call<Rpc_utcb>(thread); }
|
||||
|
||||
|
||||
void kill_thread(Thread_capability thread) {
|
||||
call<Rpc_kill_thread>(thread); }
|
||||
|
||||
Thread_capability first() {
|
||||
return call<Rpc_first>(); }
|
||||
|
||||
Thread_capability next(Thread_capability curr) {
|
||||
return call<Rpc_next>(curr); }
|
||||
|
||||
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) {
|
||||
return call<Rpc_start>(thread, ip, sp); }
|
||||
|
||||
void pause(Thread_capability thread) {
|
||||
call<Rpc_pause>(thread); }
|
||||
|
||||
void resume(Thread_capability thread) {
|
||||
call<Rpc_resume>(thread); }
|
||||
|
||||
void cancel_blocking(Thread_capability thread) {
|
||||
call<Rpc_cancel_blocking>(thread); }
|
||||
|
||||
int state(Thread_capability thread, Thread_state *dst_state) {
|
||||
return call<Rpc_state>(thread, dst_state); }
|
||||
|
||||
void exception_handler(Thread_capability thread, Signal_context_capability handler) {
|
||||
call<Rpc_exception_handler>(thread, handler); }
|
||||
|
||||
void single_step(Thread_capability thread, bool enable) {
|
||||
call<Rpc_single_step>(thread, enable); }
|
||||
|
||||
Native_capability native_cap(Thread_capability cap) {
|
||||
return call<Rpc_native_cap>(cap); }
|
||||
|
||||
int start_exc_base_vcpu(Thread_capability thread, addr_t ip,
|
||||
addr_t sp, addr_t exc_base)
|
||||
{
|
||||
return call<Rpc_start_exc_base_vcpu>(thread, ip, sp,
|
||||
exc_base);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__NOVA_CPU_SESSION__CLIENT_H_ */
|
40
base-nova/include/nova_cpu_session/connection.h
Normal file
40
base-nova/include/nova_cpu_session/connection.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* \brief Connection to NOVA specific CPU service
|
||||
* \author Alexander Boettcher
|
||||
* \date 2012-07-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2012 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_CPU_SESSION__CONNECTION_H_
|
||||
#define _INCLUDE__NOVA_CPU_SESSION__CONNECTION_H_
|
||||
|
||||
#include <nova_cpu_session/client.h>
|
||||
#include <base/connection.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Nova_cpu_connection : Connection<Cpu_session>, Nova_cpu_session_client
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param label initial session label
|
||||
* \param priority designated priority of all threads created
|
||||
* with this CPU session
|
||||
*/
|
||||
Nova_cpu_connection(const char *label = "", long priority = DEFAULT_PRIORITY)
|
||||
:
|
||||
Connection<Cpu_session>(
|
||||
session("priority=0x%lx, ram_quota=32K, label=\"%s\"",
|
||||
priority, label)),
|
||||
Nova_cpu_session_client(cap()) { }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__NOVA_CPU_SESSION__CONNECTION_H_ */
|
46
base-nova/include/nova_cpu_session/nova_cpu_session.h
Normal file
46
base-nova/include/nova_cpu_session/nova_cpu_session.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* \brief Cpu session interface extension for NOVA
|
||||
* \author Alexander Boettcher
|
||||
* \date 2012-07-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2012 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_CPU_SESSION__NOVA_CPU_SESSION_H_
|
||||
#define _INCLUDE__NOVA_CPU_SESSION__NOVA_CPU_SESSION_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
#include <cpu_session/cpu_session.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Nova_cpu_session : Cpu_session
|
||||
{
|
||||
virtual ~Nova_cpu_session() { }
|
||||
|
||||
virtual int
|
||||
start_exc_base_vcpu(Thread_capability thread, addr_t ip,
|
||||
addr_t sp, addr_t exc_base) = 0;
|
||||
virtual
|
||||
Native_capability native_cap(Thread_capability cap) = 0;
|
||||
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
GENODE_RPC(Rpc_start_exc_base_vcpu, int, start_exc_base_vcpu,
|
||||
Thread_capability, addr_t, addr_t, addr_t);
|
||||
GENODE_RPC(Rpc_native_cap, Native_capability, native_cap,
|
||||
Thread_capability);
|
||||
|
||||
GENODE_RPC_INTERFACE_INHERIT(Cpu_session, Rpc_native_cap,
|
||||
Rpc_start_exc_base_vcpu);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__NOVA_CPU_SESSION__NOVA_CPU_SESSION_H_ */
|
43
base-nova/src/core/cpu_session_extension.cc
Normal file
43
base-nova/src/core/cpu_session_extension.cc
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* \brief Core implementation of the CPU session interface extension
|
||||
* \author Alexander Boettcher
|
||||
* \date 2012-07-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2012 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 includes */
|
||||
#include <cpu_session_component.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
Native_capability
|
||||
Cpu_session_component::native_cap(Thread_capability thread_cap)
|
||||
{
|
||||
Cpu_thread_component *thread = _lookup_thread(thread_cap);
|
||||
if (!thread)
|
||||
return Native_capability(0, 0);
|
||||
|
||||
return thread->platform_thread()->native_cap();
|
||||
}
|
||||
|
||||
int
|
||||
Cpu_session_component::start_exc_base_vcpu(Thread_capability thread_cap,
|
||||
addr_t ip, addr_t sp,
|
||||
addr_t exc_base)
|
||||
{
|
||||
Cpu_thread_component *thread = _lookup_thread(thread_cap);
|
||||
if (!thread) return -1;
|
||||
|
||||
return thread->platform_thread()->start((void *)ip, (void *)sp, exc_base);
|
||||
}
|
||||
|
||||
|
156
base-nova/src/core/include/cpu_session_component.h
Normal file
156
base-nova/src/core/include/cpu_session_component.h
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the CPU session/thread interfaces
|
||||
* \author Christian Helmuth
|
||||
* \author Alexander Boettcher
|
||||
* \date 2006-07-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2012 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__CPU_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/list.h>
|
||||
#include <base/allocator_guard.h>
|
||||
#include <base/tslab.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/pager.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <nova_cpu_session/nova_cpu_session.h>
|
||||
|
||||
/* core includes */
|
||||
#include <platform_thread.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* RPC interface of CPU thread
|
||||
*
|
||||
* We make 'Cpu_thread' a RPC object only to be able to lookup CPU threads
|
||||
* from thread capabilities supplied as arguments to CPU-session functions.
|
||||
* A CPU thread does not provide an actual RPC interface.
|
||||
*/
|
||||
struct Cpu_thread
|
||||
{
|
||||
GENODE_RPC_INTERFACE();
|
||||
};
|
||||
|
||||
|
||||
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
|
||||
public List<Cpu_thread_component>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Platform_thread _platform_thread;
|
||||
|
||||
bool _bound; /* pd binding flag */
|
||||
|
||||
public:
|
||||
|
||||
Cpu_thread_component(const char *name, unsigned priority, addr_t)
|
||||
: _platform_thread(name, priority), _bound(false) { }
|
||||
|
||||
|
||||
/************************
|
||||
** Accessor functions **
|
||||
************************/
|
||||
|
||||
inline Platform_thread * platform_thread() { return &_platform_thread; }
|
||||
inline bool bound() const { return _bound; }
|
||||
inline void bound(bool b) { _bound = b; }
|
||||
};
|
||||
|
||||
|
||||
class Cpu_session_component : public Rpc_object<Nova_cpu_session>
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Allocator used for managing the CPU threads associated with the
|
||||
* CPU session
|
||||
*/
|
||||
typedef Tslab<Cpu_thread_component, 1024> Cpu_thread_allocator;
|
||||
|
||||
Rpc_entrypoint *_thread_ep;
|
||||
Pager_entrypoint *_pager_ep;
|
||||
Allocator_guard _md_alloc; /* guarded meta-data allocator */
|
||||
Cpu_thread_allocator _thread_alloc; /* meta-data allocator */
|
||||
Lock _thread_alloc_lock; /* protect alloc access */
|
||||
List<Cpu_thread_component> _thread_list;
|
||||
Lock _thread_list_lock; /* protect thread list */
|
||||
unsigned _priority; /* priority of threads
|
||||
created with this
|
||||
session */
|
||||
|
||||
/**
|
||||
* Lookup thread in CPU session by its capability
|
||||
*
|
||||
* \retval NULL thread capability is invalid or
|
||||
* does not belong to the CPU session
|
||||
*/
|
||||
Cpu_thread_component *_lookup_thread(Thread_capability thread) {
|
||||
return dynamic_cast<Cpu_thread_component *>
|
||||
(_thread_ep->obj_by_cap(thread)); }
|
||||
|
||||
/**
|
||||
* Raw thread-killing functionality
|
||||
*
|
||||
* This function is called from the 'kill_thread' function and
|
||||
* the destructor. Each these functions grab the list lock
|
||||
* by themselves and call this function to perform the actual
|
||||
* killing.
|
||||
*/
|
||||
void _unsynchronized_kill_thread(Cpu_thread_component *thread);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Cpu_session_component(Rpc_entrypoint *thread_ep,
|
||||
Pager_entrypoint *pager_ep,
|
||||
Allocator *md_alloc, const char *args);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Cpu_session_component();
|
||||
|
||||
|
||||
/***************************
|
||||
** CPU session interface **
|
||||
***************************/
|
||||
|
||||
Thread_capability create_thread(Name const &, addr_t);
|
||||
Ram_dataspace_capability utcb(Thread_capability thread);
|
||||
|
||||
void kill_thread(Thread_capability);
|
||||
Thread_capability first();
|
||||
Thread_capability next(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 cancel_blocking(Thread_capability);
|
||||
int name(Thread_capability, char *, size_t);
|
||||
int state(Thread_capability, Thread_state *);
|
||||
void exception_handler(Thread_capability, Signal_context_capability);
|
||||
|
||||
|
||||
/***********************************
|
||||
** NOVA specific extensions **
|
||||
***********************************/
|
||||
|
||||
int start_exc_base_vcpu(Thread_capability, addr_t,
|
||||
addr_t, addr_t);
|
||||
Native_capability native_cap(Thread_capability);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_ */
|
@ -31,7 +31,11 @@ namespace Genode {
|
||||
Platform_pd *_pd;
|
||||
Pager_object *_pager;
|
||||
bool _is_main_thread;
|
||||
int _id;
|
||||
addr_t _id_base;
|
||||
unsigned _cpu_no;
|
||||
|
||||
addr_t _sel_ec() { return _id_base; }
|
||||
addr_t _sel_sc() { return _id_base + 1; }
|
||||
|
||||
public:
|
||||
|
||||
@ -41,7 +45,7 @@ namespace Genode {
|
||||
* Constructor
|
||||
*/
|
||||
Platform_thread(const char *name = 0, unsigned priority = 0,
|
||||
addr_t utcb = 0, int thread_id = THREAD_INVALID);
|
||||
int thread_id = THREAD_INVALID);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
@ -53,12 +57,11 @@ namespace Genode {
|
||||
*
|
||||
* \param ip instruction pointer to start at
|
||||
* \param sp stack pointer to use
|
||||
* \param cpu_no target cpu
|
||||
*
|
||||
* \retval 0 successful
|
||||
* \retval -1 thread could not be started
|
||||
*/
|
||||
int start(void *ip, void *sp, unsigned int cpu_no = 0);
|
||||
int start(void *ip, void *sp, addr_t exc_base = ~0UL);
|
||||
|
||||
/**
|
||||
* Pause this thread
|
||||
@ -119,6 +122,12 @@ namespace Genode {
|
||||
{
|
||||
_pd = pd, _is_main_thread = is_main_thread;
|
||||
}
|
||||
|
||||
Native_capability native_cap()
|
||||
{
|
||||
return Native_capability(_sel_ec(), 0);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ void Platform_thread::set_cpu(unsigned int cpu_no)
|
||||
}
|
||||
|
||||
|
||||
int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no)
|
||||
int Platform_thread::start(void *ip, void *sp, addr_t exc_base)
|
||||
{
|
||||
using namespace Nova;
|
||||
|
||||
@ -48,13 +48,32 @@ int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no)
|
||||
return -1;
|
||||
}
|
||||
|
||||
enum { PD_EC_CPU_NO = 0, PD_UTCB = 0x6000000 };
|
||||
if (!_pd) {
|
||||
PERR("protection domain undefined");
|
||||
return -2;
|
||||
}
|
||||
|
||||
enum { PD_UTCB = 0x6000000 };
|
||||
_pager->initial_eip((addr_t)ip);
|
||||
if (!_is_main_thread) {
|
||||
addr_t initial_sp = reinterpret_cast<addr_t>(sp);
|
||||
addr_t utcb = round_page(initial_sp);
|
||||
|
||||
if (!_is_main_thread || !_pd) {
|
||||
_pager->initial_esp((addr_t)sp);
|
||||
return 0;
|
||||
_pager->initial_esp(initial_sp);
|
||||
if (exc_base == ~0UL) {
|
||||
PERR("exception base not specified");
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* ip == 0 means that caller will use the thread as worker */
|
||||
bool thread_global = ip;
|
||||
uint8_t res = create_ec(_sel_ec(), _pd->pd_sel(), _cpu_no,
|
||||
utcb, initial_sp,
|
||||
exc_base, thread_global);
|
||||
if (res)
|
||||
PERR("creation of new thread failed %u", res);
|
||||
|
||||
return res ? -4 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -67,32 +86,38 @@ int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no)
|
||||
int res = map_local((Nova::Utcb *)Thread_base::myself()->utcb(),
|
||||
Obj_crd(_pd->parent_pt_sel(), 0),
|
||||
Obj_crd(_pager->exc_pt_sel() + PT_SEL_PARENT, 0));
|
||||
if (res)
|
||||
if (res) {
|
||||
PERR("could not locally remap parent portal");
|
||||
return -5;
|
||||
}
|
||||
|
||||
Obj_crd initial_pts(_pager->exc_pt_sel(), Nova::NUM_INITIAL_PT_LOG2);
|
||||
Obj_crd initial_pts(_pager->exc_pt_sel(), Nova::NUM_INITIAL_PT_LOG2,
|
||||
1 << 4);
|
||||
|
||||
|
||||
int pd_sel = cap_selector_allocator()->pd_sel();
|
||||
int pd0_sel = _pager->exc_pt_sel() + Nova::PD_SEL;
|
||||
addr_t pd_sel = cap_selector_allocator()->pd_sel();
|
||||
addr_t pd0_sel = _pager->exc_pt_sel() + Nova::PD_SEL;
|
||||
_pd->assign_pd(pd0_sel);
|
||||
|
||||
res = create_pd(pd0_sel, pd_sel, initial_pts);
|
||||
if (res)
|
||||
if (res) {
|
||||
PERR("create_pd returned %d", res);
|
||||
|
||||
int ec_sel = cap_selector_allocator()->alloc();
|
||||
int sc_sel = cap_selector_allocator()->alloc();
|
||||
return -6;
|
||||
}
|
||||
|
||||
enum { THREAD_GLOBAL = true };
|
||||
res = create_ec(ec_sel, pd0_sel, PD_EC_CPU_NO, PD_UTCB, 0, 0,
|
||||
res = create_ec(_sel_ec(), pd0_sel, _cpu_no, PD_UTCB, 0, 0,
|
||||
THREAD_GLOBAL);
|
||||
if (res)
|
||||
PDBG("create_ec returned %d", res);
|
||||
if (res) {
|
||||
PERR("create_ec returned %d", res);
|
||||
return -7;
|
||||
}
|
||||
|
||||
res = create_sc(sc_sel, pd0_sel, ec_sel, Qpd());
|
||||
if (res)
|
||||
res = create_sc(_sel_sc(), pd0_sel, _sel_ec(), Qpd());
|
||||
if (res) {
|
||||
PERR("create_sc returned %d", res);
|
||||
return -8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -106,7 +131,10 @@ void Platform_thread::pause()
|
||||
|
||||
void Platform_thread::resume()
|
||||
{
|
||||
PDBG("not implemented");
|
||||
uint8_t res = Nova::create_sc(_sel_sc(), _pd->pd_sel(), _sel_ec(),
|
||||
Nova::Qpd());
|
||||
if (res)
|
||||
PDBG("create_sc returned %u", res);
|
||||
}
|
||||
|
||||
|
||||
@ -123,15 +151,13 @@ void Platform_thread::cancel_blocking() { PWRN("not implemented"); }
|
||||
unsigned long Platform_thread::pager_object_badge()
|
||||
const
|
||||
{
|
||||
return _pd ? ((_pd->id() << 16) || _id) : ~0;
|
||||
return ~0UL;
|
||||
}
|
||||
|
||||
|
||||
static int id_cnt;
|
||||
|
||||
|
||||
Platform_thread::Platform_thread(const char *name, unsigned, addr_t, int thread_id)
|
||||
: _pd(0), _id(++id_cnt) { }
|
||||
Platform_thread::Platform_thread(const char *name, unsigned, int thread_id)
|
||||
: _pd(0), _id_base(cap_selector_allocator()->alloc(1)),
|
||||
_cpu_no(0) { }
|
||||
|
||||
|
||||
Platform_thread::~Platform_thread()
|
||||
|
@ -32,7 +32,8 @@ SRC_CC = \
|
||||
main_thread.cc \
|
||||
context_area.cc \
|
||||
echo.cc \
|
||||
dump_alloc.cc
|
||||
dump_alloc.cc \
|
||||
cpu_session_extension.cc
|
||||
|
||||
INC_DIR = $(REP_DIR)/src/core/include \
|
||||
$(GEN_CORE_DIR)/include
|
||||
|
Loading…
x
Reference in New Issue
Block a user