mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-15 15:32:07 +00:00
92 lines
2.5 KiB
C++
92 lines
2.5 KiB
C++
/*
|
|
* \brief Echo implementation
|
|
* \author Norman Feske
|
|
* \author Alexander Boettcher
|
|
* \date 2010-01-19
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2010-2013 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.
|
|
*/
|
|
|
|
/* Core includes */
|
|
#include <platform_pd.h>
|
|
|
|
/* local includes */
|
|
#include <echo.h>
|
|
#include <nova_util.h>
|
|
|
|
enum {
|
|
ECHO_STACK_SIZE = 512,
|
|
ECHO_GLOBAL = false,
|
|
ECHO_EXC_BASE = 0,
|
|
ECHO_LOG2_COUNT = 1 /* selector for EC and out-of-memory portal */
|
|
};
|
|
|
|
|
|
inline void *echo_stack_top()
|
|
{
|
|
static char echo_stack[ECHO_STACK_SIZE];
|
|
return &echo_stack[ECHO_STACK_SIZE - sizeof(long)];
|
|
}
|
|
|
|
|
|
/**
|
|
* IDC handler for the echo portal, executed by the echo EC
|
|
*/
|
|
static void echo_reply()
|
|
{
|
|
/* collect map information from calling thread, sent as 3 words */
|
|
Nova::Crd snd_rcv(echo()->utcb()->msg[0]);
|
|
Nova::mword_t offset = echo()->utcb()->msg[1];
|
|
bool kern_pd = echo()->utcb()->msg[2];
|
|
bool dma_mem = echo()->utcb()->msg[3];
|
|
bool write_combined = echo()->utcb()->msg[4];
|
|
|
|
/* reset message transfer descriptor */
|
|
echo()->utcb()->set_msg_word(0);
|
|
/* append capability-range as message-transfer item */
|
|
bool res = echo()->utcb()->append_item(snd_rcv, offset, kern_pd, false,
|
|
false, dma_mem, write_combined);
|
|
|
|
/* set return code, 0 means failure */
|
|
echo()->utcb()->msg[0] = res;
|
|
echo()->utcb()->items += 1;
|
|
|
|
/* during reply the mapping will be established */
|
|
Nova::reply(echo_stack_top());
|
|
}
|
|
|
|
|
|
Echo::Echo(Genode::addr_t utcb_addr)
|
|
:
|
|
_ec_sel(Genode::cap_map()->insert(ECHO_LOG2_COUNT)),
|
|
_pt_sel(Genode::cap_map()->insert()),
|
|
_utcb((Nova::Utcb *)utcb_addr)
|
|
{
|
|
using namespace Nova;
|
|
|
|
/* create echo EC */
|
|
Genode::addr_t pd_sel = Genode::Platform_pd::pd_core_sel();
|
|
uint8_t res = create_ec(_ec_sel, pd_sel, boot_cpu(), utcb_addr,
|
|
reinterpret_cast<mword_t>(echo_stack_top()),
|
|
ECHO_EXC_BASE, ECHO_GLOBAL);
|
|
|
|
/* make error condition visible by raising an unhandled page fault */
|
|
if (res != Nova::NOVA_OK) { *reinterpret_cast<unsigned *>(0) = 0xdead; }
|
|
|
|
/* set up echo portal to ourself */
|
|
res = create_pt(_pt_sel, pd_sel, _ec_sel, Mtd(0), (mword_t)echo_reply);
|
|
if (res != Nova::NOVA_OK) { *reinterpret_cast<unsigned *>(0) = 0xdead; }
|
|
revoke(Obj_crd(_pt_sel, 0, Obj_crd::RIGHT_PT_CTRL));
|
|
|
|
/* echo thread doesn't receive anything, it transfers items during reply */
|
|
utcb()->crd_rcv = utcb()->crd_xlt = 0;
|
|
}
|
|
|
|
|
|
Echo *echo() { static Echo inst(Echo::ECHO_UTCB_ADDR); return &inst; }
|