NOVA: Adjust native_capability type

It now can hold a right bit used during IPC to demote rights of the to be
transfered capability.

The local_name field in the native_capability type is not needed anymore
in NOVA. Simplify the class, remove it from constructors and adapt all
invocations in base-nova.

Unfortunately local_name in struct Raw is still used in generic base code
(process.cc, reload_parent_cap.cc), however has no effect in base-nova.
This commit is contained in:
Alexander Boettcher 2012-07-30 10:56:07 +02:00 committed by Norman Feske
parent 7550f243ad
commit 4155585267
17 changed files with 208 additions and 102 deletions

View File

@ -20,14 +20,15 @@
inline void Genode::Ipc_ostream::_marshal_capability(Genode::Native_capability const &cap)
{
if (cap.valid())
_snd_msg->snd_append_pt_sel(cap.dst());
_snd_msg->snd_append_pt_sel(cap.local_name(),
cap.dst().rights());
}
inline void Genode::Ipc_istream::_unmarshal_capability(Genode::Native_capability &cap)
{
addr_t pt_sel = _rcv_msg->rcv_pt_sel();
cap = Native_capability(pt_sel, pt_sel);
cap = Native_capability(pt_sel);
}
#endif /* _INCLUDE__BASE__IPC_H_ */

View File

@ -45,7 +45,10 @@ namespace Genode {
/**
* Portal capability selectors to delegate
*/
addr_t _snd_pt_sel[MAX_CAP_ARGS];
struct {
addr_t sel;
unsigned rights;
} _snd_pt_sel [MAX_CAP_ARGS];
/**
* Base of portal receive window
@ -109,19 +112,25 @@ namespace Genode {
/**
* Append portal capability selector to message buffer
*/
inline bool snd_append_pt_sel(addr_t pt_sel)
inline bool snd_append_pt_sel(addr_t pt_sel,
unsigned rights)
{
if (_snd_pt_sel_cnt >= MAX_CAP_ARGS - 1)
return false;
_snd_pt_sel[_snd_pt_sel_cnt++] = pt_sel;
_snd_pt_sel[_snd_pt_sel_cnt ].sel = pt_sel;
_snd_pt_sel[_snd_pt_sel_cnt++].rights = rights;
return true;
}
/**
* Return number of marshalled portal-capability selectors
* Return number of marshalled portal-capability
* selectors
*/
inline size_t snd_pt_sel_cnt() { return _snd_pt_sel_cnt; }
inline size_t snd_pt_sel_cnt()
{
return _snd_pt_sel_cnt;
}
/**
* Return portal capability selector
@ -130,7 +139,14 @@ namespace Genode {
* \return portal-capability selector, or
* -1 if index is invalid
*/
addr_t snd_pt_sel(unsigned i) { return i < _snd_pt_sel_cnt ? _snd_pt_sel[i] : -1; }
Nova::Obj_crd snd_pt_sel(addr_t i)
{
if (i >= _snd_pt_sel_cnt)
return Nova::Obj_crd();
return Nova::Obj_crd(_snd_pt_sel[i].sel, 0,
_snd_pt_sel[i].rights);
}
/**
* Request current portal-receive window

View File

@ -17,6 +17,8 @@
#include <base/native_capability.h>
#include <base/stdint.h>
#include <nova/syscalls.h>
namespace Genode {
typedef volatile int Native_lock;
@ -57,18 +59,88 @@ namespace Genode {
* user process. It is not backed by a dataspace but provided
* by the kernel.
*/
long _utcb[UTCB_SIZE/sizeof(long)];
addr_t _utcb[UTCB_SIZE/sizeof(addr_t)];
};
struct Cap_dst_policy
class Native_capability
{
typedef addr_t Dst;
static bool valid(Dst pt) { return pt != 0; }
static Dst invalid() { return 0; }
static void copy(void* dst, Native_capability_tpl<Cap_dst_policy>* src);
public:
typedef Nova::Obj_crd Dst;
struct Raw
{
Dst dst;
/*
* It is obsolete and unused in NOVA,
* however still used by generic base part
*/
addr_t local_name;
};
private:
struct _Raw
{
Dst dst;
_Raw() : dst() { }
_Raw(addr_t sel, unsigned rights)
: dst(sel, 0, rights) { }
} _cap;
bool _trans_map;
void * _ptr;
protected:
explicit
Native_capability(void* ptr) : _cap(),
_trans_map(true),
_ptr(ptr) { }
public:
Native_capability() : _cap(), _trans_map(true),
_ptr(0) { }
explicit
Native_capability(addr_t sel, unsigned rights = 0x1f)
: _cap(sel, rights), _trans_map(true), _ptr(0) { }
Native_capability(const Native_capability &o)
: _cap(o._cap), _trans_map(o._trans_map), _ptr(o._ptr) { }
Native_capability& operator=(const Native_capability &o){
if (this == &o)
return *this;
_cap = o._cap;
_trans_map = o._trans_map;
_ptr = o._ptr;
return *this;
}
bool valid() const
{
return !_cap.dst.is_null() &&
_cap.dst.base() != ~0UL;
}
Dst dst() const { return _cap.dst; }
void * local() const { return _ptr; }
addr_t local_name() const { return _cap.dst.base(); }
static Dst invalid() { return Dst(); }
static Native_capability invalid_cap()
{
return Native_capability(~0UL);
}
/** Invoke map syscall instead of translate_map call */
void solely_map() { _trans_map = false; }
bool trans_map() const { return _trans_map; }
};
typedef Native_capability_tpl<Cap_dst_policy> Native_capability;
typedef int Native_connection_state;
}

View File

@ -44,8 +44,7 @@ namespace Genode {
*/
Signal_context_capability _exception_sigh;
unsigned _pt_sel; /* portal selector for object identity */
unsigned _pt_cleanup; /* portal selector for object cleanup/destruction */
addr_t _pt_cleanup; /* portal selector for object cleanup/destruction */
addr_t _initial_esp;
addr_t _initial_eip;
@ -92,11 +91,6 @@ namespace Genode {
*/
void initial_eip(addr_t eip) { _initial_eip = eip; }
/**
* Return portal capability selector used for object identity
*/
unsigned pt_sel() { return _pt_sel; }
/**
* Continue execution of pager object
*/
@ -113,15 +107,13 @@ namespace Genode {
transmitter.submit();
}
/**
* Return entry point address
*/
addr_t handler_address()
{
return reinterpret_cast<addr_t>(_invoke_handler);
return reinterpret_cast<addr_t>(_invoke_handler);
}
};

View File

@ -242,6 +242,7 @@ namespace Nova {
mword_t order() const { return _query<ORDER_MASK, ORDER_SHIFT>(); }
bool is_null() const { return (_value & TYPE_MASK) == NULL_CRD_TYPE; }
uint8_t type() const { return _query<TYPE_MASK, TYPE_SHIFT>(); }
uint8_t rights() const { return _query<RIGHTS_MASK, RIGHTS_SHIFT>(); }
} __attribute__((packed));
@ -323,6 +324,15 @@ namespace Nova {
{
public:
enum {
RIGHT_EC_RECALL = 0x1U,
};
Obj_crd() : Crd(0, 0)
{
_assign<TYPE_MASK, TYPE_SHIFT>(NULL_CRD_TYPE);
}
Obj_crd(mword_t base, mword_t order,
mword_t rights = RIGHTS_ALL)
: Crd(base, order)

View File

@ -31,7 +31,7 @@ inline void request_event_portal(Genode::Native_capability cap,
utcb->msg[0] = event;
utcb->set_msg_word(1);
uint8_t res = call(pager_cap.dst());
uint8_t res = call(pager_cap.local_name());
if (res)
PERR("request of event (%lu) capability selector failed",
event);

View File

@ -25,6 +25,8 @@
#include <base/rpc_client.h>
#include <signal_session/nova_source.h>
#include <base/nova_util.h>
namespace Genode {
class Signal_source_client : public Rpc_client<Nova_signal_source>
@ -54,7 +56,8 @@ namespace Genode {
* Constructor
*/
Signal_source_client(Signal_source_capability cap)
: Rpc_client<Nova_signal_source>(static_cap_cast<Nova_signal_source>(cap)) { }
: Rpc_client<Nova_signal_source>(
static_cap_cast<Nova_signal_source>(cap)) { }
/*****************************
@ -63,11 +66,19 @@ namespace Genode {
Signal wait_for_signal()
{
/* make sure that we have aquired the semaphore from the server */
/*
* Make sure that we have acquired the
* semaphore from the server
*/
_init_sem();
/* block on semaphore, will be unblocked if signal is available */
Nova::sm_ctrl(_sem.dst(), Nova::SEMAPHORE_DOWN);
/*
* Block on semaphore, will be unblocked if
* signal is available
*/
if (Nova::sm_ctrl(_sem.local_name(),
Nova::SEMAPHORE_DOWN))
nova_die(__FILE__, __LINE__);
/*
* Now that the server has unblocked the semaphore, we are sure

View File

@ -82,10 +82,10 @@ static bool copy_msgbuf_to_utcb(Nova::Utcb *utcb, Msgbuf_base *snd_msg,
/* append portal capability selectors */
for (unsigned i = 0; i < snd_msg->snd_pt_sel_cnt(); i++) {
int pt_sel = snd_msg->snd_pt_sel(i);
if (pt_sel < 0) continue;
Nova::Obj_crd crd = snd_msg->snd_pt_sel(i);
if (crd.base() == ~0UL) continue;
if (!utcb->append_item(Nova::Obj_crd(pt_sel, 0), i, false, false, true))
if (!utcb->append_item(crd, i, false, false, true))
return false;
}
@ -142,7 +142,7 @@ void Ipc_client::_call()
_rcv_msg->rcv_prepare_pt_sel_window(utcb);
/* establish the mapping via a portal traversal */
uint8_t res = Nova::call(Ipc_ostream::_dst.dst());
uint8_t res = Nova::call(Ipc_ostream::_dst.local_name());
if (res) {
/* If an error occurred, reset word&item count (not done by kernel). */
utcb->set_msg_word(0);

View File

@ -99,11 +99,10 @@ void Pager_object::wake_up() { PDBG("not yet implemented"); }
Pager_object::Pager_object(unsigned long badge)
: Thread_base("pager", PF_HANDLER_STACK_SIZE), _badge(badge)
{
addr_t pd_sel = cap_selector_allocator()->pd_sel();
enum { CPU_NO = 0, GLOBAL = false, EXC_BASE = 0 };
_pt_cleanup = cap_selector_allocator()->alloc();
/* create portal for page-fault handler */
addr_t pd_sel = __core_pd_sel;
uint8_t res = create_pt(exc_pt_sel() + PT_SEL_PAGE_FAULT, pd_sel,
_tid.ec_sel, Mtd(Mtd::QUAL | Mtd::EIP),
(mword_t)_page_fault_handler);
@ -124,20 +123,6 @@ Pager_object::Pager_object(unsigned long badge)
throw Create_startup_pt_failed();
}
/*
* Create object identity representing the pager object. It is used as
* argument to 'Cpu_session::set_pager'. Furthermore it can be invoked
* to request the mapping of the event capability selector window
* corresponding to the pager object.
*/
_pt_sel = cap_selector_allocator()->alloc();
res = create_pt(_pt_sel, pd_sel, _tid.ec_sel, Mtd(0),
reinterpret_cast<addr_t>(_invoke_handler));
if (res)
PERR("could not create pager object identity, error = %u\n",
res);
_pt_cleanup = cap_selector_allocator()->alloc();
res = create_pt(_pt_cleanup, pd_sel, _tid.ec_sel, Mtd(0),
reinterpret_cast<addr_t>(_invoke_handler));
if (res)
@ -147,10 +132,9 @@ Pager_object::Pager_object(unsigned long badge)
Pager_object::~Pager_object()
{
/* Revoke thread portals serving exceptions */
revoke(Obj_crd(exc_pt_sel(), NUM_INITIAL_PT_LOG2), true);
/* Revoke portal used as identity object */
revoke(Obj_crd(_pt_sel, 0), true);
/* Revoke portals of Pager_object */
revoke(Obj_crd(exc_pt_sel() + PT_SEL_STARTUP, 0), true);
revoke(Obj_crd(exc_pt_sel() + PT_SEL_PAGE_FAULT, 0), true);
/* Make sure nobody is in the handler anymore by doing an IPC to a
* local cap pointing to same serving thread (if not running in the
@ -167,8 +151,6 @@ Pager_object::~Pager_object()
/* Revoke portal used for the cleanup call */
revoke(Obj_crd(_pt_cleanup, 0), true);
cap_selector_allocator()->free(_pt_sel, 0);
cap_selector_allocator()->free(_pt_cleanup, 0);
}
@ -177,11 +159,9 @@ Pager_object::~Pager_object()
Pager_capability Pager_entrypoint::manage(Pager_object *obj)
{
/* request creation of portal bind to pager thread */
Native_capability pager_thread_cap(obj->ec_sel(), 0);
Native_capability cap_session = _cap_session->alloc(pager_thread_cap,
obj->handler_address());
cap_session = Native_capability(cap_session.dst(), cap_session.dst());
Native_capability pager_thread_cap(obj->ec_sel());
Native_capability cap_session =
_cap_session->alloc(pager_thread_cap, obj->handler_address());
/* add server object to object pool */
obj->Object_pool<Pager_object>::Entry::cap(cap_session);
@ -199,9 +179,12 @@ void Pager_entrypoint::dissolve(Pager_object *obj)
_cap_session->free(obj->Object_pool<Pager_object>::Entry::cap());
/* cleanup locally */
addr_t pager_pt = obj->Object_pool<Pager_object>::Entry::cap().dst();
revoke(Obj_crd(pager_pt, 0), true);
cap_selector_allocator()->free(pager_pt, 0);
Native_capability pager_pt =
obj->Object_pool<Pager_object>::Entry::cap();
revoke(pager_pt.dst(), true);
cap_selector_allocator()->free(pager_pt.local_name(), 0);
remove(obj);
}

View File

@ -38,12 +38,11 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
/* _ec_sel is invalid until thread gets started */
if (tid().ec_sel != ~0UL)
ep_cap = Native_capability(tid().ec_sel, 0);
ec_cap = Native_capability(tid().ec_sel);
else
ep_cap = Native_capability(_thread_cap.dst(), 0);
ec_cap = _thread_cap;
new_obj_cap = _cap_session->alloc(ep_cap, (addr_t)_activation_entry);
new_obj_cap = Native_capability(new_obj_cap.dst(), new_obj_cap.dst());
ep_cap = _cap_session->alloc(ec_cap, (addr_t)_activation_entry);
/* add server object to object pool */
obj->cap(new_obj_cap);
@ -100,7 +99,7 @@ void Rpc_entrypoint::_activation_entry()
ep->_rcv_buf.post_ipc(reinterpret_cast<Nova::Utcb *>(ep->utcb()));
/* destination of next reply */
srv.dst(Native_capability(id_pt, srv.badge()));
srv.dst(Native_capability(id_pt));
int opcode = 0;
@ -223,7 +222,7 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size,
* (to create portals bound to the ec)
*/
Native_capability ec_cap = cpu.native_cap(_thread_cap);
_tid.ec_sel = ec_cap.dst();
_tid.ec_sel = ec_cap.local_name();
}
_rcv_buf.rcv_prepare_pt_sel_window((Nova::Utcb *)&_context->utcb);

View File

@ -96,6 +96,10 @@ void Thread_base::_deinit_platform_thread()
/* de-announce thread */
env()->cpu_session()->kill_thread(_thread_cap);
revoke(_thread_cap.local_name(), 0);
cap_selector_allocator()->free(_thread_cap.local_name(), 0);
}
@ -120,7 +124,7 @@ void Thread_base::start()
/* request native EC thread cap */
Native_capability ec_cap = cpu.native_cap(_thread_cap);
_tid.ec_sel = ec_cap.dst();
_tid.ec_sel = ec_cap.local_name();
using namespace Nova;

View File

@ -38,9 +38,29 @@ namespace Genode {
addr_t entry,
addr_t mtd)
{
Lock::Guard lock_guard(_lock());
addr_t pt_sel = cap_selector_allocator()->alloc(0);
addr_t pd_sel = Platform_pd::pd_core_sel();
addr_t ec_sel = ep.local_name();
using namespace Nova;
/* create portal */
uint8_t res = create_pt(pt_sel, pd_sel, ec_sel,
Mtd(mtd), entry);
if (res == NOVA_OK)
return Native_capability(pt_sel);
return Native_capability(ep.dst(), ++_unique_id_cnt);
PERR("cap_session - cap=%lx:%lx"
" addr=%lx flags=%lx xpt=%lx res=%u",
ec_sel, ep.local_name(),
entry, mtd, pt_sel, res);
/* cleanup unused selectors */
cap_selector_allocator()->free(pt_sel, 0);
/* XXX revoke ec_sel if it was mapped !!!! */
return Native_capability::invalid_cap();
}
void free(Native_capability cap) { }

View File

@ -63,14 +63,14 @@ namespace Genode {
/**
* Return portal capability selector for parent interface
*/
int parent_pt_sel() { return _parent.dst(); }
addr_t parent_pt_sel() { return _parent.local_name(); }
/**
* Assign PD selector to PD
*/
void assign_pd(int pd_sel) { _pd_sel = pd_sel; }
int pd_sel() { return _pd_sel; }
addr_t pd_sel() { return _pd_sel; }
int id() { return _id; }
};

View File

@ -149,18 +149,19 @@ static void init_core_page_fault_handler()
static char stack[STACK_SIZE];
mword_t sp = (long)&stack[STACK_SIZE - sizeof(long)];
int ec_sel = cap_selector_allocator()->alloc();
addr_t sp = (addr_t)&stack[STACK_SIZE - sizeof(addr_t)];
addr_t ec_sel = cap_selector_allocator()->alloc();
int ret = create_ec(ec_sel, __local_pd_sel, CPU_NO, CORE_PAGER_UTCB_ADDR,
(mword_t)sp, EXC_BASE, GLOBAL);
uint8_t ret = create_ec(ec_sel, __core_pd_sel, CPU_NO,
CORE_PAGER_UTCB_ADDR, (addr_t)sp, EXC_BASE,
GLOBAL);
if (ret)
PDBG("create_ec returned %d", ret);
PDBG("create_ec returned %u", ret);
/* set up page-fault portal */
create_pt(PT_SEL_PAGE_FAULT, __local_pd_sel, ec_sel,
Mtd(Mtd::QUAL | Mtd::ESP | Mtd::EIP),
(mword_t)page_fault_handler);
(addr_t)page_fault_handler);
}

View File

@ -40,7 +40,8 @@ void Signal_source_component::submit(Signal_context_component *context,
_signal_queue.enqueue(context);
/* wake up client */
Nova::sm_ctrl(_blocking_semaphore.dst(), Nova::SEMAPHORE_UP);
Nova::sm_ctrl(_blocking_semaphore.local_name(),
Nova::SEMAPHORE_UP);
}
}
@ -64,10 +65,11 @@ Signal_source_component::Signal_source_component(Rpc_entrypoint *ep)
: _entrypoint(ep)
{
/* initialized blocking semaphore */
int sem_sel = cap_selector_allocator()->alloc();
int ret = Nova::create_sm(sem_sel, cap_selector_allocator()->pd_sel(), 0);
addr_t sem_sel = cap_selector_allocator()->alloc();
uint8_t ret = Nova::create_sm(sem_sel,
cap_selector_allocator()->pd_sel(), 0);
if (ret)
PERR("create_sm returned %d", ret);
_blocking_semaphore = Native_capability(sem_sel, 0);
_blocking_semaphore = Native_capability(sem_sel);
}

View File

@ -35,10 +35,11 @@ using namespace Genode;
*/
void Thread_base::_init_platform_thread()
{
_tid.ec_sel = cap_selector_allocator()->alloc();
_tid.rs_sel = cap_selector_allocator()->alloc();
_tid.pd_sel = cap_selector_allocator()->pd_sel();
_tid.exc_pt_sel = cap_selector_allocator()->alloc(Nova::NUM_INITIAL_PT_LOG2);
using namespace Nova;
_tid.ec_sel = cap_selector_allocator()->alloc();
_tid.exc_pt_sel = cap_selector_allocator()->alloc(NUM_INITIAL_PT_LOG2);
addr_t pd_sel = Platform_pd::pd_core_sel();
/* create running semaphore required for locking */
uint8_t res = Nova::create_sm(_tid.rs_sel, _tid.pd_sel, 0);
@ -56,7 +57,7 @@ void Thread_base::_init_platform_thread()
if (res) {
PERR("%p - create_ec returned %d", this, res);
PERR("valid thread %x %lx:%lx", _thread_cap.valid(),
_thread_cap.dst(), _thread_cap.local_name());
_thread_cap.dst()._sel, _thread_cap.local_name());
}
}

View File

@ -1,13 +1,11 @@
/*
* \brief Obtain parent capability
* \author Norman Feske
* \author Alexander Boettcher
* \date 2010-01-26
*
* On NOVA, the parent capability consists of two parts, a local portal
* capability selector (as invokation address) and a global unique object ID.
* The parent portal is, by convention, capability selector 'PT_CAP_PARENT'
* supplied with the initial portals when the PD is created. The object ID is
* provided at the begin of the data segment of the loaded ELF image.
* supplied with the initial portals when the PD is created.
*/
/*
@ -33,13 +31,9 @@ namespace Genode {
*/
Parent_capability parent_cap()
{
/* read capability from start of data section, containing object ID */
Native_capability cap;
memcpy(&cap, (void *)&_parent_cap, sizeof(cap));
/* assemble parent capability from object ID and portal */
return reinterpret_cap_cast<Parent>(Native_capability(Nova::PT_SEL_PARENT,
cap.local_name()));
/* assemble parent capability */
return reinterpret_cap_cast<Parent>(
Native_capability(Nova::PT_SEL_PARENT));
}
}