2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief IPC implementation for Fiasco
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2006-06-13
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2006-2017 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
|
|
|
|
2016-03-11 21:47:12 +01:00
|
|
|
/* Genode includes */
|
2016-06-15 15:04:54 +02:00
|
|
|
#include <base/log.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <base/ipc.h>
|
|
|
|
#include <base/blocking.h>
|
|
|
|
|
2016-03-11 21:47:12 +01:00
|
|
|
/* base-internal includes */
|
2016-03-15 20:01:59 +01:00
|
|
|
#include <base/internal/ipc_server.h>
|
2016-06-15 15:04:54 +02:00
|
|
|
#include <base/internal/capability_space_tpl.h>
|
2016-03-11 21:47:12 +01:00
|
|
|
|
|
|
|
/* Fiasco includes */
|
2011-12-22 16:19:25 +01:00
|
|
|
namespace Fiasco {
|
|
|
|
#include <l4/sys/ipc.h>
|
|
|
|
#include <l4/sys/syscalls.h>
|
|
|
|
}
|
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
using namespace Genode;
|
|
|
|
|
2016-03-15 20:01:59 +01:00
|
|
|
|
|
|
|
class Msg_header
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
/* kernel-defined message header */
|
|
|
|
Fiasco::l4_fpage_t rcv_fpage; /* unused */
|
|
|
|
Fiasco::l4_msgdope_t size_dope;
|
|
|
|
Fiasco::l4_msgdope_t send_dope;
|
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
public:
|
|
|
|
|
2016-03-15 20:01:59 +01:00
|
|
|
/*
|
2016-03-18 22:53:25 +01:00
|
|
|
* First two data words of message, used to transfer the local name of
|
|
|
|
* the invoked object (when a client calls a server) or the exception
|
|
|
|
* code (when the server replies), and the number of capability
|
|
|
|
* arguments. The kernel does not fetch these data words from memory
|
|
|
|
* but transfers them via the short-IPC registers.
|
2016-03-15 20:01:59 +01:00
|
|
|
*/
|
|
|
|
Fiasco::l4_umword_t protocol_word;
|
2016-03-18 22:53:25 +01:00
|
|
|
Fiasco::l4_umword_t num_caps;
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
enum { MAX_CAPS_PER_MSG = Msgbuf_base::MAX_CAPS_PER_MSG };
|
|
|
|
|
|
|
|
Fiasco::l4_threadid_t _cap_tid [MAX_CAPS_PER_MSG];
|
|
|
|
unsigned long _cap_local_name [MAX_CAPS_PER_MSG];
|
|
|
|
|
|
|
|
size_t _num_msg_words(size_t num_data_words) const
|
|
|
|
{
|
|
|
|
size_t const caps_size = sizeof(_cap_tid) + sizeof(_cap_local_name);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Account for the transfer of the protocol word, capability count,
|
|
|
|
* and capability arguments in front of the payload.
|
|
|
|
*/
|
|
|
|
return 2 + caps_size/sizeof(Fiasco::l4_umword_t) + num_data_words;
|
|
|
|
}
|
2016-03-15 20:01:59 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
void *msg_start() { return &rcv_fpage; }
|
|
|
|
|
|
|
|
/**
|
2016-03-18 22:53:25 +01:00
|
|
|
* Load header fields according to send-message buffer
|
2016-03-15 20:01:59 +01:00
|
|
|
*/
|
2016-03-18 22:53:25 +01:00
|
|
|
void prepare_snd_msg(unsigned long protocol, Msgbuf_base const &snd_msg)
|
2016-03-15 20:01:59 +01:00
|
|
|
{
|
|
|
|
using namespace Fiasco;
|
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
protocol_word = protocol;
|
|
|
|
num_caps = min((unsigned)MAX_CAPS_PER_MSG, snd_msg.used_caps());
|
|
|
|
|
|
|
|
size_t const snd_words = snd_msg.data_size()/sizeof(l4_umword_t);
|
|
|
|
send_dope = L4_IPC_DOPE(_num_msg_words(snd_words), 0);
|
|
|
|
|
|
|
|
/* reset _cap_tid and _cap_local_name */
|
|
|
|
for (unsigned i = 0; i < MAX_CAPS_PER_MSG; i++) {
|
|
|
|
_cap_tid[i] = L4_INVALID_ID;
|
|
|
|
_cap_local_name[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < num_caps; i++) {
|
|
|
|
Native_capability const &cap = snd_msg.cap(i);
|
2016-06-15 15:04:54 +02:00
|
|
|
|
|
|
|
if (cap.valid()) {
|
|
|
|
Capability_space::Ipc_cap_data const cap_data =
|
|
|
|
Capability_space::ipc_cap_data(snd_msg.cap(i));
|
|
|
|
|
|
|
|
_cap_tid[i] = cap_data.dst;
|
|
|
|
_cap_local_name[i] = cap_data.rpc_obj_key.value();
|
|
|
|
}
|
2016-03-18 22:53:25 +01:00
|
|
|
}
|
2016-03-15 20:01:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-03-18 22:53:25 +01:00
|
|
|
* Prepare header for receiving a message
|
2016-03-15 20:01:59 +01:00
|
|
|
*/
|
2016-03-18 22:53:25 +01:00
|
|
|
void prepare_rcv_msg(Msgbuf_base const &rcv_msg)
|
2016-03-15 20:01:59 +01:00
|
|
|
{
|
|
|
|
using namespace Fiasco;
|
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
size_t const rcv_max_words = rcv_msg.capacity()/sizeof(l4_umword_t);
|
|
|
|
|
|
|
|
size_dope = L4_IPC_DOPE(_num_msg_words(rcv_max_words), 0);
|
2016-03-15 20:01:59 +01:00
|
|
|
}
|
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
/**
|
|
|
|
* Copy received capability arguments into receive message buffer
|
|
|
|
*/
|
|
|
|
void extract_caps(Msgbuf_base &rcv_msg) const
|
2016-03-15 20:01:59 +01:00
|
|
|
{
|
2016-06-15 15:04:54 +02:00
|
|
|
for (unsigned i = 0; i < min((unsigned)MAX_CAPS_PER_MSG, num_caps); i++) {
|
|
|
|
|
|
|
|
Rpc_obj_key const rpc_obj_key(_cap_local_name[i]);
|
|
|
|
bool const cap_valid = !Fiasco::l4_is_invalid_id(_cap_tid[i]);
|
|
|
|
|
|
|
|
Native_capability cap;
|
|
|
|
if (cap_valid) {
|
|
|
|
cap = Capability_space::lookup(rpc_obj_key);
|
|
|
|
if (!cap.valid())
|
|
|
|
cap = Capability_space::import(_cap_tid[i], rpc_obj_key);
|
|
|
|
}
|
|
|
|
|
|
|
|
rcv_msg.insert(cap);
|
|
|
|
}
|
2016-03-15 20:01:59 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
/****************
|
2016-03-15 20:01:59 +01:00
|
|
|
** IPC client **
|
2011-12-22 16:19:25 +01:00
|
|
|
****************/
|
|
|
|
|
2016-03-15 20:01:59 +01:00
|
|
|
Rpc_exception_code Genode::ipc_call(Native_capability dst,
|
|
|
|
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
|
|
|
|
size_t)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
using namespace Fiasco;
|
|
|
|
|
2016-06-15 15:04:54 +02:00
|
|
|
Capability_space::Ipc_cap_data const dst_data =
|
|
|
|
Capability_space::ipc_cap_data(dst);
|
|
|
|
|
2016-03-15 20:01:59 +01:00
|
|
|
Msg_header &snd_header = snd_msg.header<Msg_header>();
|
2016-06-15 15:04:54 +02:00
|
|
|
snd_header.prepare_snd_msg(dst_data.rpc_obj_key.value(), snd_msg);
|
2016-03-15 20:01:59 +01:00
|
|
|
|
|
|
|
Msg_header &rcv_header = rcv_msg.header<Msg_header>();
|
2016-03-18 22:53:25 +01:00
|
|
|
rcv_header.prepare_rcv_msg(rcv_msg);
|
2016-03-15 20:01:59 +01:00
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
l4_msgdope_t ipc_result;
|
2016-06-15 15:04:54 +02:00
|
|
|
l4_ipc_call(dst_data.dst,
|
2016-03-18 22:53:25 +01:00
|
|
|
snd_header.msg_start(),
|
|
|
|
snd_header.protocol_word,
|
|
|
|
snd_header.num_caps,
|
2016-03-15 20:01:59 +01:00
|
|
|
rcv_header.msg_start(),
|
2016-03-18 22:53:25 +01:00
|
|
|
&rcv_header.protocol_word,
|
|
|
|
&rcv_header.num_caps,
|
2011-12-22 16:19:25 +01:00
|
|
|
L4_IPC_NEVER, &ipc_result);
|
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
rcv_header.extract_caps(rcv_msg);
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
if (L4_IPC_IS_ERROR(ipc_result)) {
|
|
|
|
|
|
|
|
if (L4_IPC_ERROR(ipc_result) == L4_IPC_RECANCELED)
|
|
|
|
throw Genode::Blocking_canceled();
|
|
|
|
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
error("ipc_call error ", Hex(L4_IPC_ERROR(ipc_result)));
|
2011-12-22 16:19:25 +01:00
|
|
|
throw Genode::Ipc_error();
|
|
|
|
}
|
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
return Rpc_exception_code(rcv_header.protocol_word);
|
2016-03-13 22:55:48 +01:00
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
|
|
|
|
/****************
|
2016-03-18 22:53:25 +01:00
|
|
|
** IPC server **
|
2011-12-22 16:19:25 +01:00
|
|
|
****************/
|
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc,
|
|
|
|
Msgbuf_base &snd_msg)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
using namespace Fiasco;
|
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
Msg_header &snd_header = snd_msg.header<Msg_header>();
|
|
|
|
snd_header.prepare_snd_msg(exc.value, snd_msg);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
l4_msgdope_t result;
|
2016-06-15 15:04:54 +02:00
|
|
|
l4_ipc_send(Capability_space::ipc_cap_data(caller).dst,
|
|
|
|
snd_header.msg_start(),
|
2016-03-18 22:53:25 +01:00
|
|
|
snd_header.protocol_word,
|
|
|
|
snd_header.num_caps,
|
2011-12-22 16:19:25 +01:00
|
|
|
L4_IPC_SEND_TIMEOUT_0, &result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-04-21 16:41:13 +02:00
|
|
|
Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
|
|
|
|
Rpc_exception_code exc,
|
|
|
|
Msgbuf_base &reply_msg,
|
|
|
|
Msgbuf_base &request_msg)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
using namespace Fiasco;
|
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
l4_msgdope_t ipc_result;
|
|
|
|
|
|
|
|
bool need_to_wait = true;
|
|
|
|
|
|
|
|
Msg_header &snd_header = reply_msg.header<Msg_header>();
|
|
|
|
snd_header.prepare_snd_msg(exc.value, reply_msg);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
request_msg.reset();
|
|
|
|
Msg_header &rcv_header = request_msg.header<Msg_header>();
|
|
|
|
rcv_header.prepare_rcv_msg(request_msg);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
l4_threadid_t caller = L4_INVALID_ID;
|
2016-03-15 20:01:59 +01:00
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
if (last_caller.valid()) {
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/*
|
2016-03-15 20:01:59 +01:00
|
|
|
* Use short IPC for reply if possible. This is the common case of
|
|
|
|
* returning an integer as RPC result.
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
2016-06-15 15:04:54 +02:00
|
|
|
l4_ipc_reply_and_wait(Capability_space::ipc_cap_data(last_caller).dst,
|
|
|
|
snd_header.msg_start(),
|
2016-03-18 22:53:25 +01:00
|
|
|
snd_header.protocol_word,
|
|
|
|
snd_header.num_caps,
|
|
|
|
&caller, rcv_header.msg_start(),
|
|
|
|
&rcv_header.protocol_word,
|
|
|
|
&rcv_header.num_caps,
|
|
|
|
L4_IPC_SEND_TIMEOUT_0, &ipc_result);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
/*
|
|
|
|
* The error condition could be a message cut (which we want to ignore
|
|
|
|
* on the server side) or a reply failure (for example, if the caller
|
|
|
|
* went dead during the call. In both cases, we do not reflect the
|
|
|
|
* error condition to the user but want to wait for the next proper
|
|
|
|
* incoming message.
|
|
|
|
*/
|
2011-12-22 16:19:25 +01:00
|
|
|
if (L4_IPC_IS_ERROR(ipc_result)) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
error("ipc_reply_and_wait error ", Hex(L4_IPC_ERROR(ipc_result)));
|
2016-03-18 22:53:25 +01:00
|
|
|
} else {
|
|
|
|
need_to_wait = false;
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
2016-03-15 20:01:59 +01:00
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-03-18 22:53:25 +01:00
|
|
|
while (need_to_wait) {
|
|
|
|
|
|
|
|
l4_ipc_wait(&caller, rcv_header.msg_start(),
|
|
|
|
&rcv_header.protocol_word,
|
|
|
|
&rcv_header.num_caps,
|
|
|
|
L4_IPC_NEVER, &ipc_result);
|
|
|
|
|
|
|
|
if (L4_IPC_IS_ERROR(ipc_result)) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
error("ipc_wait error ", Hex(L4_IPC_ERROR(ipc_result)));
|
2016-03-18 22:53:25 +01:00
|
|
|
} else {
|
|
|
|
need_to_wait = false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
rcv_header.extract_caps(request_msg);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-06-15 15:04:54 +02:00
|
|
|
return Rpc_request(Capability_space::import(caller, Rpc_obj_key()),
|
|
|
|
rcv_header.protocol_word);
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-04-21 16:41:13 +02:00
|
|
|
Ipc_server::Ipc_server()
|
2016-06-15 15:04:54 +02:00
|
|
|
:
|
2020-04-21 16:41:13 +02:00
|
|
|
Native_capability(Capability_space::import(Fiasco::l4_myself(), Rpc_obj_key()))
|
2016-06-15 15:04:54 +02:00
|
|
|
{ }
|
2016-03-11 21:47:12 +01:00
|
|
|
|
|
|
|
|
|
|
|
Ipc_server::~Ipc_server() { }
|