mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-16 06:08:16 +00:00
Clean up base-library structure
This patch moves the base library from src/base to src/lib/base, flattens the library-internal directory structure, and moves the common parts of the library-description files to base/lib/mk/base.inc and base/lib/mk/base-common.inc. Furthermore, the patch fixes a few cosmetic issues (whitespace and comments only) that I encountered while browsing the result. Fixes #1952
This commit is contained in:
23
repos/base-foc/src/lib/base/cache.cc
Normal file
23
repos/base-foc/src/lib/base/cache.cc
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* \brief Implementation of the cache operations
|
||||
* \author Christian Prochaska
|
||||
* \date 2014-05-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/cache.h>
|
||||
}
|
||||
|
||||
#include <cpu/cache.h>
|
||||
|
||||
void Genode::cache_coherent(Genode::addr_t addr, Genode::size_t size)
|
||||
{
|
||||
Fiasco::l4_cache_coherent(addr, addr + size);
|
||||
}
|
20
repos/base-foc/src/lib/base/cap_alloc.cc
Normal file
20
repos/base-foc/src/lib/base/cap_alloc.cc
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* \brief Capability index allocator for Fiasco.OC non-core processes.
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-02-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-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.
|
||||
*/
|
||||
|
||||
#include <base/cap_alloc.h>
|
||||
|
||||
Genode::Cap_index_allocator* Genode::cap_idx_alloc()
|
||||
{
|
||||
static Genode::Cap_index_allocator_tpl<Cap_index,4096> alloc;
|
||||
return &alloc;
|
||||
}
|
183
repos/base-foc/src/lib/base/cap_map.cc
Normal file
183
repos/base-foc/src/lib/base/cap_map.cc
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* \brief Mapping of Genode's capability names to kernel capabilities.
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-12-06
|
||||
*
|
||||
* This is a Fiasco.OC-specific addition to the process enviroment.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/cap_map.h>
|
||||
#include <base/native_types.h>
|
||||
|
||||
#include <util/assert.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/spin_lock.h>
|
||||
|
||||
/* kernel includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/consts.h>
|
||||
#include <l4/sys/task.h>
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
** Cap_index class **
|
||||
***********************/
|
||||
|
||||
static volatile int _cap_index_spinlock = SPINLOCK_UNLOCKED;
|
||||
|
||||
|
||||
bool Genode::Cap_index::higher(Genode::Cap_index *n) { return n->_id > _id; }
|
||||
|
||||
|
||||
Genode::Cap_index* Genode::Cap_index::find_by_id(Genode::uint16_t id)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
if (_id == id) return this;
|
||||
|
||||
Cap_index *n = Avl_node<Cap_index>::child(id > _id);
|
||||
return n ? n->find_by_id(id) : 0;
|
||||
}
|
||||
|
||||
|
||||
Genode::addr_t Genode::Cap_index::kcap() {
|
||||
return cap_idx_alloc()->idx_to_kcap(this); }
|
||||
|
||||
|
||||
Genode::uint8_t Genode::Cap_index::inc()
|
||||
{
|
||||
/* con't ref-count index that are controlled by core */
|
||||
if (cap_idx_alloc()->static_idx(this))
|
||||
return 1;
|
||||
|
||||
spinlock_lock(&_cap_index_spinlock);
|
||||
Genode::uint8_t ret = ++_ref_cnt;
|
||||
spinlock_unlock(&_cap_index_spinlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Genode::uint8_t Genode::Cap_index::dec()
|
||||
{
|
||||
/* con't ref-count index that are controlled by core */
|
||||
if (cap_idx_alloc()->static_idx(this))
|
||||
return 1;
|
||||
|
||||
spinlock_lock(&_cap_index_spinlock);
|
||||
Genode::uint8_t ret = --_ref_cnt;
|
||||
spinlock_unlock(&_cap_index_spinlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
** Capability_map class **
|
||||
****************************/
|
||||
|
||||
Genode::Cap_index* Genode::Capability_map::find(int id)
|
||||
{
|
||||
Genode::Lock_guard<Spin_lock> guard(_lock);
|
||||
|
||||
return _tree.first() ? _tree.first()->find_by_id(id) : 0;
|
||||
}
|
||||
|
||||
|
||||
Genode::Cap_index* Genode::Capability_map::insert(int id)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Lock_guard<Spin_lock> guard(_lock);
|
||||
|
||||
ASSERT(!_tree.first() || !_tree.first()->find_by_id(id),
|
||||
"Double insertion in cap_map()!");
|
||||
|
||||
Cap_index *i = cap_idx_alloc()->alloc_range(1);
|
||||
if (i) {
|
||||
i->id(id);
|
||||
_tree.insert(i);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
Genode::Cap_index* Genode::Capability_map::insert(int id, addr_t kcap)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Lock_guard<Spin_lock> guard(_lock);
|
||||
|
||||
/* remove potentially existent entry */
|
||||
Cap_index *i = _tree.first() ? _tree.first()->find_by_id(id) : 0;
|
||||
if (i)
|
||||
_tree.remove(i);
|
||||
|
||||
i = cap_idx_alloc()->alloc(kcap);
|
||||
if (i) {
|
||||
i->id(id);
|
||||
_tree.insert(i);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
Genode::Cap_index* Genode::Capability_map::insert_map(int id, addr_t kcap)
|
||||
{
|
||||
using namespace Genode;
|
||||
using namespace Fiasco;
|
||||
|
||||
Lock_guard<Spin_lock> guard(_lock);
|
||||
|
||||
/* check whether capability id exists */
|
||||
Cap_index *i = _tree.first() ? _tree.first()->find_by_id(id) : 0;
|
||||
|
||||
/* if we own the capability already check whether it's the same */
|
||||
if (i) {
|
||||
l4_msgtag_t tag = l4_task_cap_equal(L4_BASE_TASK_CAP, i->kcap(), kcap);
|
||||
if (!l4_msgtag_label(tag)) {
|
||||
/*
|
||||
* they aren't equal, possibly an already revoked cap,
|
||||
* otherwise it's a fake capability and we return an invalid one
|
||||
*/
|
||||
tag = l4_task_cap_valid(L4_BASE_TASK_CAP, i->kcap());
|
||||
if (l4_msgtag_label(tag))
|
||||
return 0;
|
||||
else
|
||||
/* it's invalid so remove it from the tree */
|
||||
_tree.remove(i);
|
||||
} else
|
||||
/* they are equal so just return the one in the map */
|
||||
return i;
|
||||
}
|
||||
|
||||
/* the capability doesn't exists in the map so allocate a new one */
|
||||
i = cap_idx_alloc()->alloc_range(1);
|
||||
if (!i)
|
||||
return 0;
|
||||
|
||||
/* set it's id and insert it into the tree */
|
||||
i->id(id);
|
||||
_tree.insert(i);
|
||||
|
||||
/* map the given cap to our registry entry */
|
||||
l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP,
|
||||
l4_obj_fpage(kcap, 0, L4_FPAGE_RWX),
|
||||
i->kcap() | L4_ITEM_MAP | L4_MAP_ITEM_GRANT);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
Genode::Capability_map* Genode::cap_map()
|
||||
{
|
||||
static Genode::Capability_map map;
|
||||
return ↦
|
||||
}
|
30
repos/base-foc/src/lib/base/cap_map_remove.cc
Normal file
30
repos/base-foc/src/lib/base/cap_map_remove.cc
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* \brief Mapping of Genode's capability names to kernel capabilities.
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2010-12-06
|
||||
*
|
||||
* This is a Fiasco.OC-specific addition to the process enviroment.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <base/cap_map.h>
|
||||
|
||||
void Genode::Capability_map::remove(Genode::Cap_index* i)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Lock_guard<Spin_lock> guard(_lock);
|
||||
|
||||
if (i) {
|
||||
Cap_index* e = _tree.first() ? _tree.first()->find_by_id(i->id()) : 0;
|
||||
if (e == i)
|
||||
_tree.remove(i);
|
||||
cap_idx_alloc()->free(i, 1);
|
||||
}
|
||||
}
|
378
repos/base-foc/src/lib/base/ipc.cc
Normal file
378
repos/base-foc/src/lib/base/ipc.cc
Normal file
@ -0,0 +1,378 @@
|
||||
/*
|
||||
* \brief Implementation of the IPC API for Fiasco.OC
|
||||
* \author Stefan Kalkowski
|
||||
* \author Norman Feske
|
||||
* \date 2009-12-03
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* l4_msgtag_t (size == 1 mword) format:
|
||||
*
|
||||
* --------------------------------------------------------------
|
||||
* | label | 4 Bit flags | 6 Bit items | 6 Bit word count |
|
||||
* --------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/blocking.h>
|
||||
#include <base/ipc.h>
|
||||
#include <base/ipc_msgbuf.h>
|
||||
#include <base/thread.h>
|
||||
#include <util/assert.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/lock_helper.h> /* for 'thread_get_my_native_id()' */
|
||||
#include <base/internal/ipc_server.h>
|
||||
|
||||
/* Fiasco.OC includes */
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/consts.h>
|
||||
#include <l4/sys/ipc.h>
|
||||
#include <l4/sys/types.h>
|
||||
#include <l4/sys/utcb.h>
|
||||
#include <l4/sys/kdebug.h>
|
||||
}
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Fiasco;
|
||||
|
||||
|
||||
/***************
|
||||
** Utilities **
|
||||
***************/
|
||||
|
||||
enum Debug { DEBUG_MSG = 1, HALT_ON_ERROR = 0 };
|
||||
|
||||
|
||||
static inline bool ipc_error(l4_msgtag_t tag, bool print)
|
||||
{
|
||||
int ipc_error = l4_ipc_error(tag, l4_utcb());
|
||||
if (ipc_error) {
|
||||
if (print) {
|
||||
outstring("Ipc error: ");
|
||||
outhex32(ipc_error);
|
||||
outstring(" occurred!\n");
|
||||
}
|
||||
if (HALT_ON_ERROR)
|
||||
enter_kdebug("Ipc error");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
enum { INVALID_BADGE = ~0UL };
|
||||
|
||||
|
||||
/**
|
||||
* Representation of a capability during UTCB marshalling/unmarshalling
|
||||
*/
|
||||
struct Cap_info
|
||||
{
|
||||
bool valid = false;
|
||||
unsigned long sel = 0;
|
||||
unsigned long badge = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Copy message registers from UTCB to destination message buffer
|
||||
*
|
||||
* \return protocol word (local name or exception code)
|
||||
*/
|
||||
static unsigned long extract_msg_from_utcb(l4_msgtag_t tag,
|
||||
Receive_window &rcv_window,
|
||||
Msgbuf_base &rcv_msg)
|
||||
{
|
||||
unsigned num_msg_words = l4_msgtag_words(tag);
|
||||
|
||||
l4_mword_t const *msg_words = (l4_mword_t const *)l4_utcb_mr();
|
||||
|
||||
/* each message has at least the protocol word and the capability count */
|
||||
if (num_msg_words < 2)
|
||||
return 0;
|
||||
|
||||
/* read badge / exception code from first message word */
|
||||
unsigned long const protocol_word = *msg_words++;
|
||||
|
||||
/* read number of capability arguments from second message word */
|
||||
unsigned long const num_caps = min(*msg_words, Msgbuf_base::MAX_CAPS_PER_MSG);
|
||||
msg_words++;
|
||||
|
||||
num_msg_words -= 2;
|
||||
if (num_caps > 0 && num_msg_words < num_caps) {
|
||||
outstring("unexpected end of message, capability info missing\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract capabilities
|
||||
*
|
||||
* The badges are stored in the subsequent message registers. For each
|
||||
* valid badge, we expect one capability selector to be present in the
|
||||
* receive window. The content of the receive window is tracked via
|
||||
* 'sel_idx'. If we encounter an invalid badge, the sender specified
|
||||
* an invalid capabilty as argument.
|
||||
*/
|
||||
unsigned const num_cap_sel = l4_msgtag_items(tag);
|
||||
|
||||
Cap_info caps[num_caps];
|
||||
|
||||
for (unsigned i = 0, sel_idx = 0; i < num_caps; i++) {
|
||||
|
||||
unsigned long const badge = *msg_words++;
|
||||
|
||||
if (badge == INVALID_BADGE)
|
||||
continue;
|
||||
|
||||
/* received a delegated capability */
|
||||
if (sel_idx == num_cap_sel) {
|
||||
outstring("missing capability selector in message\n");
|
||||
break;
|
||||
}
|
||||
|
||||
caps[i].badge = badge;
|
||||
caps[i].valid = true;
|
||||
caps[i].sel = rcv_window.rcv_cap_sel(sel_idx++);
|
||||
}
|
||||
num_msg_words -= num_caps;
|
||||
|
||||
/* the remainder of the message contains the regular data payload */
|
||||
if ((num_msg_words)*sizeof(l4_mword_t) > rcv_msg.capacity()) {
|
||||
if (DEBUG_MSG)
|
||||
outstring("receive message buffer too small\n");
|
||||
num_msg_words = rcv_msg.capacity()/sizeof(l4_mword_t);
|
||||
}
|
||||
|
||||
/* read message payload beginning from the second UTCB message register */
|
||||
l4_mword_t *dst = (l4_mword_t *)rcv_msg.data();
|
||||
for (unsigned i = 0; i < num_msg_words; i++)
|
||||
*dst++ = *msg_words++;
|
||||
|
||||
rcv_msg.data_size(sizeof(l4_mword_t)*num_msg_words);
|
||||
|
||||
/*
|
||||
* Insert received capability selectors into cap map.
|
||||
*
|
||||
* Note that this operation pollutes the UTCB. Therefore we must perform
|
||||
* it not before the entire message content is extracted.
|
||||
*/
|
||||
for (unsigned i = 0; i < num_caps; i++) {
|
||||
if (caps[i].valid) {
|
||||
rcv_msg.insert(Native_capability(cap_map()->insert_map(caps[i].badge,
|
||||
caps[i].sel)));
|
||||
} else {
|
||||
rcv_msg.insert(Native_capability());
|
||||
}
|
||||
}
|
||||
|
||||
return protocol_word;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy message registers from message buffer to UTCB and create message tag.
|
||||
*
|
||||
* \param protocol_word badge of invoked object (when a client calls a server)
|
||||
* or the exception code (when a server replies to a
|
||||
* client)
|
||||
*/
|
||||
static l4_msgtag_t copy_msgbuf_to_utcb(Msgbuf_base &snd_msg,
|
||||
unsigned long protocol_word)
|
||||
{
|
||||
|
||||
unsigned const num_data_words = snd_msg.data_size() / sizeof(l4_mword_t);
|
||||
unsigned const num_caps = snd_msg.used_caps();
|
||||
|
||||
/* validate capabilities present in the message buffer */
|
||||
for (unsigned i = 0; i < num_caps; i++) {
|
||||
|
||||
Native_capability &cap = snd_msg.cap(i);
|
||||
if (!cap.valid())
|
||||
continue;
|
||||
|
||||
if (!l4_msgtag_label(l4_task_cap_valid(L4_BASE_TASK_CAP, cap.dst())))
|
||||
cap = Native_capability();
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain capability info from message buffer
|
||||
*
|
||||
* This step must be performed prior any write operation to the UTCB
|
||||
* because the 'Genode::Capability' operations may indirectly trigger
|
||||
* system calls, which pollute the UTCB.
|
||||
*/
|
||||
Cap_info caps[num_caps];
|
||||
for (unsigned i = 0; i < num_caps; i++) {
|
||||
Native_capability const &cap = snd_msg.cap(i);
|
||||
if (cap.valid()) {
|
||||
caps[i].valid = true;
|
||||
caps[i].badge = cap.local_name();
|
||||
caps[i].sel = cap.dst();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The message consists of a protocol word, the capability count, one badge
|
||||
* value per capability, and the data payload.
|
||||
*/
|
||||
unsigned const num_msg_words = 2 + num_caps + num_data_words;
|
||||
|
||||
if (num_msg_words > L4_UTCB_GENERIC_DATA_SIZE) {
|
||||
outstring("receive message buffer too small\n");
|
||||
throw Ipc_error();
|
||||
}
|
||||
|
||||
l4_mword_t *msg_words = (l4_mword_t *)l4_utcb_mr();
|
||||
|
||||
*msg_words++ = protocol_word;
|
||||
*msg_words++ = num_caps;
|
||||
|
||||
unsigned num_cap_sel = 0;
|
||||
|
||||
for (unsigned i = 0; i < num_caps; i++) {
|
||||
|
||||
Native_capability const &cap = snd_msg.cap(i);
|
||||
|
||||
/* store badge as normal message word */
|
||||
*msg_words++ = caps[i].valid ? caps[i].badge : INVALID_BADGE;
|
||||
|
||||
/* setup flexpage for valid capability to delegate */
|
||||
if (caps[i].valid) {
|
||||
unsigned const idx = num_msg_words + 2*num_cap_sel;
|
||||
l4_utcb_mr()->mr[idx] = L4_ITEM_MAP/* | L4_ITEM_CONT*/;
|
||||
l4_utcb_mr()->mr[idx + 1] = l4_obj_fpage(caps[i].sel,
|
||||
0, L4_FPAGE_RWX).raw;
|
||||
num_cap_sel++;
|
||||
}
|
||||
}
|
||||
|
||||
/* store message data into UTCB message registers */
|
||||
for (unsigned i = 0; i < num_data_words; i++)
|
||||
*msg_words++ = snd_msg.word(i);
|
||||
|
||||
return l4_msgtag(0, num_msg_words, num_cap_sel, 0);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
** IPC client **
|
||||
****************/
|
||||
|
||||
Rpc_exception_code Genode::ipc_call(Native_capability dst,
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
|
||||
size_t rcv_caps)
|
||||
{
|
||||
Receive_window rcv_window;
|
||||
rcv_window.init();
|
||||
rcv_msg.reset();
|
||||
|
||||
/* copy call message to the UTCBs message registers */
|
||||
l4_msgtag_t const call_tag = copy_msgbuf_to_utcb(snd_msg, dst.local_name());
|
||||
|
||||
addr_t rcv_cap_sel = rcv_window.rcv_cap_sel_base();
|
||||
for (int i = 0; i < Msgbuf_base::MAX_CAPS_PER_MSG; i++) {
|
||||
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
|
||||
rcv_cap_sel += L4_CAP_SIZE;
|
||||
}
|
||||
|
||||
l4_msgtag_t const reply_tag =
|
||||
l4_ipc_call(dst.dst(), l4_utcb(), call_tag, L4_IPC_NEVER);
|
||||
|
||||
if (l4_ipc_error(reply_tag, l4_utcb()) == L4_IPC_RECANCELED)
|
||||
throw Genode::Blocking_canceled();
|
||||
|
||||
if (ipc_error(reply_tag, DEBUG_MSG))
|
||||
throw Genode::Ipc_error();
|
||||
|
||||
return Rpc_exception_code(extract_msg_from_utcb(reply_tag, rcv_window, rcv_msg));
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
** IPC server **
|
||||
****************/
|
||||
|
||||
static bool badge_matches_label(unsigned long badge, unsigned long label)
|
||||
{
|
||||
return badge == (label & (~0UL << 2));
|
||||
}
|
||||
|
||||
|
||||
void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc,
|
||||
Msgbuf_base &snd_msg)
|
||||
{
|
||||
l4_msgtag_t tag = copy_msgbuf_to_utcb(snd_msg, exc.value);
|
||||
|
||||
tag = l4_ipc_send(L4_SYSF_REPLY, l4_utcb(), tag, L4_IPC_SEND_TIMEOUT_0);
|
||||
|
||||
ipc_error(tag, DEBUG_MSG);
|
||||
}
|
||||
|
||||
|
||||
Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
|
||||
Rpc_exception_code exc,
|
||||
Msgbuf_base &reply_msg,
|
||||
Msgbuf_base &request_msg)
|
||||
{
|
||||
Receive_window &rcv_window = Thread_base::myself()->native_thread().rcv_window;
|
||||
|
||||
for (;;) {
|
||||
|
||||
request_msg.reset();
|
||||
|
||||
/* prepare receive window in UTCB */
|
||||
addr_t rcv_cap_sel = rcv_window.rcv_cap_sel_base();
|
||||
for (int i = 0; i < Msgbuf_base::MAX_CAPS_PER_MSG; i++) {
|
||||
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
|
||||
rcv_cap_sel += L4_CAP_SIZE;
|
||||
}
|
||||
l4_utcb_br()->bdr &= ~L4_BDR_OFFSET_MASK;
|
||||
|
||||
l4_msgtag_t request_tag;
|
||||
l4_umword_t label = 0; /* kernel-protected label of invoked capability */
|
||||
|
||||
if (exc.value != Rpc_exception_code::INVALID_OBJECT) {
|
||||
|
||||
l4_msgtag_t const reply_tag = copy_msgbuf_to_utcb(reply_msg, exc.value);
|
||||
|
||||
request_tag = l4_ipc_reply_and_wait(l4_utcb(), reply_tag, &label, L4_IPC_SEND_TIMEOUT_0);
|
||||
} else {
|
||||
request_tag = l4_ipc_wait(l4_utcb(), &label, L4_IPC_NEVER);
|
||||
}
|
||||
|
||||
if (ipc_error(request_tag, false))
|
||||
continue;
|
||||
|
||||
/* copy request message from the UTCBs message registers */
|
||||
unsigned long const badge =
|
||||
extract_msg_from_utcb(request_tag, rcv_window, request_msg);
|
||||
|
||||
/* ignore request if we detect a forged badge */
|
||||
if (!badge_matches_label(badge, label)) {
|
||||
outstring("badge does not match label, ignoring request\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
return Rpc_request(Native_capability(), badge);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::Ipc_server()
|
||||
:
|
||||
Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE])
|
||||
{
|
||||
Thread_base::myself()->native_thread().rcv_window.init();
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::~Ipc_server() { }
|
29
repos/base-foc/src/lib/base/spin_lock.cc
Normal file
29
repos/base-foc/src/lib/base/spin_lock.cc
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* \brief Spin-lock implementation for environment's capability -allocator.
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-02-29
|
||||
*
|
||||
* This is a Fiasco.OC-specific addition to the process enviroment.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/cap_map.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/spin_lock.h>
|
||||
|
||||
|
||||
Genode::Spin_lock::Spin_lock() : _spinlock(SPINLOCK_UNLOCKED) {}
|
||||
|
||||
|
||||
void Genode::Spin_lock::lock() { spinlock_lock(&_spinlock); }
|
||||
|
||||
|
||||
void Genode::Spin_lock::unlock() { spinlock_unlock(&_spinlock); }
|
59
repos/base-foc/src/lib/base/thread_bootstrap.cc
Normal file
59
repos/base-foc/src/lib/base/thread_bootstrap.cc
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* \brief Fiasco.OC specific thread bootstrap code
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \date 2011-01-20
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/construct_at.h>
|
||||
#include <base/thread.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
|
||||
/*****************************
|
||||
** Startup library support **
|
||||
*****************************/
|
||||
|
||||
void prepare_init_main_thread()
|
||||
{
|
||||
using namespace Genode;
|
||||
enum { THREAD_CAP_ID = 1 };
|
||||
Cap_index * ci(cap_map()->insert(THREAD_CAP_ID, Fiasco::MAIN_THREAD_CAP));
|
||||
Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE] = (unsigned long)ci;
|
||||
Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_THREAD_OBJ] = 0;
|
||||
}
|
||||
|
||||
|
||||
void prepare_reinit_main_thread()
|
||||
{
|
||||
using namespace Genode;
|
||||
construct_at<Capability_map>(cap_map());
|
||||
cap_idx_alloc()->reinit();
|
||||
prepare_init_main_thread();
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Thread_base **
|
||||
*****************/
|
||||
|
||||
void Genode::Thread_base::_thread_bootstrap() { }
|
||||
|
||||
|
||||
void Genode::Thread_base::_thread_start()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Thread_base::myself()->_thread_bootstrap();
|
||||
Thread_base::myself()->entry();
|
||||
Thread_base::myself()->_join_lock.unlock();
|
||||
sleep_forever();
|
||||
}
|
24
repos/base-foc/src/lib/base/thread_myself.cc
Normal file
24
repos/base-foc/src/lib/base/thread_myself.cc
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* \brief Implementation of the Thread API (foc-specific myself())
|
||||
* \author Norman Feske
|
||||
* \date 2015-04-28
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <base/thread.h>
|
||||
|
||||
|
||||
Genode::Thread_base *Genode::Thread_base::myself()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
return reinterpret_cast<Thread_base*>(l4_utcb_tcr()->user[UTCB_TCR_THREAD_OBJ]);
|
||||
}
|
||||
|
||||
|
104
repos/base-foc/src/lib/base/thread_start.cc
Normal file
104
repos/base-foc/src/lib/base/thread_start.cc
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* \brief Fiasco-specific implementation of the non-core startup Thread API
|
||||
* \author Norman Feske
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/env.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/utcb.h>
|
||||
}
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Thread_base::_deinit_platform_thread()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
if (native_thread().kcap && _thread_cap.valid()) {
|
||||
Cap_index *i = (Cap_index*)l4_utcb_tcr_u(utcb()->foc_utcb)->user[UTCB_TCR_BADGE];
|
||||
cap_map()->remove(i);
|
||||
_cpu_session->kill_thread(_thread_cap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::_init_platform_thread(size_t weight, Type type)
|
||||
{
|
||||
/* if no cpu session is given, use it from the environment */
|
||||
if (!_cpu_session)
|
||||
_cpu_session = env()->cpu_session();
|
||||
|
||||
if (type == NORMAL)
|
||||
{
|
||||
/* create thread at core */
|
||||
char buf[48];
|
||||
name(buf, sizeof(buf));
|
||||
_thread_cap = _cpu_session->create_thread(env()->pd_session_cap(),
|
||||
weight, buf);
|
||||
|
||||
/* assign thread to protection domain */
|
||||
if (!_thread_cap.valid())
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
|
||||
return;
|
||||
}
|
||||
/* adjust values whose computation differs for a main thread */
|
||||
native_thread().kcap = Fiasco::MAIN_THREAD_CAP;
|
||||
_thread_cap = env()->parent()->main_thread_cap();
|
||||
|
||||
if (!_thread_cap.valid())
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
|
||||
/* make thread object known to the Fiasco environment */
|
||||
addr_t const t = (addr_t)this;
|
||||
Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_THREAD_OBJ] = t;
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::start()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
/* get gate-capability and badge of new thread */
|
||||
Thread_state state;
|
||||
try { state = _cpu_session->state(_thread_cap); }
|
||||
catch (...) { throw Cpu_session::Thread_creation_failed(); }
|
||||
|
||||
/* remember UTCB of the new thread */
|
||||
Fiasco::l4_utcb_t * const foc_utcb = (Fiasco::l4_utcb_t *)state.utcb;
|
||||
utcb()->foc_utcb = foc_utcb;
|
||||
|
||||
native_thread() = Native_thread(state.kcap);
|
||||
|
||||
Cap_index *i = cap_map()->insert(state.id, state.kcap);
|
||||
l4_utcb_tcr_u(foc_utcb)->user[UTCB_TCR_BADGE] = (unsigned long) i;
|
||||
l4_utcb_tcr_u(foc_utcb)->user[UTCB_TCR_THREAD_OBJ] = (addr_t)this;
|
||||
|
||||
/* register initial IP and SP at core */
|
||||
_cpu_session->start(_thread_cap, (addr_t)_thread_start, _stack->top());
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::cancel_blocking()
|
||||
{
|
||||
_cpu_session->cancel_blocking(_thread_cap);
|
||||
}
|
Reference in New Issue
Block a user