mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-21 00:23:16 +00:00
Imported Genode release 11.11
This commit is contained in:
committed by
Christian Helmuth
parent
6bcc9aef0e
commit
da4e1feaa5
78
base-codezero/src/base/console/pl011/core_console.h
Normal file
78
base-codezero/src/base/console/pl011/core_console.h
Normal 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-2011 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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
53
base-codezero/src/base/cxx/exception.cc
Normal file
53
base-codezero/src/base/cxx/exception.cc
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* \brief Support for exceptions libsupc++
|
||||
* \author Norman Feske
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2006-07-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2011 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__);
|
||||
}
|
24
base-codezero/src/base/cxx/memcmp.cc
Normal file
24
base-codezero/src/base/cxx/memcmp.cc
Normal 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-2011 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;
|
||||
}
|
175
base-codezero/src/base/ipc/ipc.cc
Normal file
175
base-codezero/src/base/ipc/ipc.cc
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* \brief Codezero implementation of the IPC API
|
||||
* \author Norman Feske
|
||||
* \date 2009-10-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2011 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.tid().tid, _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.tid().tid, L4_IPC_TAG_SYNC_EXTENDED,
|
||||
snd_size, _snd_msg->addr());
|
||||
if (ret < 0)
|
||||
PERR("l4_send_extended (to thread %d) returned ret=%d",
|
||||
_dst.tid().tid, 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",
|
||||
tid().tid, _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",
|
||||
tid().tid, 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 = _dst.tid().tid;
|
||||
_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)
|
||||
: 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 */
|
||||
_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)
|
||||
{ }
|
175
base-codezero/src/base/ipc/pager.cc
Normal file
175
base-codezero/src/base/ipc/pager.cc
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* \brief Pager support for Codezero
|
||||
* \author Norman Feske
|
||||
* \date 2010-02-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2011 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.tid);
|
||||
|
||||
/* wake up faulter if mapping succeeded */
|
||||
if (ret < 0)
|
||||
PERR("l4_map returned %d, putting thread %d to sleep", ret, _last.tid);
|
||||
else
|
||||
acknowledge_wakeup();
|
||||
|
||||
/* wait for next page fault */
|
||||
wait_for_fault();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_pager::acknowledge_wakeup()
|
||||
{
|
||||
enum { SUCCESS = 0 };
|
||||
l4_set_sender(_last.tid);
|
||||
l4_ipc_return(SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
Ipc_pager::Ipc_pager() : Native_capability(thread_myself(), 0) { }
|
||||
|
48
base-codezero/src/base/lock/cmpxchg.cc
Normal file
48
base-codezero/src/base/lock/cmpxchg.cc
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* \brief Codezero-specific implementation of cmpxchg
|
||||
* \author Norman Feske
|
||||
* \date 2009-10-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2011 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;
|
||||
}
|
63
base-codezero/src/base/lock/lock.cc
Normal file
63
base-codezero/src/base/lock/lock.cc
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* \brief Lock implementation
|
||||
* \author Norman Feske
|
||||
* \date 2007-10-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007-2011 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/cancelable_lock.h>
|
||||
#include <base/printf.h>
|
||||
#include <cpu/atomic.h>
|
||||
|
||||
/* Codezero includes */
|
||||
#include <codezero/syscalls.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Cancelable_lock::Cancelable_lock(Cancelable_lock::State initial)
|
||||
:
|
||||
_native_lock(UNLOCKED)
|
||||
{
|
||||
if (initial == LOCKED)
|
||||
lock();
|
||||
}
|
||||
|
||||
|
||||
void Cancelable_lock::lock()
|
||||
{
|
||||
while (!cmpxchg(&_native_lock, UNLOCKED, LOCKED))
|
||||
Codezero::l4_thread_switch(-1);
|
||||
}
|
||||
|
||||
|
||||
void Cancelable_lock::unlock()
|
||||
{
|
||||
_native_lock = UNLOCKED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Printf implementation to make Codezero's syscall bindings happy.
|
||||
*
|
||||
* We need a better place for this function - actually, the best would be not
|
||||
* to need this function at all. As of now, 'printf' is referenced by
|
||||
* Codezero's libl4, in particular by the mutex implementation.
|
||||
*/
|
||||
extern "C" void printf(const char *format, ...) __attribute__((weak));
|
||||
extern "C" void printf(const char *format, ...)
|
||||
{
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
|
||||
vprintf(format, list);
|
||||
|
||||
va_end(list);
|
||||
}
|
112
base-codezero/src/base/lock/lock_helper.h
Normal file
112
base-codezero/src/base/lock/lock_helper.h
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* \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-2011 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>
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
static Codezero::l4_mutex main_running_lock = { -1 };
|
||||
|
||||
|
||||
static inline void thread_yield()
|
||||
{
|
||||
Codezero::l4_thread_switch(-1);
|
||||
}
|
||||
|
||||
|
||||
static inline bool thread_id_valid(Genode::Native_thread_id tid)
|
||||
{
|
||||
return tid.tid != Codezero::NILTHREAD;
|
||||
}
|
||||
|
||||
|
||||
static bool thread_check_stopped_and_restart(Genode::Native_thread_id tid)
|
||||
{
|
||||
if (!thread_id_valid(tid))
|
||||
return false;
|
||||
|
||||
Codezero::l4_mutex_unlock(tid.running_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static inline Genode::Native_thread_id thread_get_my_native_id()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Codezero::l4_mutex *running_lock = 0;
|
||||
|
||||
/* obtain pointer to running lock of calling thread */
|
||||
if (Thread_base::myself())
|
||||
running_lock = Thread_base::myself()->utcb()->running_lock();
|
||||
else {
|
||||
running_lock = &main_running_lock;
|
||||
if (running_lock->lock == -1) {
|
||||
Codezero::l4_mutex_init(running_lock);
|
||||
Codezero::l4_mutex_lock(running_lock); /* block on first mutex lock */
|
||||
}
|
||||
}
|
||||
|
||||
return Genode::Native_thread_id(Codezero::thread_myself(), running_lock);
|
||||
}
|
||||
|
||||
|
||||
static inline Genode::Native_thread_id thread_invalid_id()
|
||||
{
|
||||
return Genode::Native_thread_id(Codezero::NILTHREAD, 0);
|
||||
}
|
||||
|
||||
|
||||
static inline void thread_switch_to(Genode::Native_thread_id tid)
|
||||
{
|
||||
if (thread_id_valid(tid))
|
||||
Codezero::l4_thread_switch(tid.tid);
|
||||
}
|
||||
|
||||
|
||||
static inline void thread_stop_myself()
|
||||
{
|
||||
Genode::Native_thread_id myself = thread_get_my_native_id();
|
||||
Codezero::l4_mutex_lock(myself.running_lock);
|
||||
}
|
101
base-codezero/src/base/pager/pager.cc
Normal file
101
base-codezero/src/base/pager/pager.cc
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* \brief Dummy pager framework
|
||||
* \author Norman Feske
|
||||
* \date 2009-10-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2011 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();
|
||||
|
||||
pager.wait_for_fault();
|
||||
while (1) {
|
||||
|
||||
/* lookup referenced object */
|
||||
Pager_object *obj = _ep ? _ep->obj_by_id(pager.badge()) : 0;
|
||||
|
||||
/* handle request */
|
||||
if (obj) {
|
||||
if (obj->pager(pager))
|
||||
/* something strange occured - leave thread in pagefault */
|
||||
pager.wait_for_fault();
|
||||
else
|
||||
pager.reply_and_wait_for_fault();
|
||||
} else {
|
||||
|
||||
/*
|
||||
* 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.wait_for_fault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
** 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(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().tid(), 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);
|
||||
}
|
79
base-codezero/src/base/thread/thread_start.cc
Normal file
79
base-codezero/src/base/thread/thread_start.cc
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* \brief NOVA-specific implementation of the Thread API
|
||||
* \author Norman Feske
|
||||
* \date 2010-01-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2011 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();
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Thread base **
|
||||
*****************/
|
||||
|
||||
void Thread_base::_init_platform_thread()
|
||||
{
|
||||
Codezero::l4_mutex_init(utcb()->running_lock());
|
||||
Codezero::l4_mutex_lock(utcb()->running_lock()); /* block on first mutex lock */
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::_deinit_platform_thread()
|
||||
{
|
||||
env()->cpu_session()->kill_thread(_thread_cap);
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::start()
|
||||
{
|
||||
/* create thread at core */
|
||||
char buf[48];
|
||||
name(buf, sizeof(buf));
|
||||
_thread_cap = env()->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_capability pager_cap = env()->rm_session()->add_client(_thread_cap);
|
||||
env()->cpu_session()->set_pager(_thread_cap, pager_cap);
|
||||
|
||||
/* register initial IP and SP at core */
|
||||
addr_t thread_sp = (addr_t)&_context->stack[-4];
|
||||
thread_sp &= ~0xf; /* align initial stack to 16 byte boundary */
|
||||
env()->cpu_session()->start(_thread_cap, (addr_t)_thread_start, thread_sp);
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::cancel_blocking()
|
||||
{
|
||||
Codezero::l4_mutex_unlock(utcb()->running_lock());
|
||||
env()->cpu_session()->cancel_blocking(_thread_cap);
|
||||
}
|
Reference in New Issue
Block a user