NOVA: extend cpu_session for base-nova

This commit is contained in:
Alexander Boettcher 2012-08-08 17:12:10 +02:00 committed by Norman Feske
parent cb859a4785
commit 0a89d8dbb4
8 changed files with 432 additions and 30 deletions

View 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_ */

View 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_ */

View 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_ */

View 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);
}

View 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_ */

View File

@ -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);
}
};
}

View File

@ -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()

View File

@ -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