126 lines
3.5 KiB
C++
126 lines
3.5 KiB
C++
/*
|
|
* \brief IPC utility functions
|
|
* \author Norman Feske
|
|
* \date 2016-03-08
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2016-2017 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
#ifndef _INCLUDE__BASE__INTERNAL__IPC_H_
|
|
#define _INCLUDE__BASE__INTERNAL__IPC_H_
|
|
|
|
/* NOVA includes */
|
|
#include <nova/syscalls.h>
|
|
#include <nova/native_thread.h>
|
|
#include <nova/capability_space.h>
|
|
|
|
/**
|
|
* Copy message registers from UTCB to destination message buffer
|
|
*
|
|
* \return protocol word delivered via the first UTCB message register
|
|
*
|
|
* The caller of this function must ensure that utcb.msg_words is greater
|
|
* than 0.
|
|
*/
|
|
static inline Nova::mword_t copy_utcb_to_msgbuf(Nova::Utcb &utcb,
|
|
Genode::Receive_window &rcv_window,
|
|
Genode::Msgbuf_base &rcv_msg)
|
|
{
|
|
using namespace Genode;
|
|
using namespace Nova;
|
|
|
|
size_t num_msg_words = utcb.msg_words();
|
|
|
|
/*
|
|
* Handle the reception of a malformed message. This should never happen
|
|
* because the utcb.msg_words is checked by the caller of this function.
|
|
*/
|
|
if (num_msg_words < 1)
|
|
return 0;
|
|
|
|
/* the UTCB contains the protocol word followed by the message data */
|
|
mword_t const protocol_word = utcb.msg()[0];
|
|
size_t num_data_words = num_msg_words - 1;
|
|
|
|
if (num_data_words*sizeof(mword_t) > rcv_msg.capacity()) {
|
|
error("receive message buffer too small msg "
|
|
"size=", num_data_words*sizeof(mword_t), " "
|
|
"buf size=", rcv_msg.capacity());
|
|
num_data_words = rcv_msg.capacity()/sizeof(mword_t);
|
|
}
|
|
|
|
/* read message payload into destination message buffer */
|
|
mword_t *src = (mword_t *)(void *)(&utcb.msg()[1]);
|
|
mword_t *dst = (mword_t *)rcv_msg.data();
|
|
for (unsigned i = 0; i < num_data_words; i++)
|
|
*dst++ = *src++;
|
|
|
|
/* extract caps from UTCB */
|
|
for (unsigned i = 0; i < rcv_window.num_received_caps(); i++) {
|
|
Native_capability cap;
|
|
rcv_window.rcv_pt_sel(cap);
|
|
rcv_msg.insert(cap);
|
|
}
|
|
|
|
return protocol_word;
|
|
}
|
|
|
|
|
|
/**
|
|
* Copy message payload to UTCB message registers
|
|
*/
|
|
static inline bool copy_msgbuf_to_utcb(Nova::Utcb &utcb,
|
|
Genode::Msgbuf_base const &snd_msg,
|
|
Nova::mword_t protocol_value)
|
|
{
|
|
using namespace Genode;
|
|
using namespace Nova;
|
|
|
|
/* look up address and size of message payload */
|
|
mword_t *msg_buf = (mword_t *)snd_msg.data();
|
|
|
|
/* size of message payload in machine words */
|
|
size_t const num_data_words = snd_msg.data_size()/sizeof(mword_t);
|
|
|
|
/* account for protocol value in front of the message */
|
|
size_t num_msg_words = 1 + num_data_words;
|
|
|
|
enum { NUM_MSG_REGS = 256 };
|
|
if (num_msg_words > NUM_MSG_REGS) {
|
|
error("message does not fit into UTCB message registers");
|
|
num_msg_words = NUM_MSG_REGS;
|
|
}
|
|
|
|
utcb.msg()[0] = protocol_value;
|
|
|
|
/* store message into UTCB message registers */
|
|
mword_t *src = (mword_t *)&msg_buf[0];
|
|
mword_t *dst = (mword_t *)(void *)&utcb.msg()[1];
|
|
for (unsigned i = 0; i < num_data_words; i++)
|
|
*dst++ = *src++;
|
|
|
|
utcb.set_msg_word(num_msg_words);
|
|
|
|
/* append portal capability selectors */
|
|
for (unsigned i = 0; i < snd_msg.used_caps(); i++) {
|
|
|
|
Native_capability const &cap = snd_msg.cap(i);
|
|
Nova::Crd const crd = Capability_space::crd(cap);
|
|
|
|
if (crd.base() == ~0UL) continue;
|
|
|
|
if (!utcb.append_item(crd, i, false, false, true))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
#endif /* _INCLUDE__BASE__INTERNAL__IPC_H_ */
|