nova: use cap_map for IPC

Issue #905
This commit is contained in:
Alexander Boettcher 2013-09-06 14:44:12 +02:00 committed by Norman Feske
parent 75ecdab9e8
commit c139253439
2 changed files with 46 additions and 51 deletions

View File

@ -21,9 +21,6 @@
#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_ #ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
#define _INCLUDE__BASE__IPC_MSGBUF_H_ #define _INCLUDE__BASE__IPC_MSGBUF_H_
/* Genode includes */
#include <base/cap_sel_alloc.h>
/* NOVA includes */ /* NOVA includes */
#include <nova/syscalls.h> #include <nova/syscalls.h>
#include <nova/util.h> #include <nova/util.h>
@ -51,11 +48,7 @@ namespace Genode {
/** /**
* Portal capability selectors to delegate * Portal capability selectors to delegate
*/ */
struct { Native_capability _snd_pt_sel [MAX_CAP_ARGS];
addr_t sel;
unsigned rights;
bool trans_map;
} _snd_pt_sel [MAX_CAP_ARGS];
/** /**
* Base of portal receive window * Base of portal receive window
@ -117,20 +110,25 @@ namespace Genode {
/** /**
* Reset portal capability selector payload * Reset portal capability selector payload
*/ */
inline void snd_reset() { _snd_pt_sel_cnt = 0; } inline void snd_reset() {
for (unsigned i = 0; i < MAX_CAP_ARGS; i++) {
+_snd_pt_sel[i];
_snd_pt_sel[i] = Native_capability();
}
_snd_pt_sel_cnt = 0;
}
/** /**
* Append portal capability selector to message buffer * Append portal capability selector to message buffer
*/ */
inline bool snd_append_pt_sel(addr_t pt_sel, unsigned rights, inline bool snd_append_pt_sel(Native_capability const &cap)
bool trans_map)
{ {
if (_snd_pt_sel_cnt >= MAX_CAP_ARGS - 1) if (_snd_pt_sel_cnt >= MAX_CAP_ARGS - 1)
return false; return false;
_snd_pt_sel[_snd_pt_sel_cnt ].sel = pt_sel; _snd_pt_sel[_snd_pt_sel_cnt++ ] = cap;
_snd_pt_sel[_snd_pt_sel_cnt ].rights = rights;
_snd_pt_sel[_snd_pt_sel_cnt++].trans_map = trans_map;
return true; return true;
} }
@ -157,9 +155,10 @@ namespace Genode {
if (i >= _snd_pt_sel_cnt) if (i >= _snd_pt_sel_cnt)
return Nova::Obj_crd(); return Nova::Obj_crd();
trans_map = _snd_pt_sel[i].trans_map; trans_map = _snd_pt_sel[i].trans_map();
return Nova::Obj_crd(_snd_pt_sel[i].sel, 0,
_snd_pt_sel[i].rights); return Nova::Obj_crd(_snd_pt_sel[i].local_name(), 0,
_snd_pt_sel[i].dst().rights());
} }
/** /**
@ -194,13 +193,15 @@ namespace Genode {
/** /**
* Return received portal-capability selector * Return received portal-capability selector
*/ */
addr_t rcv_pt_sel() void rcv_pt_sel(Native_capability &cap)
{ {
if (_rcv_pt_sel_cnt >= _rcv_pt_sel_max) {
cap = Native_capability();
return;
}
/* return only received or translated caps */ /* return only received or translated caps */
if (_rcv_pt_sel_cnt < _rcv_pt_sel_max) cap = Native_capability(_rcv_pt_sel[_rcv_pt_sel_cnt++].sel);
return _rcv_pt_sel[_rcv_pt_sel_cnt++].sel;
else
return INVALID_INDEX;
} }
/** /**
@ -245,37 +246,38 @@ namespace Genode {
nova_die(); nova_die();
_rcv_pt_cap_free [_rcv_pt_sel[i].sel - rcv_pt_base()] = USED_CAP; _rcv_pt_cap_free [_rcv_pt_sel[i].sel - rcv_pt_base()] = USED_CAP;
cap_map()->remove(_rcv_pt_sel[i].sel - rcv_pt_base(), 0);
reinit = true; reinit = true;
} }
/* revoke received caps which are unused */ /* if old receive window was smaller, we need to re-init */
for (unsigned i = 0; i < MAX_CAP_ARGS; i++) { for (unsigned i = 0; !reinit && i < new_max; i++)
if (i < new_max && _rcv_pt_cap_free[i] == FREE_INVALID) if (_rcv_pt_cap_free[i] == FREE_INVALID)
reinit = true; reinit = true;
if (_rcv_pt_cap_free[i] == UNUSED_CAP)
Nova::revoke(Nova::Obj_crd(rcv_pt_base() + i, 0), true);
}
_rcv_pt_sel_cnt = 0; _rcv_pt_sel_cnt = 0;
_rcv_pt_sel_max = 0; _rcv_pt_sel_max = 0;
/* we can keep the cap selectors if none was used */ /* we can keep the cap selectors if none was used */
if (keep && !reinit) { if (keep && !reinit) {
/* free rest of indexes if new_max is smaller then last window */ for (unsigned i = 0; i < MAX_CAP_ARGS; i++) {
for (unsigned i = new_max; i < MAX_CAP_ARGS; i++) /* revoke received caps which are unused */
if (_rcv_pt_cap_free[i] == FREE_SEL) if (_rcv_pt_cap_free[i] == UNUSED_CAP)
cap_selector_allocator()->free(rcv_pt_base() + i, 0); Nova::revoke(Nova::Obj_crd(rcv_pt_base() + i, 0), true);
/* free rest of indexes if new_max is smaller then last window */
if (i >= new_max && _rcv_pt_cap_free[i] == FREE_SEL)
cap_map()->remove(rcv_pt_base() + i, 0, false);
}
return false; return false;
} }
/* keep used selectors, free up rest */ /* decrease ref count if valid selector */
for (unsigned i = 0; i < MAX_CAP_ARGS; i++) { for (unsigned i = 0; i < MAX_CAP_ARGS; i++)
if (_rcv_pt_cap_free[i] == UNUSED_CAP || if (_rcv_pt_cap_free[i] != FREE_INVALID)
_rcv_pt_cap_free[i] == FREE_SEL) cap_map()->remove(rcv_pt_base() + i, 0, _rcv_pt_cap_free[i] == FREE_SEL);
cap_selector_allocator()->free(rcv_pt_base() + i, 0);
}
return true; return true;
} }
@ -316,10 +318,9 @@ namespace Genode {
/* allocate receive window if necessary, otherwise use old one */ /* allocate receive window if necessary, otherwise use old one */
if (rcv_invalid() || rcv_cleanup(true, 1U << _rcv_wnd_log2)) if (rcv_invalid() || rcv_cleanup(true, 1U << _rcv_wnd_log2))
{ {
try { _rcv_pt_base = cap_map()->insert(_rcv_wnd_log2);
_rcv_pt_base = cap_selector_allocator()->alloc(_rcv_wnd_log2);
} catch (Bit_array_out_of_indexes) { if (_rcv_pt_base == INVALID_INDEX) {
_rcv_pt_base = INVALID_INDEX;
/* no mappings can be received */ /* no mappings can be received */
utcb->crd_rcv = Nova::Obj_crd(); utcb->crd_rcv = Nova::Obj_crd();
return false; return false;
@ -357,8 +358,6 @@ namespace Genode {
for (unsigned short i = 0; i < MAX_CAP_ARGS; i++) for (unsigned short i = 0; i < MAX_CAP_ARGS; i++)
_rcv_pt_cap_free [i] = (i >= max) ? FREE_INVALID : FREE_SEL; _rcv_pt_cap_free [i] = (i >= max) ? FREE_INVALID : FREE_SEL;
addr_t max = 1UL << utcb->crd_rcv.order();
for (unsigned i = 0; i < rcv_items; i++) { for (unsigned i = 0; i < rcv_items; i++) {
Utcb::Item * item = utcb->get_item(i); Utcb::Item * item = utcb->get_item(i);
if (!item) if (!item)

View File

@ -30,17 +30,13 @@ using namespace Nova;
void Ipc_ostream::_marshal_capability(Native_capability const &cap) void Ipc_ostream::_marshal_capability(Native_capability const &cap)
{ {
if (cap.valid()) _snd_msg->snd_append_pt_sel(cap);
_snd_msg->snd_append_pt_sel(cap.local_name(),
cap.dst().rights(),
cap.trans_map());
} }
void Ipc_istream::_unmarshal_capability(Native_capability &cap) void Ipc_istream::_unmarshal_capability(Native_capability &cap)
{ {
addr_t pt_sel = _rcv_msg->rcv_pt_sel(); _rcv_msg->rcv_pt_sel(cap);
cap = Native_capability(pt_sel);
} }