Run Genode directly on hardware with 'base-hw'.

This commit is contained in:
Martin Stein
2012-05-30 20:13:09 +02:00
committed by Norman Feske
parent 8220ea272c
commit ff65f6f021
81 changed files with 7800 additions and 1 deletions

View File

@ -0,0 +1,160 @@
/*
* \brief Syscall-framework implementation for ARM V7A systems
* \author Martin stein
* \date 2011-11-30
*/
/*
* Copyright (C) 2011-2012 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/syscall.h>
using namespace Kernel;
/******************************************************************
** Inline assembly templates for syscalls with 1 to 6 arguments **
******************************************************************/
#define SYSCALL_6_ASM_OPS \
"mov r5, #0 \n" \
"add r5, %[arg_5] \n" \
SYSCALL_5_ASM_OPS
#define SYSCALL_5_ASM_OPS \
"mov r4, #0 \n" \
"add r4, %[arg_4] \n" \
SYSCALL_4_ASM_OPS
#define SYSCALL_4_ASM_OPS \
"mov r3, #0 \n" \
"add r3, %[arg_3] \n" \
SYSCALL_3_ASM_OPS
#define SYSCALL_3_ASM_OPS \
"mov r2, #0 \n" \
"add r2, %[arg_2] \n" \
SYSCALL_2_ASM_OPS
#define SYSCALL_2_ASM_OPS \
"mov r1, #0 \n" \
"add r1, %[arg_1] \n" \
SYSCALL_1_ASM_OPS
#define SYSCALL_1_ASM_OPS \
"mov r0, #0 \n" \
"add r0, %[arg_0] \n" \
"svc 0x0 \n" \
"mov %[result], #0 \n" \
"add %[result], r0 "
/*****************************************************************************
** Inline assembly "writeable" template-args for syscalls with 1 to 6 args **
*****************************************************************************/
#define SYSCALL_6_ASM_WRITE [arg_5] "+r" (arg_5), SYSCALL_5_ASM_WRITE
#define SYSCALL_5_ASM_WRITE [arg_4] "+r" (arg_4), SYSCALL_4_ASM_WRITE
#define SYSCALL_4_ASM_WRITE [arg_3] "+r" (arg_3), SYSCALL_3_ASM_WRITE
#define SYSCALL_3_ASM_WRITE [arg_2] "+r" (arg_2), SYSCALL_2_ASM_WRITE
#define SYSCALL_2_ASM_WRITE [arg_1] "+r" (arg_1), SYSCALL_1_ASM_WRITE
#define SYSCALL_1_ASM_WRITE \
[arg_0] "+r" (arg_0), \
[result] "+r" (result)
/**********************************************************************
** Inline assembly clobber lists for syscalls with 1 to 6 arguments **
**********************************************************************/
#define SYSCALL_6_ASM_CLOBBER "r5", SYSCALL_5_ASM_CLOBBER
#define SYSCALL_5_ASM_CLOBBER "r4", SYSCALL_4_ASM_CLOBBER
#define SYSCALL_4_ASM_CLOBBER "r3", SYSCALL_3_ASM_CLOBBER
#define SYSCALL_3_ASM_CLOBBER "r2", SYSCALL_2_ASM_CLOBBER
#define SYSCALL_2_ASM_CLOBBER "r1", SYSCALL_1_ASM_CLOBBER
#define SYSCALL_1_ASM_CLOBBER "r0"
/************************************
** Syscalls with 1 to 6 arguments **
************************************/
Syscall_ret Kernel::syscall(Syscall_arg arg_0)
{
Syscall_ret result = 0;
asm volatile(SYSCALL_1_ASM_OPS
: SYSCALL_1_ASM_WRITE
:: SYSCALL_1_ASM_CLOBBER);
return result;
}
Syscall_ret Kernel::syscall(Syscall_arg arg_0,
Syscall_arg arg_1)
{
Syscall_ret result = 0;
asm volatile(SYSCALL_2_ASM_OPS
: SYSCALL_2_ASM_WRITE
:: SYSCALL_2_ASM_CLOBBER);
return result;
}
Syscall_ret Kernel::syscall(Syscall_arg arg_0,
Syscall_arg arg_1,
Syscall_arg arg_2)
{
Syscall_ret result = 0;
asm volatile(SYSCALL_3_ASM_OPS
: SYSCALL_3_ASM_WRITE
:: SYSCALL_3_ASM_CLOBBER);
return result;
}
Syscall_ret Kernel::syscall(Syscall_arg arg_0,
Syscall_arg arg_1,
Syscall_arg arg_2,
Syscall_arg arg_3)
{
Syscall_ret result = 0;
asm volatile(SYSCALL_4_ASM_OPS
: SYSCALL_4_ASM_WRITE
:: SYSCALL_4_ASM_CLOBBER);
return result;
}
Syscall_ret Kernel::syscall(Syscall_arg arg_0,
Syscall_arg arg_1,
Syscall_arg arg_2,
Syscall_arg arg_3,
Syscall_arg arg_4)
{
Syscall_ret result = 0;
asm volatile(SYSCALL_5_ASM_OPS
: SYSCALL_5_ASM_WRITE
:: SYSCALL_5_ASM_CLOBBER);
return result;
}
Syscall_ret Kernel::syscall(Syscall_arg arg_0,
Syscall_arg arg_1,
Syscall_arg arg_2,
Syscall_arg arg_3,
Syscall_arg arg_4,
Syscall_arg arg_5)
{
Syscall_ret result = 0;
asm volatile(SYSCALL_6_ASM_OPS
: SYSCALL_6_ASM_WRITE
:: SYSCALL_6_ASM_CLOBBER);
return result;
}

View File

@ -0,0 +1,73 @@
/**
* \brief Genode-console backend
* \author Martin Stein
* \date 2011-10-17
*/
/*
* Copyright (C) 2011-2012 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>
#include <base/printf.h>
#include <drivers/serial_log.h>
namespace Genode
{
/**
* Platform specific Genode console
*/
class Platform_console : public Console,
public Serial_log
{
enum { BAUD_RATE = 115200 };
protected:
/**
* Print a char to the console
*/
void _out_char(char c) { Serial_log::put_char(c); }
public:
/**
* Constructor
*/
Platform_console() : Serial_log(BAUD_RATE) { }
};
}
using namespace Genode;
/**
* Static object to print log output
*/
static Platform_console * platform_console()
{
static Platform_console static_platform_console;
return &static_platform_console;
}
/****************************
** Genode print functions **
****************************/
void Genode::printf(const char *format, ...)
{
va_list list;
va_start(list, format);
platform_console()->vprintf(format, list);
va_end(list);
}
void Genode::vprintf(const char *format, va_list list)
{ platform_console()->vprintf(format, list); }

220
base-hw/src/base/ipc.cc Normal file
View File

@ -0,0 +1,220 @@
/*
* \brief Implementation of the Genode IPC-framework
* \author Martin Stein
* \date 2012-02-12
*/
/*
* Copyright (C) 2012 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.h>
#include <base/thread.h>
#include <kernel/syscalls.h>
#include <kernel/log.h>
using namespace Genode;
enum
{
/* size of the callee-local name of a targeted RPC object */
RPC_OBJECT_ID_SIZE = sizeof(umword_t),
/*
* The RPC framework marshalls a return value into reply messages to
* deliver exceptions, wich occured during the RPC call to the caller.
* This defines the size of this value.
*/
RPC_RETURN_VALUE_SIZE = sizeof(umword_t),
};
/***************
** Utilities **
***************/
/**
* Translate byte size 's' to size in words
*/
static unsigned long size_in_words(unsigned long const s)
{ return (s + sizeof(unsigned long) - 1) / sizeof(unsigned long); }
/**
* Copy message payload to message buffer
*/
static void copy_utcb_to_msgbuf(Msgbuf_base * const receive_buffer,
unsigned long const message_size)
{
/* log data that is received via IPC */
enum { VERBOSE = 0 };
/* get pointers and message attributes */
Native_utcb * const utcb = Thread_base::myself()->utcb();
unsigned long * const msgbuf = (unsigned long *)receive_buffer->buf;
unsigned long const message_wsize = size_in_words(message_size);
/* assertions, avoid 'printf' in here, it may lead to infinite recursion */
if (message_wsize > size_in_words(utcb->size()))
{
kernel_log() << __PRETTY_FUNCTION__ << ": Oversized message\n";
while (1) ;
}
/* fill message buffer with message */
for (unsigned i=0; i < message_wsize; i++)
msgbuf[i] = *utcb->word(i);
}
/**
* Copy message payload to the UTCB
*/
static void copy_msgbuf_to_utcb(Msgbuf_base * const send_buffer,
unsigned long const message_size,
unsigned long const local_name)
{
/* log data that is send via IPC */
enum { VERBOSE = 0 };
/* get pointers and message attributes */
Native_utcb * const utcb = Thread_base::myself()->utcb();
unsigned long * const msgbuf = (unsigned long *)send_buffer->buf;
unsigned long const message_wsize = size_in_words(message_size);
/* assertions, avoid 'printf' in here, it may lead to infinite recursion */
if (message_wsize > size_in_words(utcb->size()))
{
kernel_log() << __PRETTY_FUNCTION__ << ": Oversized message\n";
while (1) ;
}
/* address message to an object that the targeted thread knows */
*utcb->word(0) = local_name;
/* write message payload */
for (unsigned long i = 1; i < message_wsize; i++)
*utcb->word(i) = msgbuf[i];
}
/*****************
** Ipc_ostream **
*****************/
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
:
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
_snd_msg(snd_msg), _dst(dst)
{
_write_offset = RPC_OBJECT_ID_SIZE;
}
/*****************
** Ipc_istream **
*****************/
void Ipc_istream::_wait()
{
/* FIXME this shall be not supported */
Kernel::pause_thread();
}
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
:
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
Native_capability(Genode::thread_get_my_native_id(), 0),
_rcv_msg(rcv_msg), _rcv_cs(-1)
{ _read_offset = RPC_OBJECT_ID_SIZE; }
Ipc_istream::~Ipc_istream() { }
/****************
** Ipc_client **
****************/
void Ipc_client::_call()
{
using namespace Kernel;
/* send request and receive reply */
copy_msgbuf_to_utcb(_snd_msg, _write_offset,
Ipc_ostream::_dst.local_name());
size_t const s = request_and_wait(Ipc_ostream::_dst.dst(), _write_offset);
copy_utcb_to_msgbuf(_rcv_msg, s);
/* reset unmarshaller */
_write_offset = _read_offset = RPC_OBJECT_ID_SIZE;
}
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 **
****************/
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)
{ }
void Ipc_server::_prepare_next_reply_wait()
{
/* now we have a request to reply */
_reply_needed = true;
/* leave space for RPC method return value */
_write_offset = RPC_OBJECT_ID_SIZE + RPC_RETURN_VALUE_SIZE;
/* reset unmarshaller */
_read_offset = RPC_OBJECT_ID_SIZE;
}
void Ipc_server::_wait()
{
/* receive next request */
copy_utcb_to_msgbuf(_rcv_msg, Kernel::wait_for_request());
/* update server state */
_prepare_next_reply_wait();
}
void Ipc_server::_reply()
{
kernel_log() << __PRETTY_FUNCTION__ << ": Unexpected call\n";
while (1) ;
}
void Ipc_server::_reply_wait()
{
/* if there is no reply simply do wait for request */
/* FIXME this shall be not supported */
if (!_reply_needed) {
_wait();
return;
}
/* send reply and receive next request */
copy_msgbuf_to_utcb(_snd_msg, _write_offset,
Ipc_ostream::_dst.local_name());
copy_utcb_to_msgbuf(_rcv_msg, Kernel::reply_and_wait(_write_offset));
/* update server state */
_prepare_next_reply_wait();
}

View File

@ -0,0 +1,58 @@
/*
* \brief Helper functions for the Lock implementation
* \author Martin Stein
* \date 2011-01-02
*/
/*
* Copyright (C) 2011-2012 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 _SRC__BASE__LOCK__LOCK_HELPER_H_
#define _SRC__BASE__LOCK__LOCK_HELPER_H_
/* Genode includes */
#include <base/native_types.h>
/**
* Yield CPU to any other thread
*/
static inline void thread_yield()
{ Kernel::yield_thread(); }
/**
* Yield CPU to a specified thread 't'
*/
static inline void
thread_switch_to(Genode::Native_thread_id const t)
{ Kernel::yield_thread(t); }
/**
* Resume another thread 't' and return if it were paused or not
*/
static inline bool
thread_check_stopped_and_restart(Genode::Native_thread_id const t)
{ return Kernel::resume_thread(t) == 0; }
/**
* Validation kernel thread-identifier 'id'
*/
static inline bool thread_id_valid(Genode::Native_thread_id const id)
{ return id != Genode::thread_invalid_id(); }
/**
* Exclude ourselves from CPU scheduling for now
*/
static inline void thread_stop_myself() { Kernel::pause_thread(); }
#endif /* _SRC__BASE__LOCK__LOCK_HELPER_H_ */

127
base-hw/src/base/pager.cc Normal file
View File

@ -0,0 +1,127 @@
/*
* \brief Pager implementations that are specific for the HW-core
* \author Martin Stein
* \date 2012-03-29
*/
/*
* Copyright (C) 2012 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>
#include <base/printf.h>
using namespace Genode;
/***************************
** Pager_activation_base **
***************************/
void Pager_activation_base::entry()
{
/* acknowledge that we're ready to work */
Ipc_pager pager;
_cap = pager;
_cap_valid.unlock();
/* wait for the first pagefault */
pager.wait_for_fault();
while (1)
{
/* lookup pager object for the current faulter */
Pager_object * o = _ep ? _ep->obj_by_id(pager.badge()) : 0;
if (!o) {
PERR("%s:%d: Invalid pager object", __FILE__, __LINE__);
while (1) ;
}
/* let pager handle the pagefault, apply mapping, await pagefault */
if (o->pager(pager)) pager.wait_for_fault();
else pager.resolve_and_wait_for_fault();
}
}
/**********************
** Pager_entrypoint **
**********************/
Pager_entrypoint::Pager_entrypoint(Cap_session *,
Pager_activation_base * const a)
: _activation(a) { _activation->ep(this); }
void Pager_entrypoint::dissolve(Pager_object * const o) { remove(o); }
Pager_capability Pager_entrypoint::manage(Pager_object * const o)
{
/* do we have an activation */
if (!_activation) return Pager_capability();
/* create cap with the object badge as local name */
Native_capability c;
c = Native_capability(_activation->cap().dst(), o->badge());
/* let activation provide the pager object */
o->cap(c);
insert(o);
/* return pager-object cap */
return reinterpret_cap_cast<Pager_object>(c);
}
/***************
** Ipc_pager **
***************/
void Ipc_pager::wait_for_fault()
{
/* receive first message */
size_t s = Kernel::wait_for_request();
while (1) {
switch (s) {
case sizeof(Pagefault): {
/* message is a pagefault */
Native_utcb * const utcb = Thread_base::myself()->utcb();
Pagefault * const pf = (Pagefault *)utcb;
if (pf->valid())
{
/* give our caller the chance to handle the fault */
_pagefault = *pf;
return;
}
/* pagefault is invalid so get the next message */
else {
PERR("%s:%d: Invalid pagefault", __FILE__, __LINE__);
continue;
}
continue; }
case sizeof(Pagefault_resolved): {
/* message is a release request from a RM session */
Native_utcb * const utcb = Thread_base::myself()->utcb();
Pagefault_resolved * const msg = (Pagefault_resolved *)utcb;
/* resume faulter, send ack to RM and get the next message */
Kernel::resume_thread(msg->pager_object->badge());
s = Kernel::reply_and_wait(0);
continue; }
default: {
PERR("%s:%d: Invalid message format", __FILE__, __LINE__);
continue; }
}
}
}

View File

@ -0,0 +1,130 @@
/*
* \brief Implementations of the signaling framework specific for HW-core
* \author Martin Stein
* \date 2012-05-05
*/
/*
* Copyright (C) 2012 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/signal.h>
#include <signal_session/connection.h>
#include <kernel/syscalls.h>
using namespace Genode;
/**
* Provide a static signal connection
*/
static Signal_connection * signal_connection()
{
static Signal_connection _object;
return &_object;
}
/*********************
** Signal_receiver **
*********************/
Signal_receiver::Signal_receiver() :
_cap(signal_connection()->alloc_receiver())
{
if (!_cap.valid()) {
PERR("%s: Failed to create receiver", __PRETTY_FUNCTION__);
while (1) ;
}
}
Signal_receiver::~Signal_receiver()
{
/* dissolve all contexts that are managed by us */
Lock::Guard contexts_guard(_contexts_lock);
while (1) {
Signal_context * const c = _contexts.first();
if (!c) break;
Lock::Guard context_guard(c->_lock);
_unsync_dissolve(c);
}
}
Signal_context_capability Signal_receiver::manage(Signal_context * const c)
{
/* check if the context is already managed */
Lock::Guard contexts_guard(_contexts_lock);
Lock::Guard context_guard(c->_lock);
if (c->_receiver) throw Context_already_in_use();
/* create a kernel object that corresponds to the context */
bool session_upgraded = 0;
Signal_connection * const s = signal_connection();
while (1) {
try {
c->_cap = s->alloc_context(_cap, (unsigned long)c);
break;
} catch (Signal_session::Out_of_metadata)
{
/* upgrade session quota and try again, but only once */
if (session_upgraded) return Signal_context_capability();
env()->parent()->upgrade(s->cap(), "ram_quota=4K");
session_upgraded = 1;
}
}
/* assign the context to us */
c->_receiver = this;
_contexts.insert(c);
return c->_cap;
}
Signal Signal_receiver::wait_for_signal()
{
/* await a signal */
Kernel::await_signal(_cap.dst());
Signal s = *(Signal *)Thread_base::myself()->utcb();
Signal_context * c = s.context();
/* check if the context of the signal is managed by us */
Lock::Guard context_guard(c->_lock);
if (c->_receiver != this) {
PERR("%s: Context not managed by this receiver", __PRETTY_FUNCTION__);
while (1) ;
}
/* check attributes of the signal and return it */
if (s.num() == 0) PWRN("Returning signal with num == 0");
return s;
}
void Signal_receiver::dissolve(Signal_context * const c)
{
/* check if the context is managed by us */
Lock::Guard contexts_guard(_contexts_lock);
Lock::Guard context_guard(c->_lock);
if (c->_receiver != this) throw Context_not_associated();
/* unassign the context */
_unsync_dissolve(c);
}
void Signal_receiver::_unsync_dissolve(Signal_context * const c)
{
/* reset the context */
c->_receiver = 0;
c->_cap = Signal_context_capability();
/* forget the context */
_contexts.remove(c);
}

View File

@ -0,0 +1,91 @@
/**
* \brief Platform specific parts of the thread API
* \author Martin Stein
* \date 2012-02-12
*/
/*
* Copyright (C) 2012 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>
using namespace Genode;
extern Native_utcb * _main_utcb;
namespace Genode { Rm_session *env_context_area_rm_session(); }
/*****************
** Thread_base **
*****************/
Native_utcb * Thread_base::utcb()
{
/* this is a main thread, so CRT0 provides UTCB through '_main_utcb' */
if (!this) return _main_utcb;
/* otherwise we have a valid thread base */
return &_context->utcb;
}
void Thread_base::_thread_start()
{
Thread_base::myself()->_thread_bootstrap();
Thread_base::myself()->entry();
Genode::sleep_forever();
}
void Thread_base::_init_platform_thread() { }
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));
Cpu_session * cpu = env()->cpu_session();
_thread_cap = cpu->create_thread(buf, (addr_t)&_context->utcb);
/* 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);
/* attach UTCB */
try {
Ram_dataspace_capability ds = env()->cpu_session()->utcb(_thread_cap);
size_t const size = sizeof(_context->utcb);
addr_t dst = Context_allocator::addr_to_base(_context) +
CONTEXT_VIRTUAL_SIZE - size - CONTEXT_AREA_VIRTUAL_BASE;
env_context_area_rm_session()->attach_at(ds, dst, size);
} catch (...) {
PERR("%s: Failed to attach UTCB", __PRETTY_FUNCTION__);
sleep_forever();
}
/* start thread with its initial IP and aligned SP */
addr_t thread_sp = (addr_t)&_context->stack[-4];
thread_sp &= ~0xf;
env()->cpu_session()->start(_thread_cap, (addr_t)_thread_start, thread_sp);
}
void Thread_base::cancel_blocking()
{ env()->cpu_session()->cancel_blocking(_thread_cap); }

View File

@ -0,0 +1,33 @@
/*
* \brief Dummy version of a boot modules file to enable a 'core' standalone image
* \author Martin Stein
* \date 2011-12-16
*/
/*
* Copyright (C) 2011-2012 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.
*/
.section .data
.align 3
.global _boot_modules_begin
_boot_modules_begin:
.string "GROM"
.align 3
.global _boot_module_headers_begin
_boot_module_headers_begin:
/* no module headers */
.global _boot_module_headers_end
_boot_module_headers_end:
/* no modules */
.global _boot_modules_end
_boot_modules_end:

View File

@ -0,0 +1,72 @@
/*
* \brief Startup code for the Genode Kernel on ARM
* \author Martin Stein
* \author Stefan Kalkowski
* \date 2011-10-01
*/
/*
* Copyright (C) 2011-2012 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.
*/
.section .text
/* ELF entry symbol */
.global _start
_start:
/* idle a little initially because 'u-boot' likes it this way */
.rept 8
nop
.endr
/* zero-fill BSS segment */
.extern _bss_start
.extern _bss_end
ldr r0, =_bss_start
ldr r1, =_bss_end
mov r2, #0
sub r1, r1, #4
1:
str r2, [r0]
add r0, r0, #4
cmp r0, r1
bne 1b
/* call kernel routine */
.extern kernel
_start_kernel:
ldr sp, =_kernel_stack_high
bl kernel
/* jump to code that kernel has designated for when he has returned */
ldr r1, =_call_after_kernel
ldr r1, [r1]
add pc, r1, #0
/* handle for dynamic symbol objects */
.align 3
.global __dso_handle
__dso_handle: .long 0
.section .bss
/* instruction pointer wich gets loaded when kernel returns */
.align 3
.global _call_after_kernel
_call_after_kernel: .long 0
/* kernel stack */
.align 3
.space 64*1024
.global _kernel_stack_high
_kernel_stack_high:
/* main thread UTCB pointer for the Genode thread API */
.align 3
.global _main_utcb
_main_utcb: .long 0

View File

@ -0,0 +1,205 @@
/*
* \brief Transition between kernel and userland
* \author Martin stein
* \date 2011-11-15
*/
/*
* Copyright (C) 2011-2012 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.
*/
/**
* Invalidate all entries of the branch predictor array
*/
.macro _flush_branch_predictor
mcr p15, 0, sp, c7, c5, 6
isb
.endm
/**
* Switch from an interrupted user context to a kernel context
*
* \param exception_type immediate exception type ID
* \param pc_adjust immediate value that gets subtracted from the
* user PC before it gets saved
*/
.macro _user_to_kernel_pic exception_type, pc_adjust
/*
* We expect that privileged modes are never interrupted by an
* exception. Thus we can assume that we always come from
* user mode at this point.
*/
/************************************************
** We're still in the user protection domain, **
** so we must avoid access to kernel memory **
************************************************/
/* load kernel contextidr */
adr sp, _mt_kernel_context_begin
ldr sp, [sp, #17*4]
mcr p15, 0, sp, c13, c0, 1
_flush_branch_predictor
/* load kernel section table */
adr sp, _mt_kernel_context_begin
ldr sp, [sp, #19*4]
mcr p15, 0, sp, c2, c0, 0
_flush_branch_predictor
/*******************************************
** Now it's save to access kernel memory **
*******************************************/
/* get user context pointer */
ldr sp, _mt_user_context_ptr
/*
* Save user r0 ... r12. We explicitely target user registers
* via '^' because we might be in FIQ exception-mode where
* some of them are banked. Doesn't affect other modes.
*/
stmia sp, {r0-r12}^
/* save user lr and sp */
add r0, sp, #13*4
stmia r0, {sp,lr}^
/* adjust and save user pc */
.if \pc_adjust != 0
sub lr, lr, #\pc_adjust
.endif
str lr, [sp, #15*4]
/* save user psr */
mrs r0, spsr
str r0, [sp, #16*4]
/* save type of exception that interrupted the user */
mov r0, #\exception_type
str r0, [sp, #18*4]
/*
* Switch to supervisor mode
* FIXME This is done due to incorrect behavior when running the kernel
* high-level-code in FIQ-exception mode. Please debug this behavior
* and remove this switch.
*/
cps #19
/* get kernel context pointer */
adr r0, _mt_kernel_context_begin
/* load kernel context */
add r0, r0, #13*4
ldmia r0, {sp, lr, pc}
.endm
.section .text
/*
* The mode transition PIC switches between a kernel context and a user
* context and thereby between their address spaces. Due to the latter
* it must be mapped executable to the same region in every address space.
* To enable such switching, the kernel context must be stored within this
* region, thus one should map it solely accessable for privileged modes.
*/
.align 3
.global _mode_transition_begin
_mode_transition_begin:
/*
* On user exceptions the CPU has to jump to one of the following
* 7 entry vectors to switch to a kernel context.
*/
.align 3
.global _mt_kernel_entry_pic
_mt_kernel_entry_pic:
b _rst_entry /* reset */
b _und_entry /* undefined instruction */
b _svc_entry /* supervisor call */
b _pab_entry /* prefetch abort */
b _dab_entry /* data abort */
nop /* reserved */
b _irq_entry /* interrupt request */
b _fiq_entry /* fast interrupt request */
/* PICs that switch from an user exception to the kernel */
_rst_entry: _user_to_kernel_pic 1, 0
_und_entry: _user_to_kernel_pic 2, 4
_svc_entry: _user_to_kernel_pic 3, 0
_pab_entry: _user_to_kernel_pic 4, 4
_dab_entry: _user_to_kernel_pic 5, 8
_irq_entry: _user_to_kernel_pic 6, 4
_fiq_entry: _user_to_kernel_pic 7, 4
/* kernel must jump to this point to switch to a user context */
.align 3
.global _mt_user_entry_pic
_mt_user_entry_pic:
/* get user context pointer */
ldr lr, _mt_user_context_ptr
/* buffer user pc */
ldr r0, [lr, #15*4]
adr r1, _mt_buffer
str r0, [r1]
/* buffer user psr */
ldr r0, [lr, #16*4]
msr spsr, r0
/* load user r0 ... r12 */
ldmia lr, {r0-r12}
/* load user sp and lr */
add sp, lr, #13*4
ldmia sp, {sp,lr}^
/* get user contextidr and section table */
ldr sp, [lr, #17*4]
ldr lr, [lr, #19*4]
/********************************************************
** From now on, until we leave kernel mode, we must **
** avoid access to memory that is not mapped globally **
********************************************************/
/* apply user contextidr and section table */
mcr p15, 0, sp, c13, c0, 1
mcr p15, 0, lr, c2, c0, 0
_flush_branch_predictor
/* load user pc (implies application of the user psr) */
adr lr, _mt_buffer
ldmia lr, {pc}^
/* leave some space for the kernel context */
.align 3
.global _mt_kernel_context_begin
_mt_kernel_context_begin: .space 32*4
.global _mt_kernel_context_end
_mt_kernel_context_end:
/* pointer to the user context backup space */
.align 3
.global _mt_user_context_ptr
_mt_user_context_ptr: .long 0
/* a local word-sized buffer */
.align 3
.global _mt_buffer
_mt_buffer: .long 0
.align 3
.global _mode_transition_end
_mode_transition_end:

View File

@ -0,0 +1,34 @@
/*
* \brief Platform specific parts of CPU session
* \author Martin Stein
* \date 2012-04-17
*/
/*
* Copyright (C) 2012 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 <dataspace/capability.h>
/* core includes */
#include <cpu_session_component.h>
using namespace Genode;
Ram_dataspace_capability
Cpu_session_component::utcb(Thread_capability thread_cap)
{
/* serialize access */
Lock::Guard lock_guard(_thread_list_lock);
/* lookup requested UTCB dataspace */
Cpu_thread_component * t = _lookup_thread(thread_cap);
if (!t) return Ram_dataspace_capability();
return t->platform_thread()->utcb();
}

View File

@ -0,0 +1,36 @@
/*
* \brief Assertion macro
* \author Martin Stein
* \date 2012-04-04
*/
/*
* Copyright (C) 2012 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__ASSERT_H_
#define _CORE__INCLUDE__ASSERT_H_
/* Genode includes */
#include <base/printf.h>
/**
* Assert a condition
*
* \param expression Expression that must be true
*/
#define assert(expression) \
do { \
if (!(expression)) { \
PERR("Assertion failed: "#expression""); \
PERR(" File: %s:%d", __FILE__, __LINE__); \
PERR(" Function: %s", __PRETTY_FUNCTION__); \
while (1) ; \
} \
} while (0) ;
#endif /* _CORE__INCLUDE__ASSERT_H_ */

View File

@ -0,0 +1,54 @@
/*
* \brief Parts of kernel support that are identical for all Cortex A9 systems
* \author Martin Stein
* \date 2012-04-23
*/
/*
* Copyright (C) 2012 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__CORTEX_A9__KERNEL_SUPPORT_H_
#define _CORE__INCLUDE__CORTEX_A9__KERNEL_SUPPORT_H_
/* Genode includes */
#include <drivers/cpu/cortex_a9/core.h>
#include <drivers/pic/pl390_base.h>
/**
* CPU driver
*/
class Cpu : public Genode::Cortex_a9 { };
namespace Kernel
{
/* import Genode types */
typedef Genode::Cortex_a9 Cortex_a9;
typedef Genode::Pl390_base Pl390_base;
/**
* Kernel interrupt-controller
*/
class Pic : public Pl390_base
{
public:
/**
* Constructor
*/
Pic() : Pl390_base(Cortex_a9::PL390_DISTRIBUTOR_MMIO_BASE,
Cortex_a9::PL390_CPU_MMIO_BASE)
{ }
};
/**
* Kernel timer
*/
class Timer : public Cortex_a9::Private_timer { };
}
#endif /* _CORE__INCLUDE__CORTEX_A9__KERNEL_SUPPORT_H_ */

View File

@ -0,0 +1,68 @@
/*
* \brief Platform specific parts of the core CPU session
* \author Martin Stein
* \date 2012-03-21
*/
/*
* Copyright (C) 2012 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__CPU_SESSION_SUPPORT_H_
#define _CORE__INCLUDE__CPU_SESSION_SUPPORT_H_
#include <base/printf.h>
#include <base/allocator.h>
namespace Genode
{
/**
* Thread allocator for cores CPU service
*
* Normally one would use a SLAB for threads because usually they
* are tiny objects, but in 'base-hw' they contain the whole kernel
* object in addition. Thus we use the given allocator directly.
*/
class Cpu_thread_allocator : public Allocator
{
Allocator * const _alloc;
public:
/**
* Constructor
*
* \param alloc allocator backend
*/
Cpu_thread_allocator(Allocator * alloc) : _alloc(alloc) { }
/*************************
** Allocator interface **
*************************/
bool alloc(size_t size, void **out_addr) {
return _alloc->alloc(size, out_addr); }
void free(void *addr, size_t size) {
_alloc->free(addr, size); }
size_t consumed() {
PDBG("Unexprected call");
while (1) ;
return 0;
}
size_t overhead(size_t size) {
PDBG("Unexprected call");
while (1) ;
return 0;
}
bool need_size_for_free() const { return true; }
};
}
#endif /* _CORE__INCLUDE__CPU_SESSION_SUPPORT_H_ */

View File

@ -0,0 +1,111 @@
/*
* \brief Platform interface
* \author Martin Stein
* \date 2011-12-21
*/
/*
* Copyright (C) 2011-2012 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/sync_allocator.h>
#include <base/allocator_avl.h>
#include <kernel/log.h>
#include <kernel/syscalls.h>
/* core includes */
#include <platform_generic.h>
namespace Genode {
/**
* Manages all platform ressources
*/
class Platform : public Platform_generic
{
typedef Synchronized_range_allocator<Allocator_avl> Phys_allocator;
Phys_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 */
addr_t _vm_base; /* base of virtual address space */
size_t _vm_size; /* size of virtual address space */
/**
* Get one of the consecutively numbered available resource regions
*
* \return >0 region pointer if region with index 'i' exists
* 0 if region with index 'i' doesn't exist
*
* These functions should provide all ressources that are available
* on the current platform.
*/
static Native_region * _ram_regions(unsigned i);
static Native_region * _mmio_regions(unsigned i);
static Native_region * _irq_regions(unsigned i);
/**
* Get one of the consecutively numbered core regions
*
* \return >0 Region pointer if region with index 'i' exists
* 0 If region with index 'i' doesn't exist
*
* Core regions are address regions that must be permitted to
* core only, such as the core image ROM. These regions are normally
* a subset of the ressource regions provided above.
*/
static Native_region * _core_only_ram_regions(unsigned i);
static Native_region * _core_only_mmio_regions(unsigned i);
static Native_region * _core_only_irq_regions(unsigned i);
public:
/**
* Constructor
*/
Platform();
/********************************
** Platform_generic interface **
********************************/
inline Range_allocator * core_mem_alloc() { return &_core_mem_alloc; }
inline Range_allocator * ram_alloc() { return &_core_mem_alloc; }
inline Range_allocator * io_mem_alloc() { return &_io_mem_alloc; }
inline Range_allocator * io_port_alloc() { return &_io_port_alloc; }
inline Range_allocator * irq_alloc() { return &_irq_alloc; }
inline addr_t vm_start() const { return _vm_base; }
inline size_t vm_size() const { return _vm_size; }
inline Rom_fs *rom_fs() { return &_rom_fs; }
inline void wait_for_exit() { while (1) Kernel::pause_thread(); };
inline Range_allocator * region_alloc()
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
return 0;
}
};
}
#endif /* _CORE__INCLUDE__PLATFORM_H_ */

View File

@ -0,0 +1,105 @@
/*
* \brief Platform specific part of a Genode protection domain
* \author Martin Stein
* \date 2012-02-12
*/
/*
* Copyright (C) 2009-2012 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_
/* Genode includes */
#include <base/printf.h>
/* Core includes */
#include <platform.h>
#include <platform_thread.h>
namespace Kernel
{
Genode::size_t pd_size();
unsigned pd_alignm_log2();
}
namespace Genode
{
class Platform_thread;
/**
* Platform specific part of a Genode protection domain
*/
class Platform_pd
{
unsigned long _id; /* ID of our kernel object */
Native_capability _parent; /* our parent interface */
Native_thread_id _main_thread; /* the first thread that gets
* executed in this PD */
public:
/**
* Constructor
*/
Platform_pd() : _main_thread(0)
{
/* get some aligned space for the kernel object */
void * kernel_pd;
Range_allocator * ram = platform()->ram_alloc();
assert(ram->alloc_aligned(Kernel::pd_size(), &kernel_pd,
Kernel::pd_alignm_log2()));
/* create kernel object */
_id = Kernel::new_pd(kernel_pd);
assert(_id);
}
/**
* Destructor
*/
~Platform_pd();
/**
* Bind thread 't' to protection domain
*
* \return 0 on success or
* -1 if failed
*/
int bind_thread(Platform_thread * t)
{
/* is this the first and therefore main thread in this PD? */
if (!_main_thread)
{
/* annotate that we've got a main thread from now on */
_main_thread = t->id();
return t->join_pd(_id, 1);
}
return t->join_pd(_id, 0);
}
/**
* Unbind thread from protection domain
*
* Free the thread's slot and update thread object.
*/
void unbind_thread(Platform_thread * t);
/**
* Assign parent interface to protection domain
*/
int assign_parent(Native_capability parent)
{
assert(parent.valid());
_parent = parent;
return 0;
}
};
}
#endif /* _CORE__INCLUDE__PLATFORM_PD_H_ */

View File

@ -0,0 +1,184 @@
/*
* \brief Userland interface for the management of kernel thread-objects
* \author Martin Stein
* \date 2012-02-02
*/
/*
* Copyright (C) 2012 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 <ram_session/ram_session.h>
#include <base/native_types.h>
#include <kernel/syscalls.h>
#include <kernel/log.h>
/* core includes */
#include <assert.h>
namespace Genode {
class Pager_object;
class Thread_state;
class Thread_base;
class Rm_client;
class Platform_thread;
size_t kernel_thread_size();
/**
* Userland interface for the management of kernel thread-objects
*/
class Platform_thread
{
enum { NAME_MAX_LEN = 32 };
Thread_base * _thread_base;
unsigned long _stack_size;
unsigned long _pd_id;
unsigned long _id;
Rm_client * _rm_client;
bool _main_thread;
Native_utcb * _phys_utcb;
Native_utcb * _virt_utcb;
Software_tlb * _software_tlb;
Ram_dataspace_capability _utcb;
char _name[NAME_MAX_LEN];
/**
* Common construction part
*/
void _init();
public:
/**
* Constructor for core threads
*/
Platform_thread(const char * name,
Thread_base * const thread_base,
unsigned long const stack_size,
unsigned long const pd_id);
/**
* Constructor for threads outside of core
*/
Platform_thread(const char * name, unsigned int priority,
addr_t utcb);
/**
* Join PD identified by 'pd_id'
*
* \param pd_id ID of targeted PD
* \param main_thread wether we are the main thread in this PD
*
* \retval 0 on success
* \retval <0 otherwise
*/
int join_pd(unsigned long const pd_id,
bool const main_thread);
/**
* Run this thread
*/
int start(void * ip, void * sp, unsigned int cpu_no = 0);
/**
* Pause this thread
*/
void pause() { Kernel::pause_thread(_id); }
/**
* Resume this thread
*/
void resume() { Kernel::resume_thread(_id); }
/**
* Cancel currently blocking operation
*/
void cancel_blocking()
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
};
/**
* Request our raw thread state
*
* \param state_dst destination state buffer
*
* \retval 0 successful
* \retval -1 thread state not accessible
*/
int state(Genode::Thread_state * state_dst)
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
return -1;
};
/**
* Destructor
*/
~Platform_thread()
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
}
/**
* Return unique identification of this thread as faulter
*/
unsigned long pager_object_badge() { return _id; }
/**
* Set the executing CPU for this thread.
*/
void set_cpu(unsigned int cpu_no)
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
};
/***************
** Accessors **
***************/
inline char const * name() const { return _name; }
void pager(Pager_object * const pager);
Pager_object * pager() const;
unsigned long pd_id() const { return _pd_id; }
Native_thread_id id() const { return _id; }
unsigned long stack_size() const { return _stack_size; }
Thread_base * thread_base()
{
if (!_thread_base) assert(_main_thread);
return _thread_base;
}
Native_utcb * phys_utcb() const { return _phys_utcb; }
Native_utcb * virt_utcb() const { return _virt_utcb; }
Ram_dataspace_capability utcb() const { return _utcb; }
Software_tlb * software_tlb() const { return _software_tlb; }
};
}
#endif /* _CORE__INCLUDE__PLATFORM_THREAD_H_ */

View File

@ -0,0 +1,93 @@
/*
* \brief Signal root interface on HW-core
* \author Martin Stein
* \date 2012-05-06
*/
/*
* Copyright (C) 2012 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__SIGNAL_ROOT_H_
#define _CORE__INCLUDE__SIGNAL_ROOT_H_
/* Genode includes */
#include <root/component.h>
/* core includes */
#include <signal_session_component.h>
namespace Genode
{
/**
* Provide EP to signal root before it initialises root component
*/
class Signal_handler
{
enum { STACK_SIZE = 4096 };
Rpc_entrypoint _entrypoint;
public:
/**
* Constructor
*/
Signal_handler(Cap_session * const c)
: _entrypoint(c, STACK_SIZE, "signal") { }
/***************
** Accessors **
***************/
Rpc_entrypoint * entrypoint() { return &_entrypoint; }
};
/**
* Provides signal service by managing appropriate sessions to the clients
*/
class Signal_root : private Signal_handler,
public Root_component<Signal_session_component>
{
public:
/**
* Constructor
*
* \param md Meta-data allocator to be used by root component
* \param c CAP session to be used by the root entrypoint
*/
Signal_root(Allocator * const md, Cap_session * const c) :
Signal_handler(c),
Root_component<Signal_session_component>(entrypoint(), md)
{ }
protected:
/********************************
** 'Root_component' interface **
********************************/
Signal_session_component * _create_session(const char * args)
{
size_t ram_quota =
Arg_string::find_arg(args, "ram_quota").long_value(0);
return new (md_alloc())
Signal_session_component(md_alloc(), ram_quota);
}
void _upgrade_session(Signal_session_component *s,
const char * args)
{
size_t ram_quota =
Arg_string::find_arg(args, "ram_quota").long_value(0);
s->upgrade_ram_quota(ram_quota);
}
};
}
#endif /* _CORE__INCLUDE__SIGNAL_ROOT_H_ */

View File

@ -0,0 +1,68 @@
/*
* \brief Signal service on the HW-core
* \author Martin stein
* \date 2012-05-05
*/
/*
* Copyright (C) 2012 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__SIGNAL_SESSION_COMPONENT_H_
#define _CORE__INCLUDE__SIGNAL_SESSION_COMPONENT_H_
/* Genode includes */
#include <signal_session/signal_session.h>
#include <base/rpc_server.h>
#include <base/slab.h>
#include <base/allocator_guard.h>
namespace Genode
{
/**
* Provides the signal service
*/
class Signal_session_component : public Rpc_object<Signal_session>
{
Allocator_guard _md_alloc; /* Metadata allocator */
Slab _receivers_slab; /* SLAB to allocate receiver kernel-objects */
Slab _contexts_slab; /* SLAB to allocate context kernel-objects */
public:
/**
* Constructor
*
* \param md Metadata allocator
* \param ram_quota Amount of RAM quota donated to this session
*/
Signal_session_component(Allocator * const md,
size_t const ram_quota);
/**
* Destructor
*/
~Signal_session_component();
/**
* Raise the quota of this session by 'q'
*/
void upgrade_ram_quota(size_t const q) { _md_alloc.upgrade(q); }
/******************************
** Signal_session interface **
******************************/
Signal_receiver_capability alloc_receiver();
Signal_context_capability
alloc_context(Signal_receiver_capability const r,
unsigned long const imprint);
};
}
#endif /* _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_ */

View File

@ -0,0 +1,109 @@
/*
* \brief Core-internal utilities
* \author Martin Stein
* \date 2012-01-02
*/
/*
* Copyright (C) 2012 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>
namespace Genode
{
enum { MIN_PAGE_SIZE_LOG2 = 12 };
/**
* Get the the minimal supported page-size log 2
*/
inline size_t get_page_size_log2() { return MIN_PAGE_SIZE_LOG2; }
/**
* Get the the minimal supported page-size
*/
inline size_t get_page_size() { return 1 << get_page_size_log2(); }
/**
* Get the base mask for the minimal supported page-size
*/
inline addr_t get_page_mask() { return ~(get_page_size() - 1); }
/**
* Round down to the minimal page-size alignment
*/
inline addr_t trunc_page(addr_t addr) { return addr & get_page_mask(); }
/**
* Round up to the minimal page-size alignment
*/
inline addr_t round_page(addr_t addr)
{ return trunc_page(addr + get_page_size() - 1); }
/**
* Round down to a specific alignment
*/
inline addr_t trunc(addr_t const addr, unsigned const alignm_log2)
{ return addr & ~((1 << alignm_log2) - 1); }
/**
* Round up to a specific alignment
*/
inline addr_t round(addr_t const addr, unsigned const alignm_log2)
{ return trunc(addr + (1<<alignm_log2) - 1, alignm_log2); }
/**
* Select source used for map operations
*/
inline addr_t map_src_addr(addr_t core_local, addr_t phys) { return phys; }
/**
* Return highest supported flexpage size for the given mapping size
*
* This function is called by the page-fault handler to determine the
* mapping granularity to be used for a page-fault answer. If a kernel
* supports flexible page sizes, this function can just return the
* argument. If a kernel only supports a certain set of map sizes such
* as 4K and 4M, this function should select one of those smaller or
* equal to the argument.
*/
inline size_t constrain_map_size_log2(size_t size_log2)
{
if (size_log2<20) return 12;
return 20;
}
/**
* Debug output on page faults
*/
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)", 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,29 @@
/*
* \brief Implementation of the IO_MEM session interface
* \author Martin Stein
* \date 2012-02-12
*
*/
/*
* Copyright (C) 2012 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 <kernel/log.h>
/* 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 base; }

View File

@ -0,0 +1,85 @@
/*
* \brief Implementation of the IO_PORT session interface
* \author Martin Stein
* \date 2012-02-12
*/
/*
* Copyright (C) 2012 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 <kernel/log.h>
/* core includes */
#include <io_port_session_component.h>
using namespace Genode;
unsigned char Io_port_session_component::inb(unsigned short address)
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
return 0;
}
unsigned short Io_port_session_component::inw(unsigned short address)
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
return 0;
}
unsigned Io_port_session_component::inl(unsigned short address)
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
return 0;
}
void Io_port_session_component::outb(unsigned short address,
unsigned char value)
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
}
void Io_port_session_component::outw(unsigned short address,
unsigned short value)
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
}
void Io_port_session_component::outl(unsigned short address, unsigned value)
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
}
Io_port_session_component::
Io_port_session_component(Range_allocator * io_port_alloc,
const char * args)
: _io_port_alloc(io_port_alloc)
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
}
Io_port_session_component::~Io_port_session_component()
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
}

View File

@ -0,0 +1,69 @@
/*
* \brief Implementation of IRQ session component
* \author Martin Stein
* \date 2012-02-12
*/
/*
* Copyright (C) 2012 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 <kernel/syscalls.h>
/* core includes */
#include <irq_root.h>
using namespace Genode;
bool
Irq_session_component::Irq_control_component::associate_to_irq(unsigned irq)
{ return Kernel::allocate_irq(irq); }
void Irq_session_component::wait_for_irq() { Kernel::await_irq(); }
Irq_session_component::~Irq_session_component()
{
/* free IRQ for other threads */
if (Kernel::free_irq(_irq_number))
PERR("Could not free IRQ %u", _irq_number);
}
Irq_session_component::Irq_session_component(Cap_session * cap_session,
Range_allocator * irq_alloc,
const char * args)
:
_irq_alloc(irq_alloc), _ep(cap_session, STACK_SIZE, "irqctrl"),
_control_cap(_ep.manage(&_control_component)),
_control_client(_control_cap)
{
/* check arguments */
bool shared = Arg_string::find_arg(args, "irq_shared").bool_value(false);
if (shared) {
PERR("IRQ sharing not supported");
throw Root::Invalid_args();
}
/* allocate IRQ */
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
if (irq_number == -1 || !irq_alloc ||
irq_alloc->alloc_addr(1, irq_number) != Range_allocator::ALLOC_OK) {
PERR("Unavailable IRQ %lu requested", irq_number);
throw Root::Invalid_args();
}
_irq_number = irq_number;
/* configure control client */
if (!_control_client.associate_to_irq(irq_number)) {
PERR("IRQ association failed");
throw Root::Invalid_args();
}
/* create IRQ capability */
_irq_cap = Irq_session_capability(_ep.manage(this));
}

2088
base-hw/src/core/kernel.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
/*
* \brief Kernel support specific for the PandaBoard A2
* \author Martin Stein
* \date 2012-04-23
*/
/*
* Copyright (C) 2012 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 _SRC__CORE__PANDA_A2__KERNEL_SUPPORT_H_
#define _SRC__CORE__PANDA_A2__KERNEL_SUPPORT_H_
/* local includes */
#include <cortex_a9/kernel_support.h>
#endif /* _SRC__CORE__PANDA_A2__KERNEL_SUPPORT_H_ */

View File

@ -0,0 +1,84 @@
/*
* \brief Platform implementations specific for base-hw and Panda A2
* \author Martin Stein
* \date 2012-04-27
*/
/*
* Copyright (C) 2012 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 <drivers/board/panda_a2.h>
#include <drivers/cpu/cortex_a9/core.h>
#include <drivers/pic/pl390_base.h>
/* core includes */
#include <platform.h>
using namespace Genode;
Native_region * Platform::_ram_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ Panda_a2::EMIF1_EMIF2_CS0_SDRAM_BASE,
Panda_a2::EMIF1_EMIF2_CS0_SDRAM_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_irq_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ 0, Pl390_base::MAX_INTERRUPT_ID + 1 }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_core_only_irq_regions(unsigned const i)
{
static Native_region _regions[] =
{
/* core timer */
{ Cortex_a9::PRIVATE_TIMER_IRQ, 1 },
/* core UART */
{ Panda_a2::TL16C750_3_IRQ, 1 }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_mmio_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ Panda_a2::L4_PER_BASE, Panda_a2::L4_PER_SIZE },
{ Panda_a2::L4_CFG_BASE, Panda_a2::L4_CFG_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_core_only_mmio_regions(unsigned const i)
{
static Native_region _regions[] =
{
/* core timer and PIC */
{ Panda_a2::CORTEX_A9_PRIVATE_MEM_BASE,
Panda_a2::CORTEX_A9_PRIVATE_MEM_SIZE },
/* core UART */
{ Panda_a2::TL16C750_3_MMIO_BASE, Panda_a2::TL16C750_3_MMIO_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}

View File

@ -0,0 +1,26 @@
/*
* \brief Software TLB controls specific for the PandaBoard A2
* \author Martin Stein
* \date 2012-04-23
*/
/*
* Copyright (C) 2012 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 _SRC__CORE__PANDA_A2__SOFTWARE_TLB_H_
#define _SRC__CORE__PANDA_A2__SOFTWARE_TLB_H_
/* Genode includes */
#include <drivers/cpu/cortex_a9/section_table.h>
/**
* Software TLB controls
*/
class Software_tlb : public Genode::Section_table { };
#endif /* _SRC__CORE__PANDA_A2__SOFTWARE_TLB_H_ */

View File

@ -0,0 +1,21 @@
/*
* \brief Kernel support specific for the Realview PBXA9
* \author Martin Stein
* \date 2012-04-23
*/
/*
* Copyright (C) 2012 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 _SRC__CORE__PBXA9__KERNEL_SUPPORT_H_
#define _SRC__CORE__PBXA9__KERNEL_SUPPORT_H_
/* local includes */
#include <cortex_a9/kernel_support.h>
#endif /* _SRC__CORE__PBXA9__KERNEL_SUPPORT_H_ */

View File

@ -0,0 +1,82 @@
/*
* \brief Parts of platform that are specific to PBXA9
* \author Martin Stein
* \date 2012-04-27
*/
/*
* Copyright (C) 2012 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 <drivers/board/pbxa9.h>
#include <drivers/cpu/cortex_a9/core.h>
#include <drivers/pic/pl390_base.h>
/* core includes */
#include <platform.h>
using namespace Genode;
Native_region * Platform::_ram_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ Pbxa9::NORTHBRIDGE_DDR_0_BASE, Pbxa9::NORTHBRIDGE_DDR_0_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_irq_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ 0, Pl390_base::MAX_INTERRUPT_ID + 1 }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_core_only_irq_regions(unsigned const i)
{
static Native_region _regions[] =
{
/* core timer */
{ Cortex_a9::PRIVATE_TIMER_IRQ, 1 },
/* core UART */
{ Pbxa9::PL011_0_IRQ, 1 }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_mmio_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ Pbxa9::SOUTHBRIDGE_APB_BASE, Pbxa9::SOUTHBRIDGE_APB_SIZE },
{ Pbxa9::NORTHBRIDGE_AHB_BASE, Pbxa9::NORTHBRIDGE_AHB_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_core_only_mmio_regions(unsigned const i)
{
static Native_region _regions[] =
{
/* core timer and PIC */
{ Pbxa9::CORTEX_A9_PRIVATE_MEM_BASE, Pbxa9::CORTEX_A9_PRIVATE_MEM_SIZE },
/* core UART */
{ Pbxa9::PL011_0_MMIO_BASE, Pbxa9::PL011_0_MMIO_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}

View File

@ -0,0 +1,26 @@
/*
* \brief Software TLB controls specific for the Realview PBXA9
* \author Martin Stein
* \date 2012-04-23
*/
/*
* Copyright (C) 2012 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 _SRC__CORE__PBXA9__SOFTWARE_TLB_H_
#define _SRC__CORE__PBXA9__SOFTWARE_TLB_H_
/* Genode includes */
#include <drivers/cpu/cortex_a9/section_table.h>
/**
* Software TLB controls
*/
class Software_tlb : public Genode::Section_table { };
#endif /* _SRC__CORE__PBXA9__SOFTWARE_TLB_H_ */

View File

@ -0,0 +1,162 @@
/*
* \brief Platform implementation specific for hw
* \author Martin Stein
* \date 2011-12-21
*/
/*
* Copyright (C) 2011-2012 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 <kernel/log.h>
/* core includes */
#include <core_parent.h>
#include <platform.h>
#include <util.h>
using namespace Genode;
extern int _prog_img_beg;
extern int _prog_img_end;
/**
* Format of a boot-module header
*/
struct Bm_header
{
long name; /* physical address of null-terminated string */
long base; /* physical address of module data */
long size; /* size of module data in bytes */
};
extern int _boot_modules_begin;
extern Bm_header _boot_module_headers_begin;
extern Bm_header _boot_module_headers_end;
extern int _boot_modules_end;
/**
* Functionpointer that provides accessor to a pool of address regions
*/
typedef Native_region * (*Region_pool)(unsigned const);
namespace Kernel
{
addr_t mode_transition_virt_base();
size_t mode_transition_size();
}
/**
* Helper to initialise allocators through include/exclude region lists
*/
static void init_alloc(Range_allocator * const alloc,
Region_pool incl_regions, Region_pool excl_regions,
unsigned const granu_log2 = 0)
{
/* make all include regions available */
Native_region * r = incl_regions(0);
for (unsigned i = 0; r; r = incl_regions(++i)) {
if (granu_log2) {
addr_t const b = trunc(r->base, granu_log2);
addr_t const s = round(r->size, granu_log2);
alloc->add_range(b, s);
}
else alloc->add_range(r->base, r->size);
}
/* preserve all exclude regions */
r = excl_regions(0);
for (unsigned i = 0; r; r = excl_regions(++i)) {
if (granu_log2) {
addr_t const b = trunc(r->base, granu_log2);
addr_t const s = round(r->size, granu_log2);
alloc->remove_range(b, s);
}
else alloc->remove_range(r->base, r->size);
}
}
/**************
** Platform **
**************/
Native_region * Platform::_core_only_ram_regions(unsigned const i)
{
static Native_region _r[] =
{
/* avoid null pointers */
{ 0, 1 },
/* mode transition region */
{ Kernel::mode_transition_virt_base(), Kernel::mode_transition_size() },
/* core image */
{ (addr_t)&_prog_img_beg,
(size_t)((addr_t)&_prog_img_end - (addr_t)&_prog_img_beg) },
/* boot modules */
{ (addr_t)&_boot_modules_begin,
(size_t)((addr_t)&_boot_modules_end - (addr_t)&_boot_modules_begin) }
};
return i < sizeof(_r)/sizeof(_r[0]) ? &_r[i] : 0;
}
Platform::Platform() :
_core_mem_alloc(0),
_io_mem_alloc(core_mem_alloc()), _io_port_alloc(core_mem_alloc()),
_irq_alloc(core_mem_alloc()), _vm_base(0), _vm_size(0xffff0000)
{
/*
* Initialise platform resource allocators.
* Core mem alloc must come first because it is
* used by the other allocators.
*/
enum { VERBOSE = 0 };
unsigned const psl2 = get_page_size_log2();
init_alloc(&_core_mem_alloc, _ram_regions, _core_only_ram_regions, psl2);
init_alloc(&_irq_alloc, _irq_regions, _core_only_irq_regions);
init_alloc(&_io_mem_alloc, _mmio_regions, _core_only_mmio_regions, psl2);
/* add boot modules to ROM FS */
Bm_header * header = &_boot_module_headers_begin;
for (; header < &_boot_module_headers_end; header++) {
Rom_module * rom_module = new (core_mem_alloc())
Rom_module(header->base, header->size, (const char*)header->name);
_rom_fs.insert(rom_module);
}
/* print ressource summary */
if (VERBOSE) {
printf("Core memory allocator\n");
printf("---------------------\n");
_core_mem_alloc.raw()->dump_addr_tree();
printf("\n");
printf("IO memory allocator\n");
printf("-------------------\n");
_io_mem_alloc.raw()->dump_addr_tree();
printf("\n");
printf("ROM filesystem\n");
printf("--------------\n");
_rom_fs.print_fs();
printf("\n");
}
}
/*****************
** Core_parent **
*****************/
void Core_parent::exit(int exit_value)
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
}

View File

@ -0,0 +1,28 @@
/*
* \brief Protection-domain facility
* \author Martin Stein
* \date 2012-02-12
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* core includes */
#include <platform_pd.h>
using namespace Genode;
/*****************
** Platform PD **
*****************/
void Platform_pd::unbind_thread(Platform_thread *thread) { assert(0); }
Platform_pd::~Platform_pd() { assert(0); }

View File

@ -0,0 +1,145 @@
/*
* \brief Thread facility
* \author Martin Stein
* \date 2012-02-12
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* core includes */
#include <platform_thread.h>
#include <core_env.h>
#include <rm_session_component.h>
using namespace Genode;
namespace Kernel { unsigned core_id(); }
Platform_thread::Platform_thread(const char * name,
Thread_base * const thread_base,
unsigned long const stack_size,
unsigned long const pd_id)
:
_thread_base(thread_base), _stack_size(stack_size),
_pd_id(pd_id), _rm_client(0), _virt_utcb(0)
{
strncpy(_name, name, NAME_MAX_LEN);
/* create UTCB for a core thread */
Range_allocator * const ram = platform()->ram_alloc();
assert(ram->alloc_aligned(sizeof(Native_utcb), (void **)&_phys_utcb,
MIN_MAPPING_SIZE_LOG2));
_virt_utcb = _phys_utcb;
/* common constructor parts */
_init();
}
Platform_thread::Platform_thread(const char * name, unsigned int priority,
addr_t utcb)
:
_thread_base(0), _stack_size(0), _pd_id(0), _rm_client(0),
_virt_utcb((Native_utcb *)utcb)
{
strncpy(_name, name, NAME_MAX_LEN);
/*
* Allocate UTCB backing store for a thread outside of core. Page alignment
* is done by RAM session by default. It's save to use core env because
* this cannot be its server activation thread.
*/
try {
Ram_session_component * const ram =
dynamic_cast<Ram_session_component *>(core_env()->ram_session());
assert(ram);
_utcb = ram->alloc(sizeof(Native_utcb), 1);
_phys_utcb = (Native_utcb *)ram->phys_addr(_utcb);
}
catch (...) { assert(0); }
/* common constructor parts */
_init();
}
int Platform_thread::join_pd(unsigned long const pd_id,
bool const main_thread)
{
/* check if we're already in another PD */
if (_pd_id && _pd_id != pd_id) return -1;
/* denote configuration for start method */
_pd_id = pd_id;
_main_thread = main_thread;
return 0;
}
void Platform_thread::_init()
{
/* create kernel object */
void * kernel_thread;
Range_allocator * ram = platform()->ram_alloc();
assert(ram->alloc(Kernel::thread_size(), &kernel_thread));
_id = Kernel::new_thread(kernel_thread, this);
assert(_id);
}
int Platform_thread::start(void * ip, void * sp, unsigned int cpu_no)
{
/* check thread attributes */
assert(_pd_id);
/*
* If this is a main thread outside of core it'll not manage its
* virtual context area by itself, as it is done for other threads
* through a sub RM-session. Therefore we attach the UTCB to its
* address space before it gets started.
*/
if (_pd_id != Kernel::core_id() && _main_thread)
{
/*
* Declare page aligned virtual UTCB outside the context area.
* Kernel afterwards offers this as bootstrap argument to the thread.
*/
_virt_utcb = (Native_utcb *)((platform()->vm_start()
+ platform()->vm_size() - sizeof(Native_utcb))
& ~((1<<MIN_MAPPING_SIZE_LOG2)-1));
/* attach UTCB */
assert(_rm_client);
Rm_session_component * const rm = _rm_client->member_rm_session();
try { rm->attach(_utcb, 0, 0, true, _virt_utcb, 0); }
catch (...) { assert(0); }
}
/* let thread participate in CPU scheduling */
_software_tlb = Kernel::start_thread(this, ip, sp, cpu_no);
return _software_tlb ? 0 : -1;
}
void Platform_thread::pager(Pager_object * const pager)
{
/* announce pager thread to kernel */
Kernel::set_pager(pager->cap().dst(), _id);
/* get RM client from pager pointer */
_rm_client = dynamic_cast<Rm_client *>(pager);
assert(_rm_client);
}
Genode::Pager_object * Platform_thread::pager() const
{
assert(_rm_client)
return static_cast<Pager_object *>(_rm_client);
}

View File

@ -0,0 +1,31 @@
/*
* \brief Export RAM dataspace as shared memory object (dummy)
* \author Martin Stein
* \date 2012-02-12
*/
/*
* Copyright (C) 2012 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 <ram_session_component.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)
{ memset((void *)ds->phys_addr(), 0, ds->size()); }

View File

@ -0,0 +1,85 @@
/*
* \brief RM- and pager implementations specific for base-hw and core
* \author Martin Stein
* \date 2012-02-12
*/
/*
* Copyright (C) 2012 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>
/* core includes */
#include <rm_session_component.h>
#include <platform.h>
#include <platform_thread.h>
#include <assert.h>
#include <software_tlb.h>
using namespace Genode;
/***************
** Rm_client **
***************/
void Rm_client::unmap(addr_t core_local_base, addr_t virt_base, size_t size)
{
/* get software TLB of the thread that we serve */
Platform_thread * const pt = Kernel::get_thread(badge());
assert(pt);
Software_tlb * const tlb = pt->software_tlb();
assert(tlb);
/* update all translation caches */
tlb->remove_region(virt_base, size);
Kernel::update_pd(pt->pd_id());
/* try to regain administrative memory that has been freed by unmap */
size_t s;
void * base;
while (tlb->regain_memory(base, s)) platform()->ram_alloc()->free(base, s);
}
/***************
** Ipc_pager **
***************/
void Ipc_pager::resolve_and_wait_for_fault()
{
/* valid mapping? */
assert(_mapping.valid());
/* do we need extra space to resolve pagefault? */
Software_tlb * const tlb = _pagefault.software_tlb;
enum Mapping_attributes { X = 1, K = 0, G = 0 };
unsigned sl2 = tlb->insert_translation(_mapping.virt_address,
_mapping.phys_address, _mapping.size_log2,
_mapping.writable, X, K, G);
if (sl2)
{
/* try to get some natural aligned space */
void * space;
assert(platform()->ram_alloc()->alloc_aligned(1<<sl2, &space, sl2));
/* try to translate again with extra space */
sl2 = tlb->insert_translation(_mapping.virt_address,
_mapping.phys_address,
_mapping.size_log2,
_mapping.writable, X, K, G, space);
assert(!sl2);
}
/* try to wake up faulter */
assert(!Kernel::resume_thread(_pagefault.thread_id));
/* wait for next page fault */
wait_for_fault();
}

View File

@ -0,0 +1,79 @@
/*
* \brief Implementation of the SIGNAL service on the HW-core
* \author Martin Stein
* \date 2012-05-05
*/
/*
* Copyright (C) 2012 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 <kernel/syscalls.h>
/* core includes */
#include <signal_session_component.h>
using namespace Genode;
enum {
RECEIVER_SLAB_CHUNK_SIZE = 32,
CONTEXT_SLAB_CHUNK_SIZE = 32,
};
Signal_session_component::Signal_session_component(Allocator * const md,
size_t const ram_quota) :
_md_alloc(md, ram_quota),
_receivers_slab(Kernel::signal_receiver_size(),
RECEIVER_SLAB_CHUNK_SIZE * Kernel::signal_receiver_size(),
0, &_md_alloc),
_contexts_slab(Kernel::signal_context_size(),
CONTEXT_SLAB_CHUNK_SIZE * Kernel::signal_context_size(),
0, &_md_alloc)
{ }
Signal_session_component::~Signal_session_component()
{
PERR("%s: Not implemented", __PRETTY_FUNCTION__);
while (1) ;
}
Signal_receiver_capability Signal_session_component::alloc_receiver()
{
/* create receiver kernel-object */
size_t const s = Kernel::signal_receiver_size();
void * p;
if (!_receivers_slab.alloc(s, &p)) throw Out_of_metadata();
unsigned long const id = Kernel::new_signal_receiver(p);
if (!id) throw Out_of_metadata();
/* return reference to the new kernel-object */
Native_capability c(id, 0);
return reinterpret_cap_cast<Signal_receiver>(c);
}
Signal_context_capability
Signal_session_component::alloc_context(Signal_receiver_capability r,
unsigned long imprint)
{
/* create context kernel-object */
size_t const s = Kernel::signal_context_size();
void * p;
if (!_contexts_slab.alloc(s, &p)) throw Out_of_metadata();
unsigned long const id = Kernel::new_signal_context(p, r.dst(), imprint);
if (!id) throw Out_of_metadata();
/* return reference to the new kernel-object */
Native_capability c(id, 0);
return reinterpret_cap_cast<Signal_context>(c);
}

View File

@ -0,0 +1,49 @@
#
# \brief The core of Genode
# \author Martin Stein
# \date 2011-12-16
#
# set program name
TARGET = core
# use core specific startup library
STARTUP_LIB = startup_core
# add library dependencies
LIBS += cxx raw_ipc heap process pager lock console signal raw_server \
syscall startup_core core_support
# add include paths
GEN_CORE_DIR = $(BASE_DIR)/src/core
INC_DIR += $(REP_DIR)/src/core/include $(REP_DIR)/include \
$(REP_DIR)/src/platform $(GEN_CORE_DIR)/include \
$(BASE_DIR)/src/platform $(BASE_DIR)/src/core/include \
$(BASE_DIR)/include
# add C++ sources
SRC_CC += main.cc _main.cc ram_session_component.cc \
ram_session_support.cc rom_session_component.cc \
pd_session_component.cc io_mem_session_component.cc \
io_mem_session_support.cc thread.cc platform_pd.cc platform.cc \
platform_thread.cc dataspace_component.cc rm_session_component.cc \
io_port_session_component.cc \
irq_session_component.cc signal_session_component.cc \
dump_alloc.cc cpu_session_component.cc \
cpu_session_support.cc console.cc
# declare file locations
vpath _main.cc $(BASE_DIR)/src/platform
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 dataspace_component.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)
vpath console.cc $(REP_DIR)/src/base
vpath % $(REP_DIR)/src/core

View File

@ -0,0 +1,92 @@
/*
* \brief Implementation of Thread API interface for core
* \author Martin Stein
* \date 2012-01-25
*/
/*
* Copyright (C) 2012 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 <kernel/log.h>
/* core includes */
#include <platform.h>
#include <platform_thread.h>
using namespace Genode;
extern Genode::Native_utcb * _main_utcb;
namespace Kernel { unsigned core_id(); }
Native_utcb * Thread_base::utcb()
{
/* this is the main thread */
if (!this) { return _main_utcb; }
/* this isn't the main thread */
return _tid->phys_utcb();
}
/**
* Returns 0 if this is the main thread or the thread base pointer otherwise
*/
Thread_base * Thread_base::myself()
{
/* get our platform thread wich holds our thread base or 0 */
Platform_thread * const pt = Kernel::get_thread();
if (pt) return pt->thread_base();
/* we are core main, the only thread beside idle with no platform thread */
else return 0;
}
static void thread_entry()
{
/* this is never called by a main thread */
Thread_base::myself()->entry();
}
Thread_base::Thread_base(const char *name, size_t stack_size)
: _list_element(this), _tid(0)
{
_tid = new (platform()->core_mem_alloc())
Platform_thread(name, this, stack_size, Kernel::core_id());
}
Thread_base::~Thread_base()
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
}
void Thread_base::start()
{
size_t const stack_size = _tid->stack_size()/sizeof(unsigned long) + 1;
void * const stack_base = new (platform()->core_mem_alloc())
unsigned long [stack_size];
void * sp = (void *)((addr_t)stack_base + _tid->stack_size());
void * ip = (void *)&thread_entry;
if (_tid->start(ip, sp)) PERR("Couldn't start thread");
}
void Thread_base::cancel_blocking()
{
kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n";
while (1) ;
}

View File

@ -0,0 +1,21 @@
/*
* \brief Kernel support specific for the Versatile VEA9X4
* \author Martin Stein
* \date 2012-04-23
*/
/*
* Copyright (C) 2012 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 _SRC__CORE__VEA9X4__KERNEL_SUPPORT_H_
#define _SRC__CORE__VEA9X4__KERNEL_SUPPORT_H_
/* local includes */
#include <cortex_a9/kernel_support.h>
#endif /* _SRC__CORE__VEA9X4__KERNEL_SUPPORT_H_ */

View File

@ -0,0 +1,83 @@
/*
* \brief Platform implementations specific for base-hw and VEA9X4
* \author Martin Stein
* \date 2012-04-27
*/
/*
* Copyright (C) 2012 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 <drivers/board/vea9x4.h>
#include <drivers/cpu/cortex_a9/core.h>
#include <drivers/pic/pl390_base.h>
/* Core includes */
#include <platform.h>
using namespace Genode;
Native_region * Platform::_ram_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ Vea9x4::LOCAL_DDR2_BASE, Vea9x4::LOCAL_DDR2_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_irq_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ 0, Pl390_base::MAX_INTERRUPT_ID + 1 }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_core_only_irq_regions(unsigned const i)
{
static Native_region _regions[] =
{
/* Core timer */
{ Cortex_a9::PRIVATE_TIMER_IRQ, 1 },
/* Core UART */
{ Vea9x4::PL011_0_IRQ, 1 }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_mmio_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ Vea9x4::SMB_CS7_BASE, Vea9x4::SMB_CS7_SIZE },
{ Vea9x4::SMB_CS0_TO_CS6_BASE, Vea9x4::SMB_CS0_TO_CS6_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_core_only_mmio_regions(unsigned const i)
{
static Native_region _regions[] =
{
/* Core timer and PIC */
{ Vea9x4::CORTEX_A9_PRIVATE_MEM_BASE,
Vea9x4::CORTEX_A9_PRIVATE_MEM_SIZE },
/* Core UART */
{ Vea9x4::PL011_0_MMIO_BASE, Vea9x4::PL011_0_MMIO_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}

View File

@ -0,0 +1,26 @@
/*
* \brief Software TLB controls specific for the Versatile VEA9X4
* \author Martin Stein
* \date 2012-04-23
*/
/*
* Copyright (C) 2012 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 _SRC__CORE__VEA9X4__SOFTWARE_TLB_H_
#define _SRC__CORE__VEA9X4__SOFTWARE_TLB_H_
/* Genode includes */
#include <drivers/cpu/cortex_a9/section_table.h>
/**
* Software TLB controls
*/
class Software_tlb : public Genode::Section_table { };
#endif /* _SRC__CORE__VEA9X4__SOFTWARE_TLB_H_ */

View File

@ -0,0 +1,20 @@
/*
* \brief Platform-specific helper functions for the _main() function
* \author Martin Stein
* \date 2010-09-13
*/
/*
* Copyright (C) 2010-2012 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 _SRC__PLATFORM__MAIN_HELPER_H_
#define _SRC__PLATFORM__MAIN_HELPER_H_
static void main_thread_bootstrap() { }
#endif /* _SRC__PLATFORM__MAIN_HELPER_H_ */

View File

@ -0,0 +1,61 @@
/**
* \brief Startup code for Genode programs on Cortex A9
* \author Martin Stein
* \date 2011-10-01
*/
/*
* Copyright (C) 2012 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.
*/
.section .text
/* ELF entry symbol */
.global _start
_start:
/* zero-fill BSS segment but don't pollute thread-entry arguments */
.extern _bss_start
ldr r4, =_bss_start
.extern _bss_end
ldr r3, =_bss_end
mov r2, #0
sub r3, r3, #4
1:
str r2, [r4]
add r4, r4, #4
cmp r4, r3
bne 1b
/* fetch thread-entry arguments to their destinations in BSS */
ldr r1, =_main_utcb
str r0, [r1]
/* call _main routine */
ldr sp, =_main_stack_high
.extern _main
bl _main
1:
b 1b
/* dynamic symbol object handle */
.align 3
.global __dso_handle
__dso_handle: .long 0
.section .bss
/* main-thread stack */
.align 3
.space 64*1024
.global _main_stack_high
_main_stack_high:
/* main-thread UTCB-pointer for the Genode thread-API */
.align 3
.global _main_utcb
_main_utcb: .long 0

View File

@ -0,0 +1,123 @@
/*
* \brief Linker script for Genode programs
* \author Christian Helmuth
* \date 2006-04-12
*/
/*
* Copyright (C) 2006-2012 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.
*/
ENTRY(_start)
PHDRS
{
ro PT_LOAD;
rw PT_LOAD;
}
SECTIONS
{
.text : {
_prog_img_beg = .;
*(.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 : {
/*
* Leave space for parent capability parameters at start of data
* section. The protection domain creator is reponsible for storing
* sane values here.
*/
_parent_cap = .;
_parent_cap_thread_id = .;
LONG(0xffffffff);
_parent_cap_local_name = .;
LONG(0xffffffff);
/*
* Platform-specific entry for Fiasco.OC.
*
* PIC-code compiled for Fiasco.OC, needs some PIC-compatible
* way to enter the kernel, the fixed address of the kernel
* entry code address needs to be found here.
*/
__l4sys_invoke_indirect = .;
LONG(0xeacff000);
*(.data .data.* .gnu.linkonce.d.*)
} : rw
/* exception frames for C++ */
.eh_frame : {
__eh_frame_start__ = .;
KEEP (*(.eh_frame))
LONG(0)
} : rw
.init_array : {
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
}
.gcc_except_table : {
KEEP(*(.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
.bss : {
_bss_start = .;
*(.bss .bss.* .gnu.linkonce.b.* COMMON)
}
_bss_end = .;
_prog_img_end = .;
/DISCARD/ : {
*(.note)
*(.note.ABI-tag)
*(.comment)
}
}