Move repositories to 'repos/' subdirectory

This patch changes the top-level directory layout as a preparatory
step for improving the tools for managing 3rd-party source codes.
The rationale is described in the issue referenced below.

Issue #1082
This commit is contained in:
Norman Feske
2014-05-07 11:48:19 +02:00
parent 1f9890d635
commit ca971bbfd8
3943 changed files with 454 additions and 430 deletions

View File

@ -0,0 +1,78 @@
/*
* \brief Console backend for PL011 UART on Codezero
* \author Norman Feske
* \date 2009-10-03
*
* This code assumes a PL011 UART as provided by 'qemu -M versatilepb'. Prior
* executing this code, the kernel already initialized the UART to print some
* startup message. So we can skip the UART initialization here. The kernel
* maps the UART registers to the magic address PL011_BASE when starting mm0.
* So we can just start using the device without any precautions.
*/
/*
* 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.
*/
/* Genode includes */
#include <base/console.h>
/* codezero includes */
#include <codezero/syscalls.h>
typedef unsigned char uint8_t;
/**
* Base address of default-mapped UART device
*
* defined in 'l4/arch/arm/io.h'
*/
enum { PL011_BASE = USERSPACE_CONSOLE_VBASE };
/**
* UART registers
*/
enum { PL011_REG_UARTDR = PL011_BASE + 0x00 };
enum { PL011_REG_UARTFR = PL011_BASE + 0x18 };
/**
* Returns true if UART is ready to transmit a character
*/
static bool pl011_tx_ready()
{
enum { PL011_TX_FIFO_FULL = 1 << 5 };
return !(*((volatile unsigned *)PL011_REG_UARTFR) & PL011_TX_FIFO_FULL);
}
/**
* Output character to serial port
*/
static void pl011_out_char(uint8_t c)
{
/* wait until serial port is ready */
while (!pl011_tx_ready());
/* output character */
*((volatile unsigned int *)PL011_REG_UARTDR) = c;
}
namespace Genode
{
class Core_console : public Console
{
protected:
void _out_char(char c) {
if(c == '\n')
pl011_out_char('\r');
pl011_out_char(c);
}
};
}

View File

@ -0,0 +1,53 @@
/*
* \brief Support for exceptions libsupc++
* \author Norman Feske
* \author Sebastian Sumpf
* \date 2006-07-21
*/
/*
* Copyright (C) 2006-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/printf.h>
extern "C" char __eh_frame_start__[]; /* from linker script */
extern "C" void __register_frame (const void *begin); /* from libgcc_eh */
/*
* This symbol is set by Genode's dynamic linker (ldso) during binary setup.
* After setup, the symbol will point to the actual implementation of
* 'dl_iterate_phdr', which is located within the linker. 'dl_iterate_phdr'
* iterates through all (linker loaded) binaries and shared libraries. This
* function has to be implemented in order to support C++ exceptions within
* shared libraries.
* Return values of dl_iterate_phdr (gcc 4.2.4):
* < 0 = error
* 0 = continue program header iteration
* > 0 = stop iteration (no errors occured)
*
* See also: man dl_iterate_phdr
*/
int (*genode__dl_iterate_phdr) (int (*callback) (void *info, unsigned long size, void *data), void *data) = 0;
extern "C" int dl_iterate_phdr(int (*callback) (void *info, unsigned long size, void *data), void *data) __attribute__((weak));
extern "C" int dl_iterate_phdr(int (*callback) (void *info, unsigned long size, void *data), void *data)
{
if (!genode__dl_iterate_phdr)
return -1;
return genode__dl_iterate_phdr(callback, data);
}
extern "C" void raise()
{
PDBG("raise called - not implemented\n");
}
void init_exception_handling()
{
// __register_frame(__eh_frame_start__);
}

View File

@ -0,0 +1,24 @@
/*
* \brief Functions required for using the arm-none-linux-gnueabi tool chain
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
#include <base/printf.h>
#include <base/stdint.h>
using namespace Genode;
extern "C" int raise(int sig)
{
PWRN("raise - not yet implemented");
return 0;
}

View File

@ -0,0 +1,40 @@
/*
* \brief Helper functions UTCB access on Codezero
* \author Norman Feske
* \date 2012-03-01
*/
/*
* 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/thread.h>
/**
* Resolve 'Thread_base::myself' when not linking the thread library
*
* This weak symbol is primarily used by test cases. Most other Genode programs
* use the thread library. If the thread library is not used, 'myself' can only
* be called by the main thread, for which 'myself' is defined as zero.
*/
Genode::Thread_base * __attribute__((weak)) Genode::Thread_base::myself() { return 0; }
Genode::Native_utcb *Genode::Thread_base::utcb()
{
/*
* If 'utcb' is called on the object returned by 'myself',
* the 'this' pointer may be NULL (if the calling thread is
* the main thread). Therefore we handle this special case
* here.
*/
if (this == 0) return 0;
return &_context->utcb;
}

View File

@ -0,0 +1,175 @@
/*
* \brief Codezero implementation of the IPC API
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
/* Codezero includes */
#include <codezero/syscalls.h>
/* Genode includes */
#include <base/ipc.h>
#include <base/printf.h>
#include <base/blocking.h>
#include <util/misc_math.h>
using namespace Genode;
using namespace Codezero;
enum { verbose_ipc = false };
/*****************
** Ipc_ostream **
*****************/
void Ipc_ostream::_send()
{
if (verbose_ipc)
PDBG("thread %d sends IPC to %d, write_offset=%d",
thread_myself(), _dst.dst(), _write_offset);
umword_t snd_size = min(_write_offset, (unsigned)L4_IPC_EXTENDED_MAX_SIZE);
*(umword_t *)_snd_msg->addr() = _dst.local_name();
int ret = l4_send_extended(_dst.dst(), L4_IPC_TAG_SYNC_EXTENDED,
snd_size, _snd_msg->addr());
if (ret < 0)
PERR("l4_send_extended (to thread %d) returned ret=%d",
_dst.dst(), ret);
_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()),
_snd_msg(snd_msg), _dst(dst)
{
_write_offset = sizeof(umword_t);
}
/*****************
** Ipc_istream **
*****************/
void Ipc_istream::_wait()
{
umword_t *rcv_buf = (umword_t *)_rcv_msg->addr();
umword_t rcv_size = min(_rcv_msg->size(), (unsigned)L4_IPC_EXTENDED_MAX_SIZE);
if (verbose_ipc)
PDBG("thread %d waits for IPC from %d, rcv_buf at %p, rcv_size=%d",
dst(), _rcv_cs, rcv_buf, (int)rcv_size);
int ret = l4_receive_extended(_rcv_cs, rcv_size, rcv_buf);
if (ret < 0)
PERR("l4_receive_extended (from any) returned ret=%d", ret);
if (verbose_ipc)
PDBG("thread %d received IPC from %d",
dst(), l4_get_sender());
_read_offset = sizeof(umword_t);
}
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
:
Ipc_unmarshaller((char *)rcv_msg->addr(), rcv_msg->size()),
Native_capability(thread_myself(), 0),
_rcv_msg(rcv_msg)
{
_rcv_cs = L4_ANYTHREAD;
_read_offset = sizeof(umword_t);
}
Ipc_istream::~Ipc_istream() { }
/****************
** Ipc_client **
****************/
void Ipc_client::_call()
{
#warning l4_sendrecv_extended is not yet implemented in l4lib/arch/syslib.h
_send();
_rcv_cs = Ipc_ostream::_dst.dst();
_wait();
_rcv_cs = L4_ANYTHREAD;
_write_offset = _read_offset = sizeof(umword_t);
}
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg, unsigned short)
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
{ }
/****************
** Ipc_server **
****************/
void Ipc_server::_prepare_next_reply_wait()
{
/* now we have a request to reply */
_reply_needed = true;
/* leave space for return value at the beginning of the msgbuf */
_write_offset = 2*sizeof(umword_t);
/* receive buffer offset */
_read_offset = sizeof(umword_t);
}
void Ipc_server::_wait()
{
/* wait for new server request */
try { Ipc_istream::_wait(); } catch (Blocking_canceled) { }
/* define destination of next reply */
Ipc_ostream::_dst = Native_capability(l4_get_sender(), badge());
_prepare_next_reply_wait();
}
void Ipc_server::_reply()
{
try { _send(); } catch (Ipc_error) { }
_prepare_next_reply_wait();
}
void Ipc_server::_reply_wait()
{
if (_reply_needed)
_reply();
_wait();
}
Ipc_server::Ipc_server(Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg)
:
Ipc_istream(rcv_msg), Ipc_ostream(Native_capability(), snd_msg),
_reply_needed(false)
{ }

View File

@ -0,0 +1,175 @@
/*
* \brief Pager support for Codezero
* \author Norman Feske
* \date 2010-02-16
*/
/*
* 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/ipc_pager.h>
#include <base/printf.h>
/* Codezero includes */
#include <codezero/syscalls.h>
using namespace Genode;
using namespace Codezero;
enum { verbose_page_faults = false };
/************************
** Page-fault utility **
************************/
class Fault
{
public:
enum Type { READ, WRITE, EXEC, UNKNOWN };
private:
/**
* Translate Codezero page-fault information to generic fault type
*
* \param sr status
* \param pte page-table entry
*/
static Type _fault_type(umword_t sr, umword_t pte)
{
if (is_prefetch_abort(sr))
return EXEC;
if ((pte & PTE_PROT_MASK) == (__MAP_USR_RO & PTE_PROT_MASK))
return WRITE;
return READ;
}
Type _type;
umword_t _addr;
umword_t _ip;
public:
/**
* Constructor
*
* \param kdata Codezero-specific page-fault information
*/
Fault(struct fault_kdata const &kdata)
:
_type(_fault_type(kdata.fsr, kdata.pte)),
_addr(_type == EXEC ? kdata.faulty_pc : kdata.far),
_ip(kdata.faulty_pc)
{ }
Type type() const { return _type; }
umword_t addr() const { return _addr; }
umword_t ip() const { return _ip; }
};
/**
* Print page-fault information in a human-readable form
*/
inline void print_page_fault(Fault &fault, int from)
{
printf("page (%s%s%s) fault from %d at pf_addr=%lx, pf_ip=%lx\n",
fault.type() == Fault::READ ? "r" : "-",
fault.type() == Fault::WRITE ? "w" : "-",
fault.type() == Fault::EXEC ? "x" : "-",
from, fault.addr(), fault.ip());
}
/***************
** IPC pager **
***************/
void Ipc_pager::wait_for_fault()
{
for (;;) {
int ret = l4_receive(L4_ANYTHREAD);
if (ret < 0) {
PERR("pager: l4_received returned ret=%d", ret);
continue;
}
umword_t tag = l4_get_tag();
int faulter_tid = l4_get_sender();
if (tag != L4_IPC_TAG_PFAULT) {
PWRN("got an unexpected IPC from %d", faulter_tid);
continue;
}
/* copy fault information from message registers */
struct fault_kdata fault_kdata;
for (unsigned i = 0; i < sizeof(fault_kdata_t)/sizeof(umword_t); i++)
((umword_t *)&fault_kdata)[i] = read_mr(MR_UNUSED_START + i);
Fault fault(fault_kdata);
if (verbose_page_faults)
print_page_fault(fault, faulter_tid);
/* determine corresponding page in our own address space */
_pf_addr = fault.addr();
_pf_write = fault.type() == Fault::WRITE;
_pf_ip = fault.ip();
_last = faulter_tid;
return;
}
}
void Ipc_pager::reply_and_wait_for_fault()
{
/* install mapping */
umword_t flags = _reply_mapping.writeable() ? MAP_USR_RW
: MAP_USR_RO;
/*
* XXX: remove heuristics for mapping device registers.
*/
if (_reply_mapping.from_phys() == 0x10120000 /* LCD */
|| _reply_mapping.from_phys() == 0x10006000 /* keyboard */
|| _reply_mapping.from_phys() == 0x10007000) /* mouse */
flags = MAP_USR_IO;
int ret = l4_map((void *)_reply_mapping.from_phys(),
(void *)_reply_mapping.to_virt(),
_reply_mapping.num_pages(), flags, _last);
/* wake up faulter if mapping succeeded */
if (ret < 0)
PERR("l4_map returned %d, putting thread %d to sleep", ret, _last);
else
acknowledge_wakeup();
/* wait for next page fault */
wait_for_fault();
}
void Ipc_pager::acknowledge_wakeup()
{
enum { SUCCESS = 0 };
l4_set_sender(_last);
l4_ipc_return(SUCCESS);
}
Ipc_pager::Ipc_pager() : Native_capability(thread_myself(), 0) { }

View File

@ -0,0 +1,48 @@
/*
* \brief Codezero-specific implementation of cmpxchg
* \author Norman Feske
* \date 2009-10-12
*/
/*
* 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.
*/
/* Genode includes */
#include <cpu/atomic.h>
#include <base/printf.h>
#include <base/lock.h>
/* Codezero includes */
#include <codezero/syscalls.h>
static bool mutex_initialized;
static Codezero::l4_mutex mutex;
int Genode::cmpxchg(volatile int *dest, int cmp_val, int new_val)
{
if (!mutex_initialized) {
Codezero::l4_mutex_init(&mutex);
mutex_initialized = true;
}
int ret = Codezero::l4_mutex_lock(&mutex);
if (ret < 0)
mutex_initialized = false;
bool result = false;
if (*dest == cmp_val) {
*dest = new_val;
result = true;
}
ret = Codezero::l4_mutex_unlock(&mutex);
if (ret < 0)
mutex_initialized = false;
return result;
}

View File

@ -0,0 +1,61 @@
/*
* \brief Helper functions for the Lock implementation
* \author Norman Feske
* \date 2010-04-20
*
* For documentation about the interface, please revisit the 'base-pistachio'
* implementation.
*/
/*
* 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/native_types.h>
#include <base/thread.h>
/* Codezero includes */
#include <codezero/syscalls.h>
extern Genode::Native_thread_id main_thread_tid;
extern Codezero::l4_mutex main_thread_running_lock;
static inline void thread_yield()
{
Codezero::l4_thread_switch(-1);
}
static inline bool thread_check_stopped_and_restart(Genode::Thread_base *thread_base)
{
Codezero::l4_mutex *running_lock = thread_base ?
thread_base->utcb()->running_lock() :
&main_thread_running_lock;
Codezero::l4_mutex_unlock(running_lock);
return true;
}
static inline void thread_switch_to(Genode::Thread_base *thread_base)
{
Genode::Native_thread_id tid = thread_base ?
thread_base->tid().l4id :
main_thread_tid;
Codezero::l4_thread_switch(tid);
}
static inline void thread_stop_myself()
{
Genode::Thread_base *myself = Genode::Thread_base::myself();
Codezero::l4_mutex *running_lock = myself ?
myself->utcb()->running_lock() :
&main_thread_running_lock;
Codezero::l4_mutex_lock(running_lock);
}

View File

@ -0,0 +1,105 @@
/*
* \brief Dummy pager framework
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
/* Genode includes */
#include <base/pager.h>
using namespace Genode;
/**********************
** Pager activation **
**********************/
void Pager_activation_base::entry()
{
Ipc_pager pager;
_cap = pager;
_cap_valid.unlock();
bool reply = false;
while (1) {
if (reply)
pager.reply_and_wait_for_fault();
else
pager.wait_for_fault();
/* lookup referenced object */
Object_pool<Pager_object>::Guard _obj(_ep ? _ep->lookup_and_lock(pager.badge()) : 0);
Pager_object * obj = _obj;
reply = false;
/* handle request */
if (obj) {
reply = !obj->pager(pager);
/* something strange occurred - leave thread in pagefault */
continue;
}
/*
* We got a request from one of cores region-manager sessions
* to answer the pending page fault of a resolved region-manager
* client. Hence, we have to send the page-fault reply to the
* specified thread and answer the call of the region-manager
* session.
*
* When called from a region-manager session, we receive the
* core-local address of the targeted pager object via the
* first message word, which corresponds to the 'fault_ip'
* argument of normal page-fault messages.
*/
obj = reinterpret_cast<Pager_object *>(pager.fault_ip());
/* send reply to the calling region-manager session */
pager.acknowledge_wakeup();
/* answer page fault of resolved pager object */
pager.set_reply_dst(obj->cap());
pager.acknowledge_wakeup();
}
}
/**********************
** Pager entrypoint **
**********************/
Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base *a)
: _activation(a)
{ _activation->ep(this); }
void Pager_entrypoint::dissolve(Pager_object *obj)
{
remove_locked(obj);
}
Pager_capability Pager_entrypoint::manage(Pager_object *obj)
{
/* return invalid capability if no activation is present */
if (!_activation) return Pager_capability();
_activation->cap();
Untyped_capability cap = Native_capability(_activation->cap().dst(), obj->badge());
/* add server object to object pool */
obj->cap(cap);
insert(obj);
/* return capability that uses the object id as badge */
return reinterpret_cap_cast<Pager_object>(cap);
}

View File

@ -0,0 +1,96 @@
/*
* \brief Thread bootstrap code
* \author Christian Prochaska
* \author Martin Stein
* \date 2013-02-15
*/
/*
* Copyright (C) 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/env.h>
#include <util/string.h>
/* Codezero includes */
#include <codezero/syscalls.h>
Genode::Native_thread_id main_thread_tid;
Codezero::l4_mutex main_thread_running_lock;
/*****************************
** Startup library support **
*****************************/
void prepare_init_main_thread()
{
/* initialize codezero environment */
Codezero::__l4_init();
/* provide kernel identification of thread through temporary environment */
main_thread_tid = Codezero::thread_myself();
}
void prepare_reinit_main_thread() { prepare_init_main_thread(); }
/****************************
** Codezero libl4 support **
****************************/
/*
* Unfortunately, the function 'exregs_print_registers' in 'exregs.c' refers to
* 'memset'. Because we do not want to link core against a C library, we have to
* resolve this function here.
*/
extern "C" void *memset(void *s, int c, Genode::size_t n) __attribute__((weak));
extern "C" void *memset(void *s, int c, Genode::size_t n)
{
return Genode::memset(s, c, n);
}
/*
* Same problem as for 'memset'. The 'printf' symbol is referenced from
* 'mutex.c' and 'exregs.c' of Codezero's libl4.
*/
extern "C" int printf(const char *format, ...) __attribute__((weak));
extern "C" int printf(const char *format, ...)
{
va_list list;
va_start(list, format);
Genode::vprintf(format, list);
va_end(list);
return 0;
}
/*****************
** Thread_base **
*****************/
void Genode::Thread_base::_thread_bootstrap()
{
Codezero::l4_mutex_init(utcb()->running_lock());
Codezero::l4_mutex_lock(utcb()->running_lock()); /* block on first mutex lock */
}
void Genode::Thread_base::_init_platform_thread(Type type)
{
if (type == NORMAL) { return; }
/* adjust values whose computation differs for a main thread */
_tid.l4id = main_thread_tid;
_thread_cap = Genode::env()->parent()->main_thread_cap();
/* get first mutex lock (normally done by _thread_bootstrap) */
Codezero::l4_mutex_init(utcb()->running_lock());
Codezero::l4_mutex_lock(utcb()->running_lock());
}

View File

@ -0,0 +1,76 @@
/*
* \brief NOVA-specific implementation of the Thread API
* \author Norman Feske
* \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>
/* Codezero includes */
#include <codezero/syscalls.h>
using namespace Genode;
/**
* Entry point entered by new threads
*/
void Thread_base::_thread_start()
{
Thread_base::myself()->_thread_bootstrap();
Thread_base::myself()->entry();
Thread_base::myself()->_join_lock.unlock();
Genode::sleep_forever();
}
/*****************
** Thread base **
*****************/
void Thread_base::_deinit_platform_thread()
{
_cpu_session->kill_thread(_thread_cap);
env()->rm_session()->remove_client(_pager_cap);
}
void Thread_base::start()
{
/* if no cpu session is given, use it from the environment */
if (!_cpu_session)
_cpu_session = env()->cpu_session();
/* create thread at core */
char buf[48];
name(buf, sizeof(buf));
_thread_cap = _cpu_session->create_thread(buf);
/* assign thread to protection domain */
env()->pd_session()->bind_thread(_thread_cap);
/* create new pager object and assign it to the new thread */
_pager_cap = env()->rm_session()->add_client(_thread_cap);
_cpu_session->set_pager(_thread_cap, _pager_cap);
/* register initial IP and SP at core */
_cpu_session->start(_thread_cap, (addr_t)_thread_start, _context->stack_top());
}
void Thread_base::cancel_blocking()
{
Codezero::l4_mutex_unlock(utcb()->running_lock());
_cpu_session->cancel_blocking(_thread_cap);
}

View File

@ -0,0 +1,68 @@
/*
* \brief Core-local RM session
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
/* Genode includes */
#include <base/printf.h>
/* core includes */
#include <core_rm_session.h>
#include <platform.h>
#include <map_local.h>
using namespace Genode;
Rm_session::Local_addr
Core_rm_session::attach(Dataspace_capability ds_cap, size_t size,
off_t offset, bool use_local_addr,
Rm_session::Local_addr local_addr,
bool executable)
{
using namespace Codezero;
Object_pool<Dataspace_component>::Guard ds(_ds_ep->lookup_and_lock(ds_cap));
if (!ds)
throw Invalid_dataspace();
if (size == 0)
size = ds->size();
size_t page_rounded_size = (size + get_page_size() - 1) & get_page_mask();
size_t num_pages = page_rounded_size >> get_page_size_log2();
if (use_local_addr) {
PERR("Parameter 'use_local_addr' not supported within core");
return 0;
}
if (offset) {
PERR("Parameter 'offset' not supported within core");
return 0;
}
/* allocate range in core's virtual address space */
void *virt_addr;
if (!platform()->region_alloc()->alloc(page_rounded_size, &virt_addr)) {
PERR("Could not allocate virtual address range in core of size %zd\n",
page_rounded_size);
return false;
}
if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages)) {
PERR("core-local memory mapping failed virt=%lx, phys=%lx\n",
(addr_t)virt_addr, ds->phys_addr());
return 0;
}
return virt_addr;
}

View File

@ -0,0 +1,28 @@
/*
* \brief Platform-specific parts of cores CPU-service
* \author Martin Stein
* \date 2012-04-17
*/
/*
* 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.
*/
/* Genode includes */
#include <base/printf.h>
/* Core includes */
#include <cpu_session_component.h>
using namespace Genode;
Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread_cap)
{
PERR("%s: Not implemented", __PRETTY_FUNCTION__);
return Ram_dataspace_capability();
}

View File

@ -0,0 +1,55 @@
/*
* \brief Core-local region manager session
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
#ifndef _CORE__INCLUDE__CORE_RM_SESSION_H_
#define _CORE__INCLUDE__CORE_RM_SESSION_H_
/* Genode includes */
#include <rm_session/rm_session.h>
/* core includes */
#include <dataspace_component.h>
namespace Genode {
class Core_rm_session : public Rm_session
{
private:
Rpc_entrypoint *_ds_ep;
public:
Core_rm_session(Rpc_entrypoint *ds_ep) : _ds_ep(ds_ep) { }
Local_addr attach(Dataspace_capability ds_cap, size_t size = 0,
off_t offset = 0, bool use_local_addr = false,
Local_addr local_addr = 0,
bool executable = false);
void detach(Local_addr) { }
Pager_capability add_client(Thread_capability) {
return Pager_capability(); }
void remove_client(Pager_capability) { }
void fault_handler(Signal_context_capability) { }
State state() { return State(); }
Dataspace_capability dataspace() { return Dataspace_capability(); }
};
}
#endif /* _CORE__INCLUDE__CORE_RM_SESSION_H_ */

View File

@ -0,0 +1,71 @@
/*
* \brief IRQ session interface for NOVA
* \author Norman Feske
* \date 2010-01-30
*/
/*
* 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.
*/
#ifndef _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
#define _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
#include <base/lock.h>
#include <util/list.h>
#include <irq_session/capability.h>
namespace Genode {
class Irq_session_component : public Rpc_object<Irq_session>,
public List<Irq_session_component>::Element
{
private:
enum { STACK_SIZE = 4096 };
unsigned _irq_number;
Range_allocator *_irq_alloc;
Rpc_entrypoint _entrypoint;
Irq_session_capability _cap;
bool _attached;
public:
/**
* Constructor
*
* \param cap_session capability session to use
* \param irq_alloc platform-dependent IRQ allocator
* \param args session construction arguments
*/
Irq_session_component(Cap_session *cap_session,
Range_allocator *irq_alloc,
const char *args);
/**
* Destructor
*/
~Irq_session_component();
/**
* Return capability to this session
*
* If an initialization error occurs, returned capability is invalid.
*/
Irq_session_capability cap() const { return _cap; }
/***************************
** Irq session interface **
***************************/
void wait_for_irq();
};
}
#endif /* _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ */

View File

@ -0,0 +1,66 @@
/*
* \brief Core-local mapping
* \author Norman Feske
* \date 2010-02-15
*/
/*
* 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.
*/
#ifndef _CORE__INCLUDE__MAP_LOCAL_H_
#define _CORE__INCLUDE__MAP_LOCAL_H_
/* Genode includes */
#include <base/printf.h>
/* core includes */
#include <util.h>
namespace Genode {
/**
* Map physical pages to core-local virtual address range
*
* On Codezero, mappings originate from the physical address space.
*
* \param from_phys physical source address
* \param to_virt core-local destination address
* \param num_pages number of pages to map
*
* \return true on success
*/
inline bool map_local(addr_t from_phys, addr_t to_virt, size_t num_pages)
{
using namespace Codezero;
int res = l4_map((void *)from_phys, (void *)to_virt,
num_pages, MAP_USR_RW, thread_myself());
if (res < 0) {
PERR("l4_map phys 0x%lx -> 0x%lx returned %d", from_phys, to_virt, res);
return false;
}
return true;
}
inline bool unmap_local(addr_t virt_addr, size_t num_pages)
{
using namespace Codezero;
int res = l4_unmap((void *)virt_addr, num_pages, thread_myself());
if (res < 0) {
PERR("l4_unmap returned %d", res);
return false;
}
return true;
}
}
#endif /* _CORE__INCLUDE__MAP_LOCAL_H_ */

View File

@ -0,0 +1,72 @@
/*
* \brief Platform interface
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
#ifndef _CORE__INCLUDE__PLATFORM_H_
#define _CORE__INCLUDE__PLATFORM_H_
/* Genode includes */
#include <base/printf.h>
/* local includes */
#include <platform_generic.h>
#include <core_mem_alloc.h>
namespace Genode {
class Platform : public Platform_generic
{
private:
typedef Core_mem_allocator::Phys_allocator Phys_allocator;
Core_mem_allocator _core_mem_alloc; /* core-accessible memory */
Phys_allocator _io_mem_alloc; /* MMIO allocator */
Phys_allocator _io_port_alloc; /* I/O port allocator */
Phys_allocator _irq_alloc; /* IRQ allocator */
Rom_fs _rom_fs; /* ROM file system */
/**
* Virtual address range usable by non-core processes
*/
addr_t _vm_base;
size_t _vm_size;
int _init_rom_fs();
public:
/**
* Constructor
*/
Platform();
/********************************
** Generic platform interface **
********************************/
Range_allocator *ram_alloc() { return _core_mem_alloc.phys_alloc(); }
Range_allocator *io_mem_alloc() { return &_io_mem_alloc; }
Range_allocator *io_port_alloc() { return &_io_port_alloc; }
Range_allocator *irq_alloc() { return &_irq_alloc; }
Range_allocator *region_alloc() { return _core_mem_alloc.virt_alloc(); }
Range_allocator *core_mem_alloc() { return &_core_mem_alloc; }
addr_t vm_start() const { return _vm_base; }
size_t vm_size() const { return _vm_size; }
Rom_fs *rom_fs() { return &_rom_fs; }
void wait_for_exit();
};
}
#endif /* _CORE__INCLUDE__PLATFORM_H_ */

View File

@ -0,0 +1,81 @@
/*
* \brief Protection-domain facility
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
#ifndef _CORE__INCLUDE__PLATFORM_PD_H_
#define _CORE__INCLUDE__PLATFORM_PD_H_
/* core includes */
#include <platform_thread.h>
#include <address_space.h>
/* Codezero includes */
#include <codezero/syscalls.h>
namespace Genode {
class Platform_thread;
class Platform_pd : public Address_space
{
private:
enum { MAX_THREADS_PER_PD = 32 };
enum { UTCB_VIRT_BASE = 0x30000000 };
enum { UTCB_AREA_SIZE = MAX_THREADS_PER_PD*sizeof(struct Codezero::utcb) };
unsigned _space_id;
bool utcb_in_use[MAX_THREADS_PER_PD];
public:
/**
* Constructors
*/
Platform_pd(bool core);
Platform_pd(char const *, signed pd_id = -1, bool create = true);
/**
* Destructor
*/
~Platform_pd();
/**
* Bind thread to protection domain
*
* \return 0 on success or
* -1 if thread ID allocation failed.
*/
int bind_thread(Platform_thread *thread);
/**
* Unbind thread from protection domain
*
* Free the thread's slot and update thread object.
*/
void unbind_thread(Platform_thread *thread);
/**
* Assign parent interface to protection domain
*/
int assign_parent(Native_capability parent) { return 0; }
/*****************************
** Address-space interface **
*****************************/
void flush(addr_t, size_t) { PDBG("not implemented"); }
};
}
#endif /* _CORE__INCLUDE__PLATFORM_PD_H_ */

View File

@ -0,0 +1,158 @@
/*
* \brief Thread facility
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
#ifndef _CORE__INCLUDE__PLATFORM_THREAD_H_
#define _CORE__INCLUDE__PLATFORM_THREAD_H_
/* Genode includes */
#include <base/pager.h>
#include <base/thread_state.h>
#include <base/native_types.h>
/* core includes */
#include <address_space.h>
namespace Genode {
class Platform_pd;
class Platform_thread
{
private:
friend class Platform_pd;
enum { PD_NAME_MAX_LEN = 64 };
unsigned _tid; /* global codezero thread ID */
unsigned _space_id;
Weak_ptr<Address_space> _address_space;
addr_t _utcb;
char _name[PD_NAME_MAX_LEN];
Pager_object *_pager;
/**
* Assign physical thread ID and UTCB address to thread
*
* This function is called from 'Platform_pd::bind_thread'.
*/
void _assign_physical_thread(unsigned tid, unsigned space_id,
addr_t utcb,
Weak_ptr<Address_space> address_space)
{
_tid = tid; _space_id = space_id; _utcb = utcb;
_address_space = address_space;
}
public:
enum { THREAD_INVALID = -1 }; /* invalid thread number */
/**
* Constructor
*/
Platform_thread(const char *name = 0, unsigned priority = 0,
addr_t utcb = 0, int thread_id = THREAD_INVALID);
/**
* Destructor
*/
~Platform_thread();
/**
* Start thread
*
* \param ip instruction pointer to start at
* \param sp stack pointer to use
* \param cpu_no target cpu
*
* \retval 0 successful
* \retval -1 thread could not be started
*/
int start(void *ip, void *sp, unsigned int cpu_no = 0);
/**
* Pause this thread
*/
void pause();
/**
* Resume this thread
*/
void resume();
/**
* Cancel currently blocking operation
*/
void cancel_blocking();
/**
* Override thread state with 's'
*
* \throw Cpu_session::State_access_failed
*/
void state(Thread_state s);
/**
* Read thread state
*
* \throw Cpu_session::State_access_failed
*/
Thread_state state();
/**
* Return the address space to which the thread is bound
*/
Weak_ptr<Address_space> address_space();
/************************
** Accessor functions **
************************/
/**
* Set pager capability
*/
Pager_object *pager(Pager_object *pager) const { return _pager; }
void pager(Pager_object *pager) { _pager = pager; }
Pager_object *pager() { return _pager; }
/**
* Return identification of thread when faulting
*/
unsigned long pager_object_badge() const { return _tid; }
/**
* Set the executing CPU for this thread
*/
void affinity(Affinity::Location) { }
/**
* Get the executing CPU for this thread
*/
Affinity::Location affinity() { return Affinity::Location(); }
/**
* Get thread name
*/
const char *name() const { return "noname"; }
/***********************
** Codezero specific **
***********************/
addr_t utcb() const { return _utcb; }
};
}
#endif /* _CORE__INCLUDE__PLATFORM_THREAD_H_ */

View File

@ -0,0 +1,46 @@
/*
* \brief Core-internal utilities
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
#ifndef _CORE__INCLUDE__UTIL_H_
#define _CORE__INCLUDE__UTIL_H_
/* Genode includes */
#include <rm_session/rm_session.h>
#include <base/printf.h>
/* Codezero includes */
#include <codezero/syscalls.h>
namespace Genode {
constexpr size_t get_page_size_log2() { return 12; }
constexpr size_t get_page_size() { return 1 << get_page_size_log2(); }
constexpr addr_t get_page_mask() { return ~(get_page_size() - 1); }
inline addr_t trunc_page(addr_t addr) { return addr & get_page_mask(); }
inline addr_t round_page(addr_t addr) { return trunc_page(addr + get_page_size() - 1); }
inline addr_t map_src_addr(addr_t core_local, addr_t phys) { return phys; }
inline size_t constrain_map_size_log2(size_t size_log2) { return get_page_size_log2(); }
inline void print_page_fault(const char *msg, addr_t pf_addr, addr_t pf_ip,
Rm_session::Fault_type pf_type,
unsigned long faulter_badge)
{
printf("%s (%s pf_addr=%p pf_ip=%p from %02lx)\n", msg,
pf_type == Rm_session::WRITE_FAULT ? "WRITE" : "READ",
(void *)pf_addr, (void *)pf_ip,
faulter_badge);
}
}
#endif /* _CORE__INCLUDE__UTIL_H_ */

View File

@ -0,0 +1,27 @@
/*
* \brief Implementation of the IO_MEM session interface
* \author Norman Feske
* \date 2009-03-29
*
*/
/*
* 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.
*/
/* core includes */
#include <io_mem_session_component.h>
using namespace Genode;
void Io_mem_session_component::_unmap_local(addr_t base, size_t size)
{ }
addr_t Io_mem_session_component::_map_local(addr_t base, size_t size)
{ return 0; }

View File

@ -0,0 +1,72 @@
/*
* \brief Implementation of IRQ session component
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
/* Genode includes */
#include <base/printf.h>
#include <base/sleep.h>
/* core includes */
#include <irq_root.h>
/* Codezero includes */
#include <codezero/syscalls.h>
using namespace Genode;
void Irq_session_component::wait_for_irq()
{
using namespace Codezero;
/* attach thread to IRQ when first called */
if (!_attached) {
int ret = l4_irq_control(IRQ_CONTROL_REGISTER, 0, _irq_number);
if (ret < 0) {
PERR("l4_irq_control(IRQ_CONTROL_REGISTER) returned %d", ret);
sleep_forever();
}
_attached = true;
}
/* block for IRQ */
int ret = l4_irq_control(IRQ_CONTROL_WAIT, 0, _irq_number);
if (ret < 0)
PWRN("l4_irq_control(IRQ_CONTROL_WAIT) returned %d", ret);
}
Irq_session_component::Irq_session_component(Cap_session *cap_session,
Range_allocator *irq_alloc,
const char *args)
:
_irq_alloc(irq_alloc),
_entrypoint(cap_session, STACK_SIZE, "irq"),
_attached(false)
{
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
if (!irq_alloc || (irq_number == -1)||
irq_alloc->alloc_addr(1, irq_number).is_error()) {
PERR("unavailable IRQ %lx requested", irq_number);
return;
}
_irq_number = irq_number;
_cap = Irq_session_capability(_entrypoint.manage(this));
}
Irq_session_component::~Irq_session_component()
{
PERR("not yet implemented");
}

View File

@ -0,0 +1,302 @@
/*
* \brief Platform interface implementation
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
/* Genode includes */
#include <base/printf.h>
#include <base/sleep.h>
#include <base/thread.h>
/* core includes */
#include <core_parent.h>
#include <platform.h>
#include <map_local.h>
/* Codezero includes */
#include <codezero/syscalls.h>
using namespace Genode;
enum { verbose_boot_info = true };
/*
* Memory-layout information provided by the linker script
*/
/* virtual address range consumed by core's program image */
extern unsigned _prog_img_beg, _prog_img_end;
/* physical address range occupied by core */
extern addr_t _vma_start, _lma_start;
/**************************
** Boot-module handling **
**************************/
/**
* Scan ROM module image for boot modules
*
* By convention, the boot modules start at the page after core's BSS segment.
*/
int Platform::_init_rom_fs()
{
/**
* Format of module meta-data as found in the ROM module image
*/
struct Module
{
long name; /* physical address of null-terminated string */
long base; /* physical address of module data */
long size; /* size of module data in bytes */
};
/* find base address of ROM module image */
addr_t phys_base = round_page((addr_t)&_prog_img_end);
/* map the first page of the image containing the module meta data */
class Out_of_virtual_memory_during_rom_fs_init { };
void *virt_base = 0;
if (!_core_mem_alloc.virt_alloc()->alloc(get_page_size(), &virt_base))
throw Out_of_virtual_memory_during_rom_fs_init();
if (!map_local(phys_base, (addr_t)virt_base, 1)) {
PERR("map_local failed");
return -1;
}
/* remove page containing module infos from physical memory allocator */
_core_mem_alloc.phys_alloc()->remove_range(phys_base, get_page_size());
/* validate the presence of a ROM image by checking the magic cookie */
const char cookie[4] = {'G', 'R', 'O', 'M'};
for (size_t i = 0; i < sizeof(cookie); i++)
if (cookie[i] != ((char *)virt_base)[i]) {
PERR("could not detect ROM modules");
return -2;
}
printf("detected ROM module image at 0x%p\n", (void *)phys_base);
/* detect overly large meta data, we only support 4K */
addr_t end_of_header = ((long *)virt_base)[1];
size_t header_size = end_of_header - (long)phys_base;
if (header_size > get_page_size()) {
PERR("ROM fs module header exceeds %d bytes", get_page_size());
return -3;
}
/* start of module list */
Module *module = (Module *)((addr_t)virt_base + 2*sizeof(long));
/*
* Interate over module list and populate core's ROM file system with
* 'Rom_module' objects.
*/
for (; module->name; module++) {
/* convert physical address of module name to core-local address */
char *name = (char *)(module->name - phys_base + (addr_t)virt_base);
printf("ROM module \"%s\" at physical address 0x%p, size=%zd\n",
name, (void *)module->base, (size_t)module->size);
Rom_module *rom_module = new (core_mem_alloc())
Rom_module(module->base, module->size, name);
_rom_fs.insert(rom_module);
/* remove module from physical memory allocator */
_core_mem_alloc.phys_alloc()->remove_range(module->base, round_page(module->size));
}
return 0;
}
/****************************************
** Support for core memory management **
****************************************/
bool Core_mem_allocator::Mapped_mem_allocator::_map_local(addr_t virt_addr,
addr_t phys_addr,
unsigned size)
{
return map_local(phys_addr, virt_addr, size / get_page_size());
}
bool Core_mem_allocator::Mapped_mem_allocator::_unmap_local(addr_t virt_addr,
unsigned size)
{
return unmap_local(virt_addr, size / get_page_size());
}
/************************
** Platform interface **
************************/
Platform::Platform() :
_io_mem_alloc(core_mem_alloc()), _io_port_alloc(core_mem_alloc()),
_irq_alloc(core_mem_alloc()), _vm_base(0), _vm_size(0)
{
using namespace Codezero;
/* init core UTCB */
static char main_utcb[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
static struct exregs_data exregs;
exregs_set_utcb(&exregs, (unsigned long)&main_utcb[0]);
l4_exchange_registers(&exregs, thread_myself());
/* error handling is futile at this point */
/* read number of capabilities */
int num_caps;
int ret;
if ((ret = l4_capability_control(CAP_CONTROL_NCAPS,
0, &num_caps)) < 0) {
PERR("l4_capability_control(CAP_CONTROL_NCAPS) returned %d", ret);
class Could_not_obtain_num_of_capabilities { };
throw Could_not_obtain_num_of_capabilities();
}
struct capability cap_array[num_caps];
if (verbose_boot_info)
printf("allocated cap array[%d] of size %d on stack\n",
num_caps, sizeof(cap_array));
/* read all capabilities */
if ((ret = l4_capability_control(CAP_CONTROL_READ,
0, cap_array)) < 0) {
PERR("l4_capability_control(CAP_CONTROL_READ) returned %d", ret);
class Read_caps_failed { };
throw Read_caps_failed();
}
/* initialize core allocators */
bool phys_mem_defined = false;
addr_t dev_mem_base = 0;
for (int i = 0; i < num_caps; i++) {
struct capability *cap = &cap_array[i];
addr_t base = cap->start << get_page_size_log2(),
size = cap->size << get_page_size_log2();
if (verbose_boot_info)
printf("cap type=%x, rtype=%x, base=%lx, size=%lx\n",
cap_type(cap), cap_rtype(cap), base, size);
switch (cap_type(cap)) {
case CAP_TYPE_MAP_VIRTMEM:
/*
* Use first non-UTCB virtual address range as default
* virtual memory range usable for all processes.
*/
if (_vm_size == 0) {
/* exclude page at virtual address 0 */
if (base == 0 && size >= get_page_size()) {
base += get_page_size();
size -= get_page_size();
}
_vm_base = base;
_vm_size = size;
/* add range as free range to core's virtual address allocator */
_core_mem_alloc.virt_alloc()->add_range(base, size);
break;
}
PWRN("ignoring additional virtual address range [%lx,%lx)",
base, base + size);
break;
case CAP_TYPE_MAP_PHYSMEM:
/*
* We interpret the first physical memory resource that is bigger
* than typical device resources as RAM.
*/
enum { RAM_SIZE_MIN = 16*1024*1024 };
if (!phys_mem_defined && size > RAM_SIZE_MIN) {
_core_mem_alloc.phys_alloc()->add_range(base, size);
phys_mem_defined = true;
dev_mem_base = base + size;
}
break;
case CAP_TYPE_IPC:
case CAP_TYPE_UMUTEX:
case CAP_TYPE_IRQCTRL:
case CAP_TYPE_QUANTITY:
break;
}
}
addr_t core_virt_beg = trunc_page((addr_t)&_prog_img_beg),
core_virt_end = round_page((addr_t)&_prog_img_end);
size_t core_size = core_virt_end - core_virt_beg;
printf("core image:\n");
printf(" virtual address range [%08lx,%08lx) size=0x%zx\n",
core_virt_beg, core_virt_end, core_size);
printf(" physically located at 0x%08lx\n", _lma_start);
/* remove core image from core's virtual address allocator */
_core_mem_alloc.virt_alloc()->remove_range(core_virt_beg, core_size);
/* preserve context area in core's virtual address space */
_core_mem_alloc.virt_alloc()->raw()->remove_range(Native_config::context_area_virtual_base(),
Native_config::context_area_virtual_size());
/* remove used core memory from physical memory allocator */
_core_mem_alloc.phys_alloc()->remove_range(_lma_start, core_size);
/* remove magically mapped UART from core virtual memory */
_core_mem_alloc.virt_alloc()->remove_range(USERSPACE_CONSOLE_VBASE, get_page_size());
/* add boot modules to ROM fs */
if (_init_rom_fs() < 0) {
PERR("initialization of romfs failed - halt.");
while(1);
}
/* initialize interrupt allocator */
_irq_alloc.add_range(0, 255);
/* regard physical addresses higher than memory area as MMIO */
_io_mem_alloc.add_range(dev_mem_base, 0x80000000 - dev_mem_base);
/*
* Print statistics about allocator initialization
*/
printf("VM area at [%08lx,%08lx)\n", _vm_base, _vm_base + _vm_size);
if (verbose_boot_info) {
printf(":phys_alloc: "); _core_mem_alloc.phys_alloc()->raw()->dump_addr_tree();
printf(":virt_alloc: "); _core_mem_alloc.virt_alloc()->raw()->dump_addr_tree();
printf(":io_mem_alloc: "); _io_mem_alloc.raw()->dump_addr_tree();
}
}
void Platform::wait_for_exit()
{
sleep_forever();
}
void Core_parent::exit(int exit_value) { }

View File

@ -0,0 +1,126 @@
/*
* \brief Protection-domain facility
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
/* Genode includes */
#include <base/printf.h>
/* core includes */
#include <platform_pd.h>
#include <platform.h>
#include <util.h>
using namespace Genode;
using namespace Codezero;
/***************************
** Public object members **
***************************/
int Platform_pd::bind_thread(Platform_thread *thread)
{
/* allocate new thread at the kernel */
struct task_ids ids = { 1, _space_id, TASK_ID_INVALID };
int ret = l4_thread_control(THREAD_CREATE | TC_SHARE_SPACE, &ids);
if (ret < 0) {
PERR("l4_thread_control returned %d, tid=%d\n", ret, ids.tid);
return -1;
}
/* allocate UTCB for new thread */
int utcb_idx;
for (utcb_idx = 0; utcb_idx < MAX_THREADS_PER_PD; utcb_idx++)
if (!utcb_in_use[utcb_idx]) break;
if (utcb_idx == MAX_THREADS_PER_PD) {
PERR("UTCB allocation failed");
return -2;
}
/* mark UTCB as being in use */
utcb_in_use[utcb_idx] = true;
/* map UTCB area for the first thread of a new PD */
if (utcb_idx == 0) {
void *utcb_phys = 0;
if (!platform()->ram_alloc()->alloc(UTCB_AREA_SIZE, &utcb_phys)) {
PERR("could not allocate physical pages for UTCB");
return -3;
}
ret = l4_map(utcb_phys, (void *)UTCB_VIRT_BASE,
UTCB_AREA_SIZE/get_page_size(), MAP_USR_RW, ids.tid);
if (ret < 0) {
PERR("UTCB mapping into new PD failed, ret=%d", ret);
return -4;
}
}
addr_t utcb_addr = UTCB_VIRT_BASE + utcb_idx*sizeof(struct utcb);
thread->_assign_physical_thread(ids.tid, _space_id, utcb_addr,
this->Address_space::weak_ptr());
return 0;
}
void Platform_pd::unbind_thread(Platform_thread *thread)
{
/* find UTCB index of thread */
unsigned utcb_idx;
for (utcb_idx = 0; utcb_idx < MAX_THREADS_PER_PD; utcb_idx++)
if (thread->utcb() == UTCB_VIRT_BASE + utcb_idx*sizeof(struct utcb))
break;
if (utcb_idx == MAX_THREADS_PER_PD) {
PWRN("could not find UTCB index of thread");
return;
}
utcb_in_use[utcb_idx] = false;
PWRN("not fully implemented");
}
Platform_pd::Platform_pd(bool core)
{
PWRN("not yet implemented");
}
Platform_pd::Platform_pd(char const *, signed pd_id, bool create)
: _space_id(TASK_ID_INVALID)
{
_space_id = TASK_ID_INVALID;
/* mark all UTCBs of the new PD as free */
for (int i = 0; i < MAX_THREADS_PER_PD; i++)
utcb_in_use[i] = false;
struct task_ids ids = { TASK_ID_INVALID, TASK_ID_INVALID, TASK_ID_INVALID };
int ret = l4_thread_control(THREAD_CREATE | TC_NEW_SPACE, &ids);
if (ret < 0) {
PERR("l4_thread_control(THREAD_CREATE | TC_NEW_SPACE) returned %d", ret);
return;
}
/* set space ID to valid value to indicate success */
_space_id = ids.spid;
}
Platform_pd::~Platform_pd()
{
PWRN("not yet implemented");
}

View File

@ -0,0 +1,112 @@
/*
* \brief Thread facility
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
/* Genode includes */
#include <base/printf.h>
#include <util/string.h>
/* core includes */
#include <platform_thread.h>
/* Codezero includes */
#include <codezero/syscalls.h>
enum { verbose_thread_start = true };
using namespace Genode;
using namespace Codezero;
int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no)
{
Native_thread_id pager = _pager ? _pager->cap().dst() : THREAD_INVALID;
/* setup thread context */
struct exregs_data exregs;
memset(&exregs, 0, sizeof(exregs));
exregs_set_stack(&exregs, (unsigned long)sp);
exregs_set_pc (&exregs, (unsigned long)ip);
exregs_set_pager(&exregs, pager);
exregs_set_utcb (&exregs, _utcb);
int ret = l4_exchange_registers(&exregs, _tid);
if (ret < 0) {
printf("l4_exchange_registers returned ret=%d\n", ret);
return -2;
}
/* start execution */
struct task_ids ids = { _tid, _space_id, _tid };
ret = l4_thread_control(THREAD_RUN, &ids);
if (ret < 0) {
printf("Error: l4_thread_control(THREAD_RUN) returned %d\n", ret);
return -3;
}
if (verbose_thread_start)
printf("core started thread \"%s\" with ID %d inside space ID %d\n",
_name, _tid, _space_id);
return 0;
}
void Platform_thread::pause()
{
PDBG("not implemented");
}
void Platform_thread::resume()
{
PDBG("not implemented");
}
void Platform_thread::state(Thread_state s)
{
PDBG("Not implemented");
throw Cpu_session::State_access_failed();
}
Thread_state Platform_thread::state()
{
PDBG("Not implemented");
throw Cpu_session::State_access_failed();
}
void Platform_thread::cancel_blocking()
{
PDBG("not implemented");
}
Weak_ptr<Address_space> Platform_thread::address_space()
{
return _address_space;
}
Platform_thread::Platform_thread(const char *name, unsigned, addr_t,
int thread_id)
: _tid(THREAD_INVALID)
{
strncpy(_name, name, sizeof(_name));
}
Platform_thread::~Platform_thread()
{
PDBG("not implemented");
}

View File

@ -0,0 +1,65 @@
/*
* \brief Export RAM dataspace as shared memory object (dummy)
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
/* Genode includes */
#include <base/printf.h>
#include <util/misc_math.h>
/* core includes */
#include <ram_session_component.h>
#include <platform.h>
#include <map_local.h>
using namespace Genode;
void Ram_session_component::_export_ram_ds(Dataspace_component *ds) { }
void Ram_session_component::_revoke_ram_ds(Dataspace_component *ds) { }
void Ram_session_component::_clear_ds (Dataspace_component *ds)
{
using namespace Codezero;
/*
* Map dataspace core-locally, memset, unmap dataspace
*/
size_t page_rounded_size = (ds->size() + get_page_size() - 1) & get_page_mask();
size_t num_pages = page_rounded_size >> get_page_size_log2();
/* allocate range in core's virtual address space */
void *virt_addr;
if (!platform()->region_alloc()->alloc(page_rounded_size, &virt_addr)) {
PERR("Could not allocate virtual address range in core of size %zd\n",
page_rounded_size);
return;
}
/* map the dataspace's physical pages to corresponding virtual addresses */
if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages)) {
PERR("core-local memory mapping failed\n");
return;
}
memset(virt_addr, 0, ds->size());
/* unmap dataspace from core */
if (!unmap_local((addr_t)virt_addr, num_pages)) {
PERR("could not unmap %zd pages from virtual address range at %p",
num_pages, virt_addr);
return;
}
/* free core's virtual address space */
platform()->region_alloc()->free(virt_addr, page_rounded_size);
}

View File

@ -0,0 +1,28 @@
/*
* \brief RM-session implementation
* \author Norman Feske
* \date 2009-10-02
*/
/*
* 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.
*/
/* core includes */
#include <rm_session_component.h>
#include <util.h>
/* Codezero includes */
#include <codezero/syscalls.h>
using namespace Genode;
using namespace Codezero;
void Rm_client::unmap(addr_t core_local_base, addr_t virt_base, size_t size)
{
l4_unmap((void *)virt_base, size >> get_page_size_log2(), badge());
}

View File

@ -0,0 +1,57 @@
TARGET = core
GEN_CORE_DIR = $(BASE_DIR)/src/core
SRC_CC += \
main.cc \
ram_session_component.cc \
ram_session_support.cc \
rom_session_component.cc \
cpu_session_component.cc \
cpu_session_support.cc \
pd_session_component.cc \
io_mem_session_component.cc \
io_mem_session_support.cc \
thread_start.cc \
platform_thread.cc \
platform_pd.cc \
platform_services.cc \
platform.cc \
dataspace_component.cc \
rm_session_component.cc \
rm_session_support.cc \
irq_session_component.cc \
signal_session_component.cc \
signal_source_component.cc \
trace_session_component.cc \
core_rm_session.cc \
core_mem_alloc.cc \
dump_alloc.cc \
context_area.cc
LIBS += core_printf base-common
INC_DIR += $(REP_DIR)/src/core/include \
$(GEN_CORE_DIR)/include \
$(REP_DIR)/include/codezero/dummies \
$(BASE_DIR)/src/base/thread
include $(GEN_CORE_DIR)/version.inc
vpath main.cc $(GEN_CORE_DIR)
vpath ram_session_component.cc $(GEN_CORE_DIR)
vpath rom_session_component.cc $(GEN_CORE_DIR)
vpath cpu_session_component.cc $(GEN_CORE_DIR)
vpath pd_session_component.cc $(GEN_CORE_DIR)
vpath rm_session_component.cc $(GEN_CORE_DIR)
vpath io_mem_session_component.cc $(GEN_CORE_DIR)
vpath io_mem_session_support.cc $(GEN_CORE_DIR)
vpath platform_services.cc $(GEN_CORE_DIR)
vpath signal_session_component.cc $(GEN_CORE_DIR)
vpath signal_source_component.cc $(GEN_CORE_DIR)
vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath dataspace_component.cc $(GEN_CORE_DIR)
vpath core_mem_alloc.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)
vpath context_area.cc $(GEN_CORE_DIR)
vpath %.cc $(REP_DIR)/src/core

View File

@ -0,0 +1,4 @@
include $(PRG_DIR)/target.inc
LD_TEXT_ADDR = 0x100000

View File

@ -0,0 +1,120 @@
/*
* \brief Implementation of Thread API interface for core
* \author Norman Feske
* \date 2006-05-03
*/
/*
* Copyright (C) 2006-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.
*/
/* Codezero includes */
#include <codezero/syscalls.h>
/* Genode includes */
#include <base/thread.h>
#include <base/printf.h>
#include <base/sleep.h>
/* core includes */
#include <platform.h>
#include <platform_thread.h>
enum { verbose_thread_start = true };
using namespace Genode;
void Thread_base::_deinit_platform_thread() { }
/**
* Create and start new thread
*
* \param space_no space ID in which the new thread will be executed
* \param sp initial stack pointer
* \param ip initial instruction pointer
* \return new thread ID, or
* negative error code
*/
inline int create_thread(unsigned space_no,
void *sp, void *ip,
int pager_tid = 1)
{
using namespace Codezero;
struct task_ids ids = { 1U, space_no, TASK_ID_INVALID };
/* allocate new thread at the kernel */
unsigned long flags = THREAD_CREATE | TC_SHARE_SPACE | TC_SHARE_GROUP;
int ret = l4_thread_control(flags, &ids);
if (ret < 0) {
PERR("l4_thread_control returned %d, spid=%d\n",
ret, ids.spid);
return -1;
}
unsigned long utcb_base_addr = (unsigned long)l4_get_utcb();
/* calculate utcb address of new thread */
unsigned long new_utcb = utcb_base_addr + ids.tid*sizeof(struct utcb);
/* setup thread context */
struct exregs_data exregs;
memset(&exregs, 0, sizeof(exregs));
exregs_set_stack(&exregs, (unsigned long)sp);
exregs_set_pc (&exregs, (unsigned long)ip);
exregs_set_pager(&exregs, pager_tid);
exregs_set_utcb (&exregs, new_utcb);
ret = l4_exchange_registers(&exregs, ids.tid);
if (ret < 0) {
printf("l4_exchange_registers returned ret=%d\n", ret);
return -2;
}
/* start execution */
ret = l4_thread_control(THREAD_RUN, &ids);
if (ret < 0) {
printf("Error: l4_thread_control(THREAD_RUN) returned %d\n", ret);
return -3;
}
/* return new thread ID allocated by the kernel */
return ids.tid;
}
void Thread_base::_thread_start()
{
Thread_base::myself()->_thread_bootstrap();
Thread_base::myself()->entry();
sleep_forever();
}
void Thread_base::start()
{
/* create and start platform thread */
_tid.pt = new(platform()->core_mem_alloc()) Platform_thread(_context->name);
_tid.l4id = create_thread(1, stack_top(), (void *)&_thread_start);
if (_tid.l4id < 0)
PERR("create_thread returned %d", _tid.l4id);
if (verbose_thread_start)
printf("core started local thread \"%s\" with ID %d\n",
_context->name, _tid.l4id);
}
void Thread_base::cancel_blocking()
{
PWRN("not implemented");
}

View File

@ -0,0 +1,74 @@
TARGET = codezero
-include $(BUILD_BASE_DIR)/etc/codezero.conf
ifeq ($(wildcard $(CODEZERO_DIR)),)
$(error No valid kernel configured in 'etc/codezero.conf')
endif
include $(REP_DIR)/lib/mk/codezero_cml.inc
TOOL_CHAIN_DIR = $(dir $(CROSS_DEV_PREFIX))
CODEZERO_DST_DIR = $(BUILD_BASE_DIR)/kernel/codezero
CODEZERO_BUILD_DIR = $(CODEZERO_DST_DIR)/build
.PHONY: $(TARGET)
MIRROR_COPY := conts/baremetal/empty conts/userlibs \
build.py include SConstruct src loader
MIRROR_SYMLINK := scripts tools
update_copy = $(VERBOSE)tar c -C $(CODEZERO_DIR) $(MIRROR_COPY) | tar x -C $(CODEZERO_DST_DIR)
ifneq ($(VERBOSE),)
CODEZERO_STDOUT := > /dev/null
endif
#
# Environment variables passed to the Codezero build system
#
BUILD_ENV = PATH=$(dir $(CROSS_DEV_PREFIX)):$$PATH
#
# Local copy of the CML file used for supplying the configuration
# to the Codezero build system.
#
LOCAL_CONFIG_CML := $(shell pwd)/config.cml
$(TARGET): $(CODEZERO_BUILD_DIR)
$(MSG_BUILD)kernel
$(update_copy)
$(VERBOSE)cd $(CODEZERO_DST_DIR); $(BUILD_ENV) ./build.py $(CODEZERO_STDOUT)
#
# Mirror the parts of the Codezero source tree that are relevant for building
# the kernel
#
$(CODEZERO_DST_DIR): $(CODEZERO_DIR)
$(VERBOSE)test -d $@ || mkdir -p $@
$(VERBOSE)for d in $(MIRROR_SYMLINK); do ln -sf $(realpath $^)/$$d $@/$$d; done
$(CODEZERO_BUILD_DIR): $(CODEZERO_DST_DIR) $(CODEZERO_CML)
$(update_copy)
$(VERBOSE)cp $(CODEZERO_CML) $(LOCAL_CONFIG_CML)
@#
@# Create copy of the CML config in the local build directory to update
@# the tool chain parameters according to the CROSS_DEV_PREFIX configured
@# for Genode.
@#
$(VERBOSE)sed -i "/TOOLCHAIN_USERSPACE/s/\".*\"/\"$(notdir $(CROSS_DEV_PREFIX))\"/" $(LOCAL_CONFIG_CML)
$(VERBOSE)sed -i "/TOOLCHAIN_KERNEL/s/\".*\"/\"$(notdir $(CROSS_DEV_PREFIX))\"/" $(LOCAL_CONFIG_CML)
$(VERBOSE)cd $(CODEZERO_DST_DIR); $(BUILD_ENV) ./build.py -C -b -f $(LOCAL_CONFIG_CML) $(CODEZERO_STDOUT)
clean cleanall: clean_codezero
#
# Make sure to execute the 'clean_codezero' rule prior the generic clean
# rule in 'prg.mk' because the generic rule will attempt to remove $(TARGET)
# file, which is a directory in our case.
#
clean_prg_objects: clean_codezero
clean_codezero:
$(VERBOSE)rm -f $(LOCAL_CONFIG_CML)
$(VERBOSE)rm -rf $(CODEZERO_DST_DIR)

View File

@ -0,0 +1,131 @@
/*
* \brief Linker script for Genode programs
* \author Christian Helmuth
* \date 2006-04-12
*/
/*
* Copyright (C) 2006-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.
*/
/* values taken from Codezero's mm0 linker script */
/*physical_base = 0x00208000;*/
/*virtual_base = 0xe0000000;*/
/*offset = virtual_base - physical_base;*/
/*
* Addresses correspond to the linker script generated by
* the Codezero build system.
*/
vma_start = 0x100000;
lma_start = 0x40000;
offset = vma_start - lma_start;
ENTRY(_start)
PHDRS
{
ro PT_LOAD;
rw PT_LOAD;
}
SECTIONS
{
. = vma_start;
.text : AT (ADDR(.text) - offset) {
/* begin of program image (link address) */
_prog_img_beg = .;
*(.text.crt0)
*(.init)
*(.text .text.* .gnu.linkonce.t.*)
*(.fini)
*(.rodata .rodata.* .gnu.linkonce.r.*)
. = ALIGN(0x08);
_ctors_start = .;
KEEP (*(.ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.init_array)) /* list of constructors specific for ARM eabi */
_ctors_end = .;
_dtors_start = .;
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
_dtors_end = .;
} : ro = 0x90909090
/* Linux: exception section for uaccess mechanism */
__ex_table : { *(__ex_table) }
.eh_frame_hdr : { *(.eh_frame_hdr) }
. = ALIGN(0x1000);
_prog_img_data = .;
.data : AT (ADDR(.data) - offset) {
/*
* Leave space for parent capability parameters at start of data
* section. The protection domain creator is reponsible for storing
* sane values here.
*/
_parent_cap = .;
LONG(0xffffffff);
LONG(0xffffffff);
_vma_start = .;
LONG(vma_start);
_lma_start = .;
LONG(lma_start);
*(.data .data.* .gnu.linkonce.d.*)
} : rw
/* exception frames for C++ */
.eh_frame : {
__eh_frame_start__ = .;
KEEP (*(.eh_frame))
LONG(0)
} : rw
.init_array : {
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
}
.gcc_except_table : { KEEP(*(.gcc_except_table)) }
.dynamic : { *(.dynamic) }
/* .ARM.exidx is sorted, so has to go in its own output section */
__exidx_start = .;
.ARM.exidx : {
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
}
__exidx_end = .;
.ARM.extab : {
*(.ARM.extab*)
} : rw
. = ALIGN(4);
.bss : AT (ADDR(.bss) - offset) {
*(.bss .bss.* .gnu.linkonce.b.* COMMON)
}
/* end of program image -- must be after last section */
_prog_img_end = .;
/DISCARD/ : {
*(.note)
*(.note.ABI-tag)
*(.comment)
}
}