mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
sel4: IPC implementation
This commit is contained in:
parent
ff46d02c48
commit
6ffba0e473
@ -1,11 +1,11 @@
|
||||
/*
|
||||
* \brief seL4-specific layout of IPC message buffer
|
||||
* \brief IPC message buffer layout
|
||||
* \author Norman Feske
|
||||
* \date 2014-10-14
|
||||
* \date 2015-05-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
* Copyright (C) 2015 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.
|
||||
@ -14,99 +14,133 @@
|
||||
#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
|
||||
#define _INCLUDE__BASE__IPC_MSGBUF_H_
|
||||
|
||||
#include <base/native_types.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* IPC message buffer layout
|
||||
*/
|
||||
class Msgbuf_base
|
||||
{
|
||||
public:
|
||||
|
||||
enum { MAX_CAPS_PER_MSG = 8 };
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
* Capabilities to be transferred
|
||||
*/
|
||||
int _caps[MAX_CAPS_PER_MSG];
|
||||
Genode::size_t _used_caps;
|
||||
Genode::size_t _read_cap_index;
|
||||
|
||||
/**
|
||||
* Maximum size of plain-data message payload
|
||||
*/
|
||||
Genode::size_t _size;
|
||||
|
||||
/**
|
||||
* Actual size of plain-data message payload
|
||||
*/
|
||||
Genode::size_t _used_size;
|
||||
|
||||
char _msg_start[]; /* symbol marks start of message buffer data */
|
||||
|
||||
/*
|
||||
* No member variables are allowed beyond this point!
|
||||
*/
|
||||
|
||||
public:
|
||||
|
||||
char buf[];
|
||||
|
||||
Msgbuf_base() { reset_caps(); }
|
||||
|
||||
/**
|
||||
* Return size of message buffer
|
||||
*/
|
||||
inline Genode::size_t size() const { return _size; };
|
||||
|
||||
/**
|
||||
* Return address of message buffer
|
||||
*/
|
||||
inline void *addr() { return &_msg_start[0]; };
|
||||
|
||||
void reset_caps() { _used_caps = 0; _read_cap_index = 0; }
|
||||
|
||||
bool append_cap(int cap)
|
||||
{
|
||||
if (_used_caps == MAX_CAPS_PER_MSG)
|
||||
return false;
|
||||
|
||||
_caps[_used_caps++] = cap;
|
||||
return true;
|
||||
}
|
||||
|
||||
int read_cap()
|
||||
{
|
||||
if (_read_cap_index == _used_caps)
|
||||
return -1;
|
||||
|
||||
return _caps[_read_cap_index++];
|
||||
}
|
||||
|
||||
size_t used_caps() const { return _used_caps; }
|
||||
|
||||
int cap(unsigned index) const
|
||||
{
|
||||
return index < _used_caps ? _caps[index] : -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Pump up IPC message buffer to specified buffer size
|
||||
*/
|
||||
template <unsigned BUF_SIZE>
|
||||
class Msgbuf : public Msgbuf_base
|
||||
{
|
||||
public:
|
||||
|
||||
char buf[BUF_SIZE];
|
||||
|
||||
Msgbuf() { _size = BUF_SIZE; }
|
||||
};
|
||||
class Msgbuf_base;
|
||||
template <unsigned> struct Msgbuf;
|
||||
}
|
||||
|
||||
|
||||
class Genode::Msgbuf_base
|
||||
{
|
||||
public:
|
||||
|
||||
enum { MAX_CAPS_PER_MSG = 3 };
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
* Resolve ambiguity if the header is included from a libc-using
|
||||
* program.
|
||||
*/
|
||||
typedef Genode::size_t size_t;
|
||||
|
||||
/*
|
||||
* Capabilities to be transferred
|
||||
*/
|
||||
Native_capability _caps[MAX_CAPS_PER_MSG];
|
||||
size_t _used_caps = 0;
|
||||
size_t _read_cap_index = 0;
|
||||
|
||||
/**
|
||||
* Maximum size of plain-data message payload
|
||||
*/
|
||||
size_t const _size;
|
||||
|
||||
/**
|
||||
* Actual size of plain-data message payload
|
||||
*/
|
||||
size_t _used_size = 0;
|
||||
|
||||
char _msg_start[]; /* symbol marks start of message buffer data */
|
||||
|
||||
/*
|
||||
* No member variables are allowed beyond this point!
|
||||
*/
|
||||
|
||||
Msgbuf_base(size_t size) : _size(size) { }
|
||||
|
||||
public:
|
||||
|
||||
char buf[];
|
||||
|
||||
/**
|
||||
* Return size of message buffer
|
||||
*/
|
||||
size_t size() const { return _size; };
|
||||
|
||||
void reset_caps()
|
||||
{
|
||||
for (Genode::size_t i = 0; i < _used_caps; i++)
|
||||
_caps[i] = Native_capability();
|
||||
|
||||
_used_caps = 0;
|
||||
}
|
||||
|
||||
void reset_read_cap_index()
|
||||
{
|
||||
_read_cap_index = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return pointer to start of message-buffer content
|
||||
*/
|
||||
void const *data() const { return &_msg_start[0]; };
|
||||
void *data() { return &_msg_start[0]; };
|
||||
|
||||
/**
|
||||
* Exception type
|
||||
*/
|
||||
class Too_many_caps : public Exception { };
|
||||
|
||||
/**
|
||||
* Called from '_marshal_capability'
|
||||
*/
|
||||
void append_cap(Native_capability const &cap)
|
||||
{
|
||||
if (_used_caps == MAX_CAPS_PER_MSG)
|
||||
throw Too_many_caps();
|
||||
|
||||
_caps[_used_caps++] = cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from '_unmarshal_capability'
|
||||
*/
|
||||
Native_capability extract_cap()
|
||||
{
|
||||
if (_read_cap_index == _used_caps)
|
||||
return Native_capability();
|
||||
|
||||
return _caps[_read_cap_index++];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of marshalled capabilities
|
||||
*/
|
||||
size_t used_caps() const { return _used_caps; }
|
||||
|
||||
Native_capability &cap(unsigned index)
|
||||
{
|
||||
return _caps[index];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <unsigned BUF_SIZE>
|
||||
struct Genode::Msgbuf : Msgbuf_base
|
||||
{
|
||||
/**
|
||||
* Pump up IPC message buffer to specified buffer size
|
||||
*
|
||||
* XXX remove padding of 16
|
||||
*/
|
||||
char buf[BUF_SIZE + 16];
|
||||
|
||||
Msgbuf() : Msgbuf_base(BUF_SIZE) { }
|
||||
};
|
||||
|
||||
|
||||
#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
|
||||
|
35
repos/base-sel4/src/base/env/capability_space.cc
vendored
35
repos/base-sel4/src/base/env/capability_space.cc
vendored
@ -82,3 +82,38 @@ Rpc_obj_key Capability_space::rpc_obj_key(Native_capability::Data const &data)
|
||||
return local_capability_space().rpc_obj_key(data);
|
||||
}
|
||||
|
||||
|
||||
Capability_space::Ipc_cap_data Capability_space::ipc_cap_data(Native_capability const &cap)
|
||||
{
|
||||
return local_capability_space().ipc_cap_data(*cap.data());
|
||||
}
|
||||
|
||||
|
||||
Native_capability Capability_space::lookup(Rpc_obj_key rpc_obj_key)
|
||||
{
|
||||
Native_capability::Data *data = local_capability_space().lookup(rpc_obj_key);
|
||||
|
||||
return data ? Native_capability(*data) : Native_capability();
|
||||
}
|
||||
|
||||
|
||||
unsigned Capability_space::alloc_rcv_sel()
|
||||
{
|
||||
PDBG("not implemented");
|
||||
for (;;);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Capability_space::reset_sel(unsigned sel)
|
||||
{
|
||||
PDBG("not implemented");
|
||||
}
|
||||
|
||||
|
||||
Native_capability Capability_space::import(Ipc_cap_data ipc_cap_data)
|
||||
{
|
||||
PDBG("not implemented");
|
||||
|
||||
return Native_capability();
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <internal/capability_space.h>
|
||||
#include <internal/assert.h>
|
||||
|
||||
namespace Genode { template <unsigned, typename> class Capability_space_sel4; }
|
||||
namespace Genode { template <unsigned, unsigned, typename> class Capability_space_sel4; }
|
||||
|
||||
|
||||
/**
|
||||
@ -37,6 +37,9 @@ namespace Genode { namespace Capability_space {
|
||||
{
|
||||
Rpc_obj_key rpc_obj_key;
|
||||
unsigned sel;
|
||||
|
||||
Ipc_cap_data(Rpc_obj_key rpc_obj_key, unsigned sel)
|
||||
: rpc_obj_key(rpc_obj_key), sel(sel) { }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -49,6 +52,23 @@ namespace Genode { namespace Capability_space {
|
||||
*/
|
||||
unsigned alloc_rcv_sel();
|
||||
|
||||
/**
|
||||
* Delete selector but retain allocation
|
||||
*
|
||||
* This function is used when a delegated capability selector is replaced
|
||||
* with an already known selector. The delegated selector is discarded.
|
||||
*/
|
||||
void reset_sel(unsigned sel);
|
||||
|
||||
/**
|
||||
* Lookup capability by its RPC object key
|
||||
*/
|
||||
Native_capability lookup(Rpc_obj_key key);
|
||||
|
||||
/**
|
||||
* Import capability into the component's capability space
|
||||
*/
|
||||
Native_capability import(Ipc_cap_data ipc_cap_data);
|
||||
} }
|
||||
|
||||
|
||||
@ -65,7 +85,7 @@ namespace Genode { namespace Capability_space {
|
||||
* freeing capabilities allocated from another component. This information
|
||||
* is part of the core-specific 'Native_capability::Data' structure.
|
||||
*/
|
||||
template <unsigned NUM_CAPS, typename CAP_DATA>
|
||||
template <unsigned NUM_CAPS, unsigned _NUM_CORE_MANAGED_CAPS, typename CAP_DATA>
|
||||
class Genode::Capability_space_sel4
|
||||
{
|
||||
public:
|
||||
@ -73,10 +93,10 @@ class Genode::Capability_space_sel4
|
||||
/*
|
||||
* The capability space consists of two parts. The lower part is
|
||||
* populated with statically-defined capabilities whereas the upper
|
||||
* part is dynamically managed by the component. The 'NUM_STATIC_CAPS'
|
||||
* defines the size of the first part.
|
||||
* part is dynamically managed by the component. The
|
||||
* 'NUM_CORE_MANAGED_CAPS' defines the size of the first part.
|
||||
*/
|
||||
enum { NUM_STATIC_CAPS = 1024 };
|
||||
enum { NUM_CORE_MANAGED_CAPS = _NUM_CORE_MANAGED_CAPS };
|
||||
|
||||
private:
|
||||
|
||||
@ -111,7 +131,7 @@ class Genode::Capability_space_sel4
|
||||
|
||||
Tree_managed_data _caps_data[NUM_CAPS];
|
||||
Avl_tree<Tree_managed_data> _tree;
|
||||
Lock _lock;
|
||||
Lock mutable _lock;
|
||||
|
||||
/**
|
||||
* Calculate index into _caps_data for capability data object
|
||||
@ -125,9 +145,9 @@ class Genode::Capability_space_sel4
|
||||
/**
|
||||
* Return true if capability is locally managed by the component
|
||||
*/
|
||||
bool _is_dynamic(Data &data) const
|
||||
bool _is_core_managed(Data &data) const
|
||||
{
|
||||
return _index(data) >= NUM_STATIC_CAPS;
|
||||
return _index(data) < NUM_CORE_MANAGED_CAPS;
|
||||
}
|
||||
|
||||
void _remove(Native_capability::Data &data)
|
||||
@ -180,7 +200,7 @@ class Genode::Capability_space_sel4
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (_is_dynamic(data) && !data.dec_ref()) {
|
||||
if (!_is_core_managed(data) && !data.dec_ref()) {
|
||||
PDBG("remove cap");
|
||||
_remove(data);
|
||||
}
|
||||
@ -190,8 +210,9 @@ class Genode::Capability_space_sel4
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (_is_dynamic(data))
|
||||
if (!_is_core_managed(data)) {
|
||||
data.inc_ref();
|
||||
}
|
||||
}
|
||||
|
||||
Rpc_obj_key rpc_obj_key(Data const &data) const
|
||||
@ -203,6 +224,16 @@ class Genode::Capability_space_sel4
|
||||
{
|
||||
return { rpc_obj_key(data), sel(data) };
|
||||
}
|
||||
|
||||
Data *lookup(Rpc_obj_key key) const
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (!_tree.first())
|
||||
return nullptr;
|
||||
|
||||
return _tree.first()->find_by_key(key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -19,7 +19,8 @@
|
||||
#include <util/misc_math.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <internal/capability_space.h>
|
||||
#include <internal/capability_space_sel4.h>
|
||||
#include <internal/kernel_debugger.h>
|
||||
|
||||
/* seL4 includes */
|
||||
#include <sel4/interfaces/sel4_client.h>
|
||||
@ -27,19 +28,216 @@
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/**
|
||||
* Message-register definitions
|
||||
*/
|
||||
enum {
|
||||
MR_IDX_NUM_CAPS = 0,
|
||||
MR_IDX_CAPS = 1,
|
||||
MR_IDX_DATA = MR_IDX_CAPS + Msgbuf_base::MAX_CAPS_PER_MSG,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Convert Genode::Msgbuf_base content into seL4 message
|
||||
*
|
||||
* \param msg source message buffer
|
||||
* \param data_length size of message data in bytes
|
||||
*/
|
||||
static seL4_MessageInfo_t new_seL4_message(Msgbuf_base &msg,
|
||||
size_t const data_length)
|
||||
{
|
||||
/*
|
||||
* Supply capabilities to kernel IPC message
|
||||
*/
|
||||
seL4_SetMR(MR_IDX_NUM_CAPS, msg.used_caps());
|
||||
size_t sel4_sel_cnt = 0;
|
||||
for (size_t i = 0; i < msg.used_caps(); i++) {
|
||||
|
||||
Native_capability &cap = msg.cap(i);
|
||||
|
||||
if (cap.valid()) {
|
||||
Capability_space::Ipc_cap_data const ipc_cap_data =
|
||||
Capability_space::ipc_cap_data(cap);
|
||||
|
||||
seL4_SetMR(MR_IDX_CAPS + i, ipc_cap_data.rpc_obj_key.value());
|
||||
seL4_SetCap(sel4_sel_cnt++, ipc_cap_data.sel);
|
||||
} else {
|
||||
seL4_SetMR(MR_IDX_CAPS + i, Rpc_obj_key::INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pad unused capability slots with invalid capabilities to avoid
|
||||
* leakage of any information that happens to be in the IPC buffer.
|
||||
*/
|
||||
for (size_t i = msg.used_caps(); i < Msgbuf_base::MAX_CAPS_PER_MSG; i++)
|
||||
seL4_SetMR(MR_IDX_CAPS + i, Rpc_obj_key::INVALID);
|
||||
|
||||
/*
|
||||
* Allocate and define receive selector
|
||||
*/
|
||||
Native_thread &thread = Thread_base::myself()->tid();
|
||||
|
||||
if (!thread.rcv_sel)
|
||||
thread.rcv_sel = Capability_space::alloc_rcv_sel();
|
||||
|
||||
/*
|
||||
* Supply data payload
|
||||
*/
|
||||
size_t const num_data_mwords =
|
||||
align_natural(data_length) / sizeof(umword_t);
|
||||
|
||||
umword_t const *src = (umword_t const *)msg.data();
|
||||
for (size_t i = 0; i < num_data_mwords; i++)
|
||||
seL4_SetMR(MR_IDX_DATA + i, *src++);
|
||||
|
||||
seL4_MessageInfo_t const msg_info =
|
||||
seL4_MessageInfo_new(0, 0, sel4_sel_cnt,
|
||||
MR_IDX_DATA + num_data_mwords);
|
||||
return msg_info;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert seL4 message into Genode::Msgbuf_base
|
||||
*/
|
||||
static void decode_seL4_message(umword_t badge,
|
||||
seL4_MessageInfo_t const &msg_info,
|
||||
Msgbuf_base &dst_msg)
|
||||
{
|
||||
/*
|
||||
* Extract Genode capabilities from seL4 IPC message
|
||||
*/
|
||||
dst_msg.reset_caps();
|
||||
size_t const num_caps = seL4_GetMR(MR_IDX_NUM_CAPS);
|
||||
size_t curr_sel4_cap_idx = 0;
|
||||
|
||||
for (size_t i = 0; i < num_caps; i++) {
|
||||
|
||||
Rpc_obj_key const rpc_obj_key(seL4_GetMR(MR_IDX_CAPS + i));
|
||||
|
||||
if (!rpc_obj_key.valid()) {
|
||||
dst_msg.append_cap(Native_capability());
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* RPC object key as contained in the message data is valid.
|
||||
*/
|
||||
|
||||
unsigned const unwrapped =
|
||||
seL4_MessageInfo_get_capsUnwrapped(msg_info) &
|
||||
(1 << curr_sel4_cap_idx);
|
||||
|
||||
/* distinguish unwrapped from delegated cap */
|
||||
if (unwrapped) {
|
||||
|
||||
/*
|
||||
* Received unwrapped capability
|
||||
*
|
||||
* This means that the capability argument belongs to our endpoint.
|
||||
* So it is already present within the capability space.
|
||||
*/
|
||||
|
||||
unsigned const arg_badge =
|
||||
seL4_CapData_Badge_get_Badge(seL4_GetBadge(curr_sel4_cap_idx));
|
||||
|
||||
if (arg_badge != rpc_obj_key.value()) {
|
||||
PWRN("argument badge (%d) != RPC object key (%d)",
|
||||
arg_badge, rpc_obj_key.value());
|
||||
}
|
||||
|
||||
Native_capability arg_cap = Capability_space::lookup(rpc_obj_key);
|
||||
|
||||
dst_msg.append_cap(arg_cap);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Received delegated capability
|
||||
*
|
||||
* We have either received a capability that is foreign to us,
|
||||
* or an alias for a capability that we already posses. The
|
||||
* latter can happen in the following circumstances:
|
||||
*
|
||||
* - We forwarded a selector that was created by another
|
||||
* component. We cannot re-identify such a capability when
|
||||
* handed back because seL4's badge mechanism works only for
|
||||
* capabilities belonging to the IPC destination endpoint.
|
||||
*
|
||||
* - We received a selector on the IPC reply path, where seL4's
|
||||
* badge mechanism is not in effect.
|
||||
*/
|
||||
|
||||
bool const delegated = seL4_MessageInfo_get_extraCaps(msg_info);
|
||||
|
||||
ASSERT(delegated);
|
||||
|
||||
Native_thread &thread = Thread_base::myself()->tid();
|
||||
|
||||
Native_capability arg_cap = Capability_space::lookup(rpc_obj_key);
|
||||
|
||||
if (arg_cap.valid()) {
|
||||
|
||||
/*
|
||||
* Discard the received selector and keep using the already
|
||||
* present one.
|
||||
*
|
||||
* XXX We'd need to find out if both the received and the
|
||||
* looked-up selector refer to the same endpoint.
|
||||
* Unfortunaltely, seL4 lacks such a comparison operation.
|
||||
*/
|
||||
|
||||
Capability_space::reset_sel(thread.rcv_sel);
|
||||
|
||||
dst_msg.append_cap(arg_cap);
|
||||
|
||||
} else {
|
||||
|
||||
Capability_space::Ipc_cap_data const
|
||||
ipc_cap_data(rpc_obj_key, thread.rcv_sel);
|
||||
|
||||
dst_msg.append_cap(Capability_space::import(ipc_cap_data));
|
||||
|
||||
/*
|
||||
* Since we keep using the received selector, we need to
|
||||
* allocate a fresh one for the next incoming delegation.
|
||||
*/
|
||||
thread.rcv_sel = Capability_space::alloc_rcv_sel();
|
||||
}
|
||||
}
|
||||
curr_sel4_cap_idx++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract message data payload
|
||||
*/
|
||||
|
||||
umword_t *dst = (umword_t *)dst_msg.data();
|
||||
for (size_t i = 0; i < seL4_MessageInfo_get_length(msg_info); i++)
|
||||
*dst++ = seL4_GetMR(MR_IDX_DATA + i);
|
||||
|
||||
/*
|
||||
* Store RPC object key of invoked object to be picked up by server.cc
|
||||
*/
|
||||
*(long *)dst_msg.data() = badge;
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
** IPC marshalling support **
|
||||
*****************************/
|
||||
|
||||
void Ipc_ostream::_marshal_capability(Native_capability const &cap)
|
||||
{
|
||||
PDBG("not implemented");
|
||||
_snd_msg->append_cap(cap);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_istream::_unmarshal_capability(Native_capability &cap)
|
||||
{
|
||||
PDBG("not implemented");
|
||||
cap = _rcv_msg->extract_cap();
|
||||
}
|
||||
|
||||
|
||||
@ -49,16 +247,15 @@ void Ipc_istream::_unmarshal_capability(Native_capability &cap)
|
||||
|
||||
void Ipc_ostream::_send()
|
||||
{
|
||||
PDBG("not implemented");
|
||||
ASSERT(false);
|
||||
|
||||
_write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
|
||||
:
|
||||
Ipc_marshaller((char *)snd_msg->addr(), snd_msg->size()),
|
||||
Ipc_marshaller((char *)snd_msg->data(), snd_msg->size()),
|
||||
_snd_msg(snd_msg), _dst(dst)
|
||||
{
|
||||
_write_offset = sizeof(umword_t);
|
||||
@ -71,19 +268,13 @@ Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
|
||||
|
||||
void Ipc_istream::_wait()
|
||||
{
|
||||
PDBG("not implemented");
|
||||
|
||||
for (;;)
|
||||
seL4_Yield();
|
||||
|
||||
|
||||
_read_offset = sizeof(umword_t);
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
|
||||
:
|
||||
Ipc_unmarshaller((char *)rcv_msg->addr(), rcv_msg->size()),
|
||||
Ipc_unmarshaller((char *)rcv_msg->data(), rcv_msg->size()),
|
||||
_rcv_msg(rcv_msg)
|
||||
{
|
||||
_read_offset = sizeof(umword_t);
|
||||
@ -99,7 +290,20 @@ Ipc_istream::~Ipc_istream() { }
|
||||
|
||||
void Ipc_client::_call()
|
||||
{
|
||||
PDBG("not implemented");
|
||||
if (!Ipc_ostream::_dst.valid()) {
|
||||
PERR("Trying to invoke an invalid capability, stop.");
|
||||
kernel_debugger_panic("IPC destination is invalid");
|
||||
}
|
||||
|
||||
seL4_MessageInfo_t const request_msg_info =
|
||||
new_seL4_message(*_snd_msg, _write_offset);
|
||||
|
||||
unsigned const dst_sel = Capability_space::ipc_cap_data(_dst).sel;
|
||||
|
||||
seL4_MessageInfo_t const reply_msg_info =
|
||||
seL4_Call(dst_sel, request_msg_info);
|
||||
|
||||
decode_seL4_message(0, reply_msg_info, *_rcv_msg);
|
||||
|
||||
_write_offset = _read_offset = sizeof(umword_t);
|
||||
}
|
||||
@ -125,29 +329,19 @@ void Ipc_server::_prepare_next_reply_wait()
|
||||
|
||||
/* receive buffer offset */
|
||||
_read_offset = sizeof(umword_t);
|
||||
|
||||
_rcv_msg->reset_read_cap_index();
|
||||
_snd_msg->reset_caps();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_wait()
|
||||
{
|
||||
/* wait for new server request */
|
||||
PDBG("called, do seL4_Wait");
|
||||
|
||||
seL4_Word badge = Rpc_obj_key::INVALID;
|
||||
seL4_MessageInfo_t const msg_info =
|
||||
seL4_Wait(Thread_base::myself()->tid().ep_sel, nullptr);
|
||||
PDBG("returned from seL4_Wait, call seL4_Reply");
|
||||
seL4_Wait(Thread_base::myself()->tid().ep_sel, &badge);
|
||||
|
||||
PDBG("msg_info: got unwrapped %d", seL4_MessageInfo_get_capsUnwrapped(msg_info));
|
||||
PDBG(" got extra caps %d", seL4_MessageInfo_get_extraCaps(msg_info));
|
||||
PDBG(" label %d", seL4_MessageInfo_get_label(msg_info));
|
||||
|
||||
if (seL4_MessageInfo_get_capsUnwrapped(msg_info)) {
|
||||
PDBG(" badge %d", seL4_CapData_Badge_get_Badge(seL4_GetBadge(0)));
|
||||
}
|
||||
|
||||
for (;;)
|
||||
seL4_Yield();
|
||||
// try { Ipc_istream::_wait(); } catch (Blocking_canceled) { }
|
||||
decode_seL4_message(badge, msg_info, *_rcv_msg);
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
@ -155,18 +349,30 @@ void Ipc_server::_wait()
|
||||
|
||||
void Ipc_server::_reply()
|
||||
{
|
||||
try { _send(); } catch (Ipc_error) { }
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait()
|
||||
{
|
||||
if (_reply_needed)
|
||||
_reply();
|
||||
if (!_reply_needed) {
|
||||
|
||||
_wait();
|
||||
_wait();
|
||||
|
||||
} else {
|
||||
|
||||
seL4_Word badge = Rpc_obj_key::INVALID;
|
||||
seL4_MessageInfo_t const reply_msg_info =
|
||||
new_seL4_message(*_snd_msg, _write_offset);
|
||||
|
||||
seL4_MessageInfo_t const request_msg_info =
|
||||
seL4_ReplyWait(Thread_base::myself()->tid().ep_sel,
|
||||
reply_msg_info, &badge);
|
||||
|
||||
decode_seL4_message(badge, request_msg_info, *_rcv_msg);
|
||||
}
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
@ -176,5 +382,6 @@ Ipc_server::Ipc_server(Msgbuf_base *snd_msg,
|
||||
Ipc_istream(rcv_msg), Ipc_ostream(Native_capability(), snd_msg),
|
||||
_reply_needed(false)
|
||||
{
|
||||
*static_cast<Native_capability *>(this) = Native_capability(Capability_space::create_ep_cap(*Thread_base::myself()));
|
||||
*static_cast<Native_capability *>(this) =
|
||||
Native_capability(Capability_space::create_ep_cap(*Thread_base::myself()));
|
||||
}
|
||||
|
@ -64,9 +64,6 @@ void Rpc_entrypoint::entry()
|
||||
/* set default return value */
|
||||
srv.ret(Ipc_client::ERR_INVALID_OBJECT);
|
||||
|
||||
/* check whether capability's label fits global id */
|
||||
PDBG("not implemented");
|
||||
|
||||
/* atomically lookup and lock referenced object */
|
||||
Object_pool<Rpc_object_base>::Guard curr_obj(lookup_and_lock(srv.badge()));
|
||||
if (!curr_obj)
|
||||
|
@ -61,7 +61,7 @@ namespace {
|
||||
|
||||
struct Local_capability_space
|
||||
:
|
||||
Capability_space_sel4<1UL << Core_cspace::NUM_CORE_SEL_LOG2,
|
||||
Capability_space_sel4<1UL << Core_cspace::NUM_CORE_SEL_LOG2, 0UL,
|
||||
Native_capability::Data>
|
||||
{ };
|
||||
|
||||
@ -163,7 +163,34 @@ Capability_space::Ipc_cap_data Capability_space::ipc_cap_data(Native_capability
|
||||
}
|
||||
|
||||
|
||||
Native_capability Capability_space::lookup(Rpc_obj_key rpc_obj_key)
|
||||
{
|
||||
Native_capability::Data *data = local_capability_space().lookup(rpc_obj_key);
|
||||
|
||||
return data ? Native_capability(*data) : Native_capability();
|
||||
}
|
||||
|
||||
|
||||
unsigned Capability_space::alloc_rcv_sel()
|
||||
{
|
||||
return platform_specific()->alloc_core_rcv_sel();
|
||||
}
|
||||
|
||||
|
||||
void Capability_space::reset_sel(unsigned sel)
|
||||
{
|
||||
return platform_specific()->reset_sel(sel);
|
||||
}
|
||||
|
||||
|
||||
Native_capability Capability_space::import(Ipc_cap_data ipc_cap_data)
|
||||
{
|
||||
/* imported capabilities are not associated with a CAP session */
|
||||
Cap_session const *cap_session = nullptr;
|
||||
|
||||
Native_capability::Data &data =
|
||||
local_capability_space().create_capability(ipc_cap_data.sel, cap_session,
|
||||
ipc_cap_data.rpc_obj_key);
|
||||
|
||||
return Native_capability(data);
|
||||
}
|
||||
|
@ -138,6 +138,7 @@ class Genode::Platform : public Platform_generic
|
||||
|
||||
unsigned alloc_core_sel();
|
||||
unsigned alloc_core_rcv_sel();
|
||||
void reset_sel(unsigned sel);
|
||||
void free_core_sel(unsigned sel);
|
||||
|
||||
void wait_for_exit();
|
||||
|
@ -272,12 +272,18 @@ unsigned Platform::alloc_core_rcv_sel()
|
||||
{
|
||||
unsigned rcv_sel = alloc_core_sel();
|
||||
|
||||
seL4_SetCapReceivePath(_core_cnode.sel(), rcv_sel, 0);
|
||||
seL4_SetCapReceivePath(_core_cnode.sel(), rcv_sel, _core_cnode.size_log2());
|
||||
|
||||
return rcv_sel;
|
||||
}
|
||||
|
||||
|
||||
void Platform::reset_sel(unsigned sel)
|
||||
{
|
||||
_core_cnode.remove(sel);
|
||||
}
|
||||
|
||||
|
||||
void Platform::free_core_sel(unsigned sel)
|
||||
{
|
||||
Lock::Guard guard(_core_sel_alloc_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user