mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 12:32:56 +01:00
Imported Genode release 11.11
This commit is contained in:
committed by
Christian Helmuth
parent
6bcc9aef0e
commit
da4e1feaa5
1
base-linux/README
Normal file
1
base-linux/README
Normal file
@@ -0,0 +1 @@
|
||||
This repository contains the Linux-specific implementation of Genode.
|
||||
22
base-linux/etc/specs.conf
Normal file
22
base-linux/etc/specs.conf
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Description of build platform
|
||||
#
|
||||
|
||||
#
|
||||
# If you want to build the Linux-specific Genode
|
||||
# binaries, use this config option.
|
||||
#
|
||||
ifeq ($(shell uname -m),x86_64)
|
||||
SPECS ?= genode linux_x86_64 sdl
|
||||
else
|
||||
SPECS ?= genode linux_x86_32 sdl
|
||||
endif
|
||||
|
||||
#
|
||||
# If you want to build for the host platform,
|
||||
# use the following config option.
|
||||
# You need to specify '32bit' additionally to 'host'
|
||||
# to include the 32bit-specific Genode include path
|
||||
# containing integer definitions.
|
||||
#
|
||||
#SPECS ?= host 32bit
|
||||
64
base-linux/include/base/ipc_msgbuf.h
Normal file
64
base-linux/include/base/ipc_msgbuf.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* \brief Linux-specific layout of IPC message buffer
|
||||
* \author Norman Feske
|
||||
* \date 2006-06-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
|
||||
#define _INCLUDE__BASE__IPC_MSGBUF_H_
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* IPC message buffer layout
|
||||
*/
|
||||
class Msgbuf_base
|
||||
{
|
||||
protected:
|
||||
|
||||
Genode::size_t _size;
|
||||
char _msg_start[]; /* symbol marks start of message buffer data */
|
||||
|
||||
/*
|
||||
* No member variables are allowed beyond this point!
|
||||
*/
|
||||
|
||||
public:
|
||||
|
||||
char buf[];
|
||||
|
||||
/**
|
||||
* Return size of message buffer
|
||||
*/
|
||||
inline Genode::size_t size() const { return _size; };
|
||||
|
||||
/**
|
||||
* Return address of message buffer
|
||||
*/
|
||||
inline void *addr() { return &_msg_start[0]; };
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Pump up IPC message buffer to specified buffer size
|
||||
*/
|
||||
template <unsigned BUF_SIZE>
|
||||
class Msgbuf : public Msgbuf_base
|
||||
{
|
||||
public:
|
||||
|
||||
char buf[BUF_SIZE];
|
||||
|
||||
Msgbuf() { _size = BUF_SIZE; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
|
||||
89
base-linux/include/base/local_interface.h
Normal file
89
base-linux/include/base/local_interface.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* \brief Support for process-local pseudo capabilities
|
||||
* \author Norman Feske
|
||||
* \date 2011-11-21
|
||||
*
|
||||
* Pseudo capabilities have a zero 'tid' and a non-zero 'local_name'. The local
|
||||
* name is a pointer to the local object implementing the interface. Pseudo
|
||||
* capabilties are valid only as arguments for local services that are prepared
|
||||
* for it. I.e., the locally implemented RM service accepts pseudo dataspace
|
||||
* capabilities that refer to managed dataspaces. Or the Linux-specific
|
||||
* 'Rm_session_client' takes a pseudo capability to target RM-session
|
||||
* invokations to the local implementation.
|
||||
*
|
||||
* Please note that this header file is not part of the official Genode API.
|
||||
* It exists on no other platform than Linux and is meant for Genode-internal
|
||||
* use only.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__LOCAL_INTERFACE_H_
|
||||
#define _INCLUDE__BASE__LOCAL_INTERFACE_H_
|
||||
|
||||
#include <base/capability.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* Common base class of local interface implementations
|
||||
*/
|
||||
struct Local_interface
|
||||
{
|
||||
virtual ~Local_interface() { }
|
||||
|
||||
/**
|
||||
* Exception type
|
||||
*/
|
||||
class Non_local_capability { };
|
||||
|
||||
/**
|
||||
* Convert pseudo capability to pointer to locally implemented session
|
||||
*
|
||||
* \param IF interface type
|
||||
* \param cap pseudo capability
|
||||
*
|
||||
* \throw Non_local_capability if the argument does not refer to a
|
||||
* locally implemented interface
|
||||
*/
|
||||
template <typename IF>
|
||||
static IF *deref(Capability<IF> cap)
|
||||
{
|
||||
/* check if this is a pseudo capability */
|
||||
if (cap.tid() != 0 || !cap.local_name())
|
||||
throw Non_local_capability();
|
||||
|
||||
/*
|
||||
* For a pseudo capability, the 'local_name' points to the local
|
||||
* session object of the correct type.
|
||||
*/
|
||||
IF *interface = dynamic_cast<IF *>((Local_interface *)cap.local_name());
|
||||
if (!interface)
|
||||
throw Non_local_capability();
|
||||
|
||||
return interface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct pseudo capability to process-local interface implementation
|
||||
*
|
||||
* \param IF interface type
|
||||
* \param interface pointer to local interface implementation
|
||||
* \return pseudo capability
|
||||
*
|
||||
*/
|
||||
template <typename IF>
|
||||
static Capability<IF> capability(IF *interface)
|
||||
{
|
||||
return reinterpret_cap_cast<IF>(Native_capability(0, (long)interface));
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__LOCAL_INTERFACE_H_ */
|
||||
135
base-linux/include/base/native_types.h
Normal file
135
base-linux/include/base/native_types.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* \brief Native types
|
||||
* \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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__NATIVE_TYPES_H_
|
||||
#define _INCLUDE__BASE__NATIVE_TYPES_H_
|
||||
|
||||
/*
|
||||
* We cannot just include <semaphore.h> and <pthread.h> here
|
||||
* because this would impy the nested inclusion of a myriad
|
||||
* of Linux types and would pollute the namespace for everyone
|
||||
* who includes this header file. We want to cleanly separate
|
||||
* Genode from POSIX.
|
||||
*/
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* Native lock type
|
||||
*
|
||||
* We are using a sleeping spinlock as lock implementation on Linux. This
|
||||
* is a temporary solution until we have implemented futex-based locking.
|
||||
* In a previous version, we have relied on POSIX semaphores as provided by
|
||||
* the glibc. However, relying on the glibc badly interferes with a custom
|
||||
* libc implementation. The glibc semaphore implementation expects to find
|
||||
* a valid pthread structure via the TLS pointer. We do not have such a
|
||||
* structure because we create threads via the 'clone' system call rather
|
||||
* than 'pthread_create'. Hence we have to keep the base framework clean
|
||||
* from glibc usage altogether.
|
||||
*/
|
||||
typedef volatile int Native_lock;
|
||||
|
||||
/**
|
||||
* Thread ID used in lock implementation
|
||||
*
|
||||
* Unfortunately, both - PID and TID - are needed for lx_tgkill() in
|
||||
* thread_check_stopped_and_restart().
|
||||
*/
|
||||
struct Native_thread_id
|
||||
{
|
||||
unsigned int tid; /* Native thread ID type as returned by the
|
||||
'clone' system call */
|
||||
unsigned int pid; /* process ID (resp. thread-group ID) */
|
||||
|
||||
Native_thread_id() : tid(0), pid(0) { }
|
||||
Native_thread_id(unsigned int tid, unsigned int pid)
|
||||
: tid(tid), pid(pid) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Native thread contains more thread-local data than just the ID
|
||||
*
|
||||
* A thread needs two sockets as it may be a server that depends on another
|
||||
* service during request processing. If the server socket would be used for
|
||||
* the client call, the server thread may be unblocked by further requests
|
||||
* from its clients. In other words, the additional client socket provides
|
||||
* closed-receive semantics in calls. An even better solution is to use
|
||||
* SCM_RIGHTS messages to send a client socket descriptor with the request.
|
||||
*/
|
||||
struct Native_thread : Native_thread_id
|
||||
{
|
||||
int client; /* socket used as IPC client */
|
||||
int server; /* socket used as IPC server */
|
||||
|
||||
Native_thread() : client(-1), server(-1) { }
|
||||
};
|
||||
|
||||
inline bool operator == (Native_thread_id t1, Native_thread_id t2) {
|
||||
return (t1.tid == t2.tid) && (t1.pid == t2.pid); }
|
||||
|
||||
inline bool operator != (Native_thread_id t1, Native_thread_id t2) {
|
||||
return (t1.tid != t2.tid) || (t1.pid != t2.pid); }
|
||||
|
||||
/**
|
||||
* Empty UTCB type expected by the thread library, unused on Linux
|
||||
*/
|
||||
typedef struct { } Native_utcb;
|
||||
|
||||
/*
|
||||
* On Linux, the local_name member of a capability is global
|
||||
* to the whole system. Therefore, capabilities are to be
|
||||
* created at a central place that prevents id clashes.
|
||||
*/
|
||||
class Native_capability
|
||||
{
|
||||
protected:
|
||||
|
||||
long _tid; /* target thread */
|
||||
long _local_name;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
Native_capability() : _tid(0), _local_name(0) { }
|
||||
|
||||
long local_name() const { return _local_name; }
|
||||
|
||||
bool valid() const { return _tid != 0; }
|
||||
|
||||
|
||||
/****************************************************
|
||||
** Functions to be used by the Linux backend only **
|
||||
****************************************************/
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* This constructor can be called to create a Linux
|
||||
* capability by hand. It must never be used from
|
||||
* generic code!
|
||||
*/
|
||||
Native_capability(long tid, long local_name)
|
||||
: _tid(tid), _local_name(local_name) { }
|
||||
|
||||
/**
|
||||
* Access raw capability data
|
||||
*/
|
||||
long tid() const { return _tid; }
|
||||
};
|
||||
|
||||
typedef int Native_connection_state; /* socket descriptor */
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */
|
||||
43
base-linux/include/base/pager.h
Normal file
43
base-linux/include/base/pager.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* \brief Paging-server framework
|
||||
* \author Norman Feske
|
||||
* \author Christian Helmuth
|
||||
* \date 2006-04-28
|
||||
*
|
||||
* Linux dummies
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__PAGER_H_
|
||||
#define _INCLUDE__BASE__PAGER_H_
|
||||
|
||||
#include <base/signal.h>
|
||||
#include <pager/capability.h>
|
||||
#include <cap_session/cap_session.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Pager_object
|
||||
{
|
||||
virtual ~Pager_object() { }
|
||||
|
||||
void exception_handler(Signal_context_capability) { }
|
||||
};
|
||||
|
||||
class Pager_activation_base { };
|
||||
struct Pager_entrypoint
|
||||
{
|
||||
Pager_entrypoint(Cap_session *, Pager_activation_base *) { }
|
||||
|
||||
Pager_object *obj_by_cap(Pager_capability) { return 0; }
|
||||
};
|
||||
template <int FOO> class Pager_activation : public Pager_activation_base { };
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__PAGER_H_ */
|
||||
379
base-linux/include/base/platform_env.h
Normal file
379
base-linux/include/base/platform_env.h
Normal file
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* \brief Linux-specific environment
|
||||
* \author Norman Feske
|
||||
* \author Christian Helmuth
|
||||
* \date 2006-07-28
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__PLATFORM_ENV_H_
|
||||
#define _INCLUDE__BASE__PLATFORM_ENV_H_
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <base/local_interface.h>
|
||||
#include <base/heap.h>
|
||||
#include <parent/client.h>
|
||||
#include <ram_session/client.h>
|
||||
#include <cpu_session/client.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Platform_env : public Env
|
||||
{
|
||||
private:
|
||||
|
||||
/**************************
|
||||
** Local region manager **
|
||||
**************************/
|
||||
|
||||
class Region
|
||||
{
|
||||
private:
|
||||
|
||||
addr_t _start;
|
||||
off_t _offset;
|
||||
Dataspace_capability _ds;
|
||||
size_t _size;
|
||||
|
||||
/**
|
||||
* Return offset of first byte after the region
|
||||
*/
|
||||
addr_t _end() const { return _start + _size; }
|
||||
|
||||
public:
|
||||
|
||||
Region() : _start(0), _offset(0), _size(0) { }
|
||||
|
||||
Region(addr_t start, off_t offset, Dataspace_capability ds, size_t size)
|
||||
: _start(start), _offset(offset), _ds(ds), _size(size) { }
|
||||
|
||||
bool used() const { return _size > 0; }
|
||||
addr_t start() const { return _start; }
|
||||
off_t offset() const { return _offset; }
|
||||
size_t size() const { return _size; }
|
||||
Dataspace_capability dataspace() const { return _ds; }
|
||||
|
||||
bool intersects(Region const &r) const
|
||||
{
|
||||
return (r.start() < _end()) && (_start < r._end());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Meta data about dataspaces attached to an RM session
|
||||
*/
|
||||
class Region_map
|
||||
{
|
||||
public:
|
||||
|
||||
enum { MAX_REGIONS = 4096 };
|
||||
|
||||
private:
|
||||
|
||||
Region _map[MAX_REGIONS];
|
||||
|
||||
bool _id_valid(int id) const {
|
||||
return (id >= 0 && id < MAX_REGIONS); }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Add region to region map
|
||||
*
|
||||
* \return region ID, or
|
||||
* -1 if out of metadata, or
|
||||
* -2 if region conflicts existing region
|
||||
*/
|
||||
int add_region(Region const ®ion)
|
||||
{
|
||||
/*
|
||||
* Check for region conflicts
|
||||
*/
|
||||
for (int i = 0; i < MAX_REGIONS; i++) {
|
||||
if (_map[i].intersects(region))
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate new region metadata
|
||||
*/
|
||||
int i;
|
||||
for (i = 0; i < MAX_REGIONS; i++)
|
||||
if (!_map[i].used()) break;
|
||||
|
||||
if (i == MAX_REGIONS) {
|
||||
PERR("maximum number of %d regions reached",
|
||||
MAX_REGIONS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_map[i] = region;
|
||||
return i;
|
||||
}
|
||||
|
||||
Region region(int id) const
|
||||
{
|
||||
return _id_valid(id) ? _map[id] : Region();
|
||||
}
|
||||
|
||||
Region lookup(addr_t start)
|
||||
{
|
||||
for (int i = 0; i < MAX_REGIONS; i++)
|
||||
if (_map[i].start() == start)
|
||||
return _map[i];
|
||||
return Region();
|
||||
}
|
||||
|
||||
void remove_region(addr_t start)
|
||||
{
|
||||
for (int i = 0; i < MAX_REGIONS; i++)
|
||||
if (_map[i].start() == start)
|
||||
_map[i] = Region();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* On Linux, we use a local region manager session
|
||||
* that attaches dataspaces via mmap to the local
|
||||
* address space.
|
||||
*/
|
||||
class Rm_session_mmap : public Local_interface,
|
||||
public Rm_session,
|
||||
public Dataspace
|
||||
{
|
||||
private:
|
||||
|
||||
Lock _lock; /* protect '_rmap' */
|
||||
Region_map _rmap;
|
||||
bool const _sub_rm; /* false if RM session is root */
|
||||
size_t const _size;
|
||||
|
||||
/**
|
||||
* Base offset of the RM session
|
||||
*
|
||||
* For a normal RM session (the one that comes with the
|
||||
* 'env()', this value is zero. If the RM session is
|
||||
* used as nested dataspace, '_base' contains the address
|
||||
* where the managed dataspace is attached in the root RM
|
||||
* session.
|
||||
*
|
||||
* Note that a managed dataspace cannot be attached more
|
||||
* than once. Furthermore, managed dataspace cannot be
|
||||
* attached to another managed dataspace. The nested
|
||||
* dataspace emulation is solely implemented to support
|
||||
* the common use case of managed dataspaces as mechanism
|
||||
* to reserve parts of the local address space from being
|
||||
* populated by the 'env()->rm_session()'. (i.e., for the
|
||||
* context area, or for the placement of consecutive
|
||||
* shared-library segments)
|
||||
*/
|
||||
addr_t _base;
|
||||
|
||||
bool _is_attached() const { return _base > 0; }
|
||||
|
||||
void _add_to_rmap(Region const &);
|
||||
|
||||
public:
|
||||
|
||||
Rm_session_mmap(bool sub_rm, size_t size = ~0)
|
||||
: _sub_rm(sub_rm), _size(size), _base(0) { }
|
||||
|
||||
~Rm_session_mmap()
|
||||
{
|
||||
/* detach sub RM session when destructed */
|
||||
if (_sub_rm && _is_attached())
|
||||
env()->rm_session()->detach((void *)_base);
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
** Region manager session interface **
|
||||
**************************************/
|
||||
|
||||
Local_addr attach(Dataspace_capability ds, size_t size,
|
||||
off_t, bool, Local_addr);
|
||||
|
||||
void detach(Local_addr local_addr);
|
||||
|
||||
Pager_capability add_client(Thread_capability thread) {
|
||||
return Pager_capability(); }
|
||||
|
||||
void fault_handler(Signal_context_capability handler) { }
|
||||
|
||||
State state() { return State(); }
|
||||
|
||||
|
||||
/*************************
|
||||
** Dataspace interface **
|
||||
*************************/
|
||||
|
||||
size_t size() { return _size; }
|
||||
|
||||
addr_t phys_addr() { return 0; }
|
||||
|
||||
bool writable() { return true; }
|
||||
|
||||
/**
|
||||
* Return pseudo dataspace capability of the RM session
|
||||
*
|
||||
* The capability returned by this function is only usable
|
||||
* as argument to 'Rm_session_mmap::attach'. It is not a
|
||||
* real capability.
|
||||
*/
|
||||
Dataspace_capability dataspace()
|
||||
{
|
||||
return Local_interface::capability(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Expanding_ram_session_client : public Ram_session_client
|
||||
{
|
||||
Ram_session_capability _cap;
|
||||
|
||||
public:
|
||||
|
||||
Expanding_ram_session_client(Ram_session_capability cap)
|
||||
: Ram_session_client(cap), _cap(cap) { }
|
||||
|
||||
Ram_dataspace_capability alloc(size_t size) {
|
||||
bool try_again;
|
||||
do {
|
||||
try_again = false;
|
||||
try {
|
||||
return Ram_session_client::alloc(size);
|
||||
|
||||
} catch (Ram_session::Out_of_metadata) {
|
||||
|
||||
/* give up if the error occurred a second time */
|
||||
if (try_again)
|
||||
break;
|
||||
|
||||
PINF("upgrade quota donation for Env::RAM session");
|
||||
env()->parent()->upgrade(_cap, "ram_quota=8K");
|
||||
try_again = true;
|
||||
}
|
||||
} while (try_again);
|
||||
|
||||
return Ram_dataspace_capability();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Local interceptor of parent requests
|
||||
*
|
||||
* On Linux, we need to intercept calls to the parent interface to
|
||||
* implement the RM service locally. This particular service is
|
||||
* used for creating managed dataspaces, which allow the
|
||||
* reservation of parts of the local address space from being
|
||||
* automatically managed by the 'env()->rm_session()'.
|
||||
*
|
||||
* All requests that do not refer to the RM service are passed
|
||||
* through the real parent interface.
|
||||
*/
|
||||
class Local_parent : public Parent_client
|
||||
{
|
||||
public:
|
||||
|
||||
/**********************
|
||||
** Parent interface **
|
||||
**********************/
|
||||
|
||||
Session_capability session(Service_name const &,
|
||||
Session_args const &);
|
||||
void close(Session_capability);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param parent_cap real parent capability used to
|
||||
* promote requests to non-local
|
||||
* services
|
||||
*/
|
||||
Local_parent(Parent_capability parent_cap);
|
||||
};
|
||||
|
||||
|
||||
/*************************************
|
||||
** Linux-specific helper functions **
|
||||
*************************************/
|
||||
|
||||
/**
|
||||
* Read Unix environment variable as long value
|
||||
*/
|
||||
static unsigned long _get_env_ulong(const char *key);
|
||||
|
||||
|
||||
Parent_capability _parent_cap()
|
||||
{
|
||||
long tid = _get_env_ulong("parent_tid");
|
||||
long local_name = _get_env_ulong("parent_local_name");
|
||||
|
||||
/* produce typed capability manually */
|
||||
return reinterpret_cap_cast<Parent>(Native_capability(tid, local_name));
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
** Platform-specific members **
|
||||
*******************************/
|
||||
|
||||
Local_parent _parent;
|
||||
Ram_session_capability _ram_session_cap;
|
||||
Expanding_ram_session_client _ram_session_client;
|
||||
Cpu_session_client _cpu_session_client;
|
||||
Rm_session_mmap _rm_session_mmap;
|
||||
Heap _heap;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Standard constructor
|
||||
*/
|
||||
Platform_env()
|
||||
:
|
||||
_parent(_parent_cap()),
|
||||
_ram_session_cap(static_cap_cast<Ram_session>(parent()->session("Env::ram_session", ""))),
|
||||
_ram_session_client(_ram_session_cap),
|
||||
_cpu_session_client(static_cap_cast<Cpu_session>(parent()->session("Env::cpu_session", ""))),
|
||||
_rm_session_mmap(false),
|
||||
_heap(&_ram_session_client, &_rm_session_mmap)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Platform_env() { parent()->exit(0); }
|
||||
|
||||
|
||||
/*******************
|
||||
** Env interface **
|
||||
*******************/
|
||||
|
||||
Parent *parent() { return &_parent; }
|
||||
Ram_session *ram_session() { return &_ram_session_client; }
|
||||
Ram_session_capability ram_session_cap() { return _ram_session_cap; }
|
||||
Rm_session *rm_session() { return &_rm_session_mmap; }
|
||||
Heap *heap() { return &_heap; }
|
||||
Cpu_session *cpu_session() { return &_cpu_session_client; }
|
||||
Pd_session *pd_session() { return 0; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__PLATFORM_ENV_H_ */
|
||||
47
base-linux/include/linux_dataspace/client.h
Normal file
47
base-linux/include/linux_dataspace/client.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* \brief Linux-specific dataspace client interface
|
||||
* \author Norman Feske
|
||||
* \date 2006-05-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__LINUX_DATASPACE__CLIENT_H_
|
||||
#define _INCLUDE__LINUX_DATASPACE__CLIENT_H_
|
||||
|
||||
#include <dataspace/client.h>
|
||||
#include <linux_dataspace/linux_dataspace.h>
|
||||
#include <base/rpc_client.h>
|
||||
#include <util/string.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Linux_dataspace_client : Rpc_client<Linux_dataspace>
|
||||
{
|
||||
explicit Linux_dataspace_client(Dataspace_capability ds)
|
||||
: Rpc_client<Linux_dataspace>(static_cap_cast<Linux_dataspace>(ds)) { }
|
||||
|
||||
|
||||
/*********************************
|
||||
** Generic dataspace interface **
|
||||
*********************************/
|
||||
|
||||
size_t size() { return call<Rpc_size>(); }
|
||||
addr_t phys_addr() { return call<Rpc_phys_addr>(); }
|
||||
bool writable() { return call<Rpc_writable>(); }
|
||||
|
||||
|
||||
/****************************************
|
||||
** Linux-specific dataspace interface **
|
||||
****************************************/
|
||||
|
||||
Filename fname() { return call<Rpc_fname>(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__LINUX_DATASPACE__CLIENT_H_ */
|
||||
47
base-linux/include/linux_dataspace/linux_dataspace.h
Normal file
47
base-linux/include/linux_dataspace/linux_dataspace.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* \brief Linux-specific dataspace interface
|
||||
* \author Norman Feske
|
||||
* \date 2006-07-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__LINUX_DATASPACE__LINUX_DATASPACE_H_
|
||||
#define _INCLUDE__LINUX_DATASPACE__LINUX_DATASPACE_H_
|
||||
|
||||
#include <dataspace/dataspace.h>
|
||||
#include <base/stdint.h>
|
||||
#include <base/ipc.h>
|
||||
#include <base/rpc.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Linux_dataspace : Dataspace
|
||||
{
|
||||
enum { FNAME_LEN = 32 };
|
||||
|
||||
struct Filename { char buf[FNAME_LEN]; };
|
||||
|
||||
virtual ~Linux_dataspace() { }
|
||||
|
||||
/**
|
||||
* Request name of file that represents the dataspace on Linux
|
||||
*/
|
||||
virtual Filename fname() = 0;
|
||||
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
|
||||
GENODE_RPC(Rpc_fname, Filename, fname);
|
||||
GENODE_RPC_INTERFACE_INHERIT(Dataspace, Rpc_fname);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__LINUX_DATASPACE__LINUX_DATASPACE_H_ */
|
||||
59
base-linux/include/rm_session/client.h
Normal file
59
base-linux/include/rm_session/client.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* \brief Pseudo RM-session client stub targeting the process-local RM service
|
||||
* \author Norman Feske
|
||||
* \date 2011-11-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__RM_SESSION__CLIENT_H_
|
||||
#define _INCLUDE__RM_SESSION__CLIENT_H_
|
||||
|
||||
#include <base/local_interface.h>
|
||||
#include <rm_session/capability.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Rm_session_client : Rm_session
|
||||
{
|
||||
Rm_session_capability const _cap;
|
||||
|
||||
/**
|
||||
* Return pointer to locally implemented RM session
|
||||
*
|
||||
* \throw Local_interface::Non_local_capability
|
||||
*/
|
||||
Rm_session *_local() const { return Local_interface::deref(_cap); }
|
||||
|
||||
explicit Rm_session_client(Rm_session_capability session)
|
||||
: _cap(session) { }
|
||||
|
||||
Local_addr attach(Dataspace_capability ds, size_t size, off_t offset,
|
||||
bool use_local_addr, Local_addr local_addr)
|
||||
{
|
||||
return _local()->attach(ds, size, offset, use_local_addr, local_addr);
|
||||
}
|
||||
|
||||
void detach(Local_addr local_addr) {
|
||||
return _local()->detach(local_addr); }
|
||||
|
||||
Pager_capability add_client(Thread_capability thread) {
|
||||
return _local()->add_client(thread); }
|
||||
|
||||
void fault_handler(Signal_context_capability handler) {
|
||||
return _local()->fault_handler(handler); }
|
||||
|
||||
State state() {
|
||||
return _local()->state(); }
|
||||
|
||||
Dataspace_capability dataspace() {
|
||||
return _local()->dataspace(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__RM_SESSION__CLIENT_H_ */
|
||||
92
base-linux/lib/import/import-lx_hybrid.mk
Normal file
92
base-linux/lib/import/import-lx_hybrid.mk
Normal file
@@ -0,0 +1,92 @@
|
||||
#
|
||||
# Make Linux headers of the host platform available to the program
|
||||
#
|
||||
include $(call select_from_repositories,lib/import/import-syscall.mk)
|
||||
|
||||
#
|
||||
# Manually supply all library search paths of the host compiler to our tool
|
||||
# chain.
|
||||
#
|
||||
HOST_LIB_SEARCH_DIRS := $(shell cc -print-search-dirs | grep libraries |\
|
||||
sed "s/.*=//" | sed "s/:/ /g" |\
|
||||
sed "s/\/ / /g" | sed "s/\/\$$//")
|
||||
#
|
||||
# Add search path for 'limits.h'
|
||||
#
|
||||
INC_DIR += $(shell echo "int main() {return 0;}" |\
|
||||
LANG=C $(CXX) -x c++ -v -E - 2>&1 |\
|
||||
sed '/^\#include <\.\.\.> search starts here:/,/^End of search list/!d' |\
|
||||
grep "include-fixed")
|
||||
|
||||
#
|
||||
# Add search paths for normal libraries
|
||||
#
|
||||
CXX_LINK_OPT += $(addprefix -L,$(HOST_LIB_SEARCH_DIRS))
|
||||
|
||||
#
|
||||
# Add search paths for shared-library lookup
|
||||
#
|
||||
# We add all locations of shared libraries present in the ld.cache to our
|
||||
# library search path.
|
||||
#
|
||||
HOST_SO_SEARCH_DIRS := $(sort $(dir $(shell ldconfig -p | sed "s/^.* \//\//" | grep "^\/")))
|
||||
LINK_ARG_PREFIX := -Wl,
|
||||
CXX_LINK_OPT += $(addprefix $(LINK_ARG_PREFIX)-rpath-link $(LINK_ARG_PREFIX),$(HOST_SO_SEARCH_DIRS))
|
||||
|
||||
#
|
||||
# The '__libc_csu_init' function is normally provided by the C library. We
|
||||
# override the libc's version in our 'lx_hybrid' library to have a hook for
|
||||
# Genode-specific initializations. Unfortunately, this way, we get two symbols
|
||||
# with the same name. So we have to tell the linker to be forgiving. The order
|
||||
# of the libraries at the linker command line determines which symbol is used.
|
||||
# Therefore it is important to have 'lx_hybrid.lib.so' listed before '-lc',
|
||||
# which is always the case when supplying '-lc' via 'EXT_OBJECTS' (not
|
||||
# 'CXX_LINK_OPT').
|
||||
#
|
||||
CXX_LINK_OPT += -Wl,--allow-multiple-definition
|
||||
|
||||
#
|
||||
# Make exceptions work
|
||||
#
|
||||
CXX_LINK_OPT += -Wl,--eh-frame-hdr
|
||||
|
||||
#
|
||||
# Add all libraries and their dependencies specified at the 'LX_LIBS'
|
||||
# variable to the linker command line
|
||||
#
|
||||
ifneq ($(LX_LIBS),)
|
||||
EXT_OBJECTS = $(shell pkg-config --static --libs $(LX_LIBS))
|
||||
endif
|
||||
|
||||
#
|
||||
# Use the host's startup codes, linker script, and dynamic linker
|
||||
#
|
||||
EXT_OBJECTS += $(shell cc -print-file-name=crt1.o)
|
||||
EXT_OBJECTS += $(shell cc -print-file-name=crti.o)
|
||||
EXT_OBJECTS += $(shell cc -print-file-name=crtbegin.o)
|
||||
EXT_OBJECTS += $(shell cc -print-file-name=crtend.o)
|
||||
EXT_OBJECTS += $(shell cc -print-file-name=crtn.o)
|
||||
EXT_OBJECTS += -lgcc -lgcc_s -lsupc++ -lc
|
||||
|
||||
#
|
||||
# Some header files installed on GNU/Linux test for the GNU compiler. For
|
||||
# example, 'stdio.h' might complain with the following error otherwise:
|
||||
#
|
||||
# /usr/include/stdio.h:432:27: error: expected initializer before ‘throw’
|
||||
# /usr/include/stdio.h:488:6: error: expected initializer before ‘throw’
|
||||
#
|
||||
# By manually defining '_GNU_SOURCE', the header files are processed as
|
||||
# expected.
|
||||
#
|
||||
CC_OPT += -D_GNU_SOURCE
|
||||
|
||||
USE_HOST_LD_SCRIPT = yes
|
||||
|
||||
ifeq (x86_64,$(findstring x86_64,$(SPECS)))
|
||||
CXX_LINK_OPT += -Wl,--dynamic-linker=/lib64/ld-linux-x86-64.so.2
|
||||
else
|
||||
CXX_LINK_OPT += -Wl,--dynamic-linker=/lib/ld-linux.so.2
|
||||
endif
|
||||
|
||||
# because we use the host compiler's libgcc, omit the Genode toolchain's version
|
||||
LD_LIBGCC =
|
||||
6
base-linux/lib/import/import-syscall.mk
Normal file
6
base-linux/lib/import/import-syscall.mk
Normal file
@@ -0,0 +1,6 @@
|
||||
INC_DIR += $(dir $(call select_from_repositories,src/platform/linux_syscalls.h))
|
||||
INC_DIR += /usr/include
|
||||
|
||||
# needed for Ubuntu 11.04
|
||||
INC_DIR += /usr/include/i386-linux-gnu
|
||||
INC_DIR += /usr/include/x86_64-linux-gnu
|
||||
5
base-linux/lib/mk/core_printf.mk
Normal file
5
base-linux/lib/mk/core_printf.mk
Normal file
@@ -0,0 +1,5 @@
|
||||
SRC_CC = core_printf.cc
|
||||
LIBS = cxx console syscall
|
||||
INC_DIR += $(REP_DIR)/src/base/console
|
||||
|
||||
vpath core_printf.cc $(BASE_DIR)/src/base/console
|
||||
6
base-linux/lib/mk/env.mk
Normal file
6
base-linux/lib/mk/env.mk
Normal file
@@ -0,0 +1,6 @@
|
||||
SRC_CC = env.cc rm_session_mmap.cc platform_env.cc debug.cc context_area.cc
|
||||
LIBS = ipc heap log_console lock syscall
|
||||
|
||||
vpath env.cc $(BASE_DIR)/src/base/env
|
||||
vpath context_area.cc $(BASE_DIR)/src/base/env
|
||||
vpath %.cc $(REP_DIR)/src/base/env
|
||||
5
base-linux/lib/mk/ipc.mk
Normal file
5
base-linux/lib/mk/ipc.mk
Normal file
@@ -0,0 +1,5 @@
|
||||
REQUIRES = linux
|
||||
SRC_CC = ipc.cc
|
||||
LIBS = syscall rpath
|
||||
|
||||
vpath ipc.cc $(REP_DIR)/src/base/ipc
|
||||
5
base-linux/lib/mk/lock.mk
Normal file
5
base-linux/lib/mk/lock.mk
Normal file
@@ -0,0 +1,5 @@
|
||||
SRC_CC = lock.cc
|
||||
LIBS = syscall
|
||||
INC_DIR += $(REP_DIR)/src/base/lock
|
||||
|
||||
vpath lock.cc $(BASE_DIR)/src/base/lock
|
||||
7
base-linux/lib/mk/lx_hybrid.mk
Normal file
7
base-linux/lib/mk/lx_hybrid.mk
Normal file
@@ -0,0 +1,7 @@
|
||||
SRC_CC = lx_hybrid.cc new_delete.cc
|
||||
LIBS += syscall env
|
||||
|
||||
vpath new_delete.cc $(BASE_DIR)/src/base/cxx
|
||||
vpath lx_hybrid.cc $(REP_DIR)/src/platform
|
||||
|
||||
CUSTOM_CXX = g++
|
||||
13
base-linux/lib/mk/process.mk
Normal file
13
base-linux/lib/mk/process.mk
Normal file
@@ -0,0 +1,13 @@
|
||||
SRC_CC = process.cc
|
||||
LIBS = syscall
|
||||
|
||||
#
|
||||
# The Linux version of the process library does not use Genode's ELF loader for
|
||||
# loading executables but the 'execve' system call. However, for supporting
|
||||
# dynamically linked executables, we have to take the decision of whether to load
|
||||
# the dynamic linker or a static executable based on information provided by
|
||||
# the ELF program header. We use the ELF library to obtain this information.
|
||||
#
|
||||
LIBS += elf
|
||||
|
||||
vpath process.cc $(REP_DIR)/src/base/process
|
||||
6
base-linux/lib/mk/rpath.mk
Normal file
6
base-linux/lib/mk/rpath.mk
Normal file
@@ -0,0 +1,6 @@
|
||||
REQUIRES = linux
|
||||
SRC_CC = linux_rpath.cc
|
||||
LIBS = syscall
|
||||
|
||||
vpath linux_rpath.cc $(REP_DIR)/src/platform
|
||||
|
||||
6
base-linux/lib/mk/thread.mk
Normal file
6
base-linux/lib/mk/thread.mk
Normal file
@@ -0,0 +1,6 @@
|
||||
REQUIRES = linux
|
||||
SRC_CC = thread.cc thread_linux.cc
|
||||
LIBS = syscall
|
||||
|
||||
vpath thread.cc $(BASE_DIR)/src/base/thread
|
||||
vpath thread_linux.cc $(REP_DIR)/src/base/thread
|
||||
8
base-linux/lib/mk/x86_32/startup.mk
Normal file
8
base-linux/lib/mk/x86_32/startup.mk
Normal file
@@ -0,0 +1,8 @@
|
||||
REQUIRES = linux x86
|
||||
LIBS = cxx lock syscall
|
||||
SRC_S = crt0.s
|
||||
SRC_CC = _main.cc
|
||||
INC_DIR += $(BASE_DIR)/src/platform
|
||||
|
||||
vpath crt0.s $(REP_DIR)/src/platform/x86_32
|
||||
vpath _main.cc $(dir $(call select_from_repositories,src/platform/_main.cc))
|
||||
5
base-linux/lib/mk/x86_32/syscall.mk
Normal file
5
base-linux/lib/mk/x86_32/syscall.mk
Normal file
@@ -0,0 +1,5 @@
|
||||
REQUIRES = linux x86
|
||||
SRC_S += lx_clone.S lx_syscall.S
|
||||
|
||||
vpath lx_clone.S $(REP_DIR)/../base-linux/src/platform/x86_32
|
||||
vpath lx_syscall.S $(REP_DIR)/../base-linux/src/platform/x86_32
|
||||
8
base-linux/lib/mk/x86_64/startup.mk
Normal file
8
base-linux/lib/mk/x86_64/startup.mk
Normal file
@@ -0,0 +1,8 @@
|
||||
REQUIRES = linux x86
|
||||
LIBS = cxx lock syscall
|
||||
SRC_S = crt0.s
|
||||
SRC_CC = _main.cc
|
||||
INC_DIR += $(BASE_DIR)/src/platform
|
||||
|
||||
vpath crt0.s $(REP_DIR)/src/platform/x86_64
|
||||
vpath _main.cc $(dir $(call select_from_repositories,src/platform/_main.cc))
|
||||
7
base-linux/lib/mk/x86_64/syscall.mk
Normal file
7
base-linux/lib/mk/x86_64/syscall.mk
Normal file
@@ -0,0 +1,7 @@
|
||||
REQUIRES = linux x86
|
||||
SRC_S += lx_clone.S lx_restore_rt.S lx_syscall.S
|
||||
|
||||
vpath lx_restore_rt.S $(REP_DIR)/../base-linux/src/platform/x86_64
|
||||
vpath lx_clone.S $(REP_DIR)/../base-linux/src/platform/x86_64
|
||||
vpath lx_syscall.S $(REP_DIR)/../base-linux/src/platform/x86_64
|
||||
|
||||
18
base-linux/mk/spec-linux.mk
Normal file
18
base-linux/mk/spec-linux.mk
Normal file
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# Specifics for the Linux-specific Genode components
|
||||
#
|
||||
|
||||
#
|
||||
# Startup code to be used when building a program and linker script that is
|
||||
# specific for Linux. We also reserve the thread-context area via a segment in
|
||||
# the program under Linux to prevent clashes with vdso.
|
||||
#
|
||||
ifneq ($(USE_HOST_LD_SCRIPT),yes)
|
||||
PRG_LIBS += startup
|
||||
LD_TEXT_ADDR ?= 0x01000000
|
||||
LD_SCRIPT_STATIC = $(call select_from_repositories,src/platform/genode.ld) \
|
||||
$(call select_from_repositories,src/platform/context_area.nostdlib.ld)
|
||||
else
|
||||
LD_SCRIPT_STATIC = $(LD_SCRIPT_DEFAULT) \
|
||||
$(call select_from_repositories,src/platform/context_area.stdlib.ld)
|
||||
endif
|
||||
21
base-linux/mk/spec-linux_x86_32.mk
Normal file
21
base-linux/mk/spec-linux_x86_32.mk
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
# Specifics for Linux on 32-bit x86
|
||||
#
|
||||
SPECS += linux x86_32
|
||||
|
||||
REP_INC_DIR += src/platform/x86_32
|
||||
|
||||
#
|
||||
# We need to manually add the default linker script on the command line in case
|
||||
# of standard library use. Otherwise, we were not able to extend it by the
|
||||
# context area section.
|
||||
#
|
||||
ifeq ($(USE_HOST_LD_SCRIPT),yes)
|
||||
LD_SCRIPT_DEFAULT = ldscripts/elf_i386.xc
|
||||
endif
|
||||
|
||||
#
|
||||
# Include less-specific configuration
|
||||
#
|
||||
include $(call select_from_repositories,mk/spec-x86_32.mk)
|
||||
include $(call select_from_repositories,mk/spec-linux.mk)
|
||||
22
base-linux/mk/spec-linux_x86_64.mk
Normal file
22
base-linux/mk/spec-linux_x86_64.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Specifics for Linux on 64-bit x86
|
||||
#
|
||||
SPECS += linux x86_64
|
||||
|
||||
REP_INC_DIR += src/platform/x86_64
|
||||
|
||||
#
|
||||
# We need to manually add the default linker script on the command line in case
|
||||
# of standard library use. Otherwise, we were not able to extend it by the
|
||||
# context area section.
|
||||
#
|
||||
ifeq ($(USE_HOST_LD_SCRIPT),yes)
|
||||
LD_SCRIPT_DEFAULT = ldscripts/elf_x86_64.xc
|
||||
endif
|
||||
|
||||
#
|
||||
# Include less-specific configuration
|
||||
#
|
||||
include $(call select_from_repositories,mk/spec-x86_64.mk)
|
||||
include $(call select_from_repositories,mk/spec-linux.mk)
|
||||
|
||||
43
base-linux/run/env
Normal file
43
base-linux/run/env
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# \brief Environment for executing Genode on Linux
|
||||
# \author Norman Feske
|
||||
# \date 2010-08-16
|
||||
#
|
||||
# For the documentation of the implemented API functions,
|
||||
# please refer to the comments in 'tool/run'.
|
||||
#
|
||||
|
||||
proc create_boot_directory { } {
|
||||
exec rm -rf [run_dir]
|
||||
exec mkdir -p [run_dir]
|
||||
}
|
||||
|
||||
|
||||
proc install_config {config} {
|
||||
set fh [open "[run_dir]/config" "WRONLY CREAT TRUNC"]
|
||||
puts $fh $config
|
||||
close $fh
|
||||
}
|
||||
|
||||
|
||||
proc build_boot_image {binaries} {
|
||||
foreach binary $binaries {
|
||||
exec ln -sf ../../../bin/$binary [run_dir] }
|
||||
}
|
||||
|
||||
|
||||
proc run_genode_until {{wait_for_re forever} {timeout_value 0}} {
|
||||
global output
|
||||
set timeout $timeout_value
|
||||
set orig_pwd [pwd]
|
||||
cd [run_dir]
|
||||
set pid [spawn ./core]
|
||||
if {$wait_for_re == "forever"} { interact $pid }
|
||||
expect {
|
||||
-re $wait_for_re { }
|
||||
timeout { puts stderr "Error: Test execution timed out"; exit -2 }
|
||||
}
|
||||
cd $orig_pwd
|
||||
set output $expect_out(buffer)
|
||||
}
|
||||
|
||||
77
base-linux/run/lx_hybrid_ctors.run
Normal file
77
base-linux/run/lx_hybrid_ctors.run
Normal file
@@ -0,0 +1,77 @@
|
||||
#
|
||||
# \brief Test if global static constructors in hybrid applications and
|
||||
# host shared libs get called
|
||||
# \author Christian Prochaska
|
||||
# \date 2011-11-24
|
||||
#
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
|
||||
build {
|
||||
core init
|
||||
test/lx_hybrid_ctors
|
||||
}
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Generate config
|
||||
#
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="LOG"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="test-lx_hybrid_ctors">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
|
||||
exec cp test/lx_hybrid_ctors/libtestlib.so bin/
|
||||
|
||||
# generic modules
|
||||
set boot_modules {
|
||||
core init
|
||||
test-lx_hybrid_ctors
|
||||
libtestlib.so
|
||||
}
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
#
|
||||
# Execute test case
|
||||
#
|
||||
|
||||
# qemu config
|
||||
append qemu_args "-nographic -m 64 "
|
||||
|
||||
run_genode_until "child exited with exit value 0.*\n" 10
|
||||
|
||||
#
|
||||
# Compare output
|
||||
#
|
||||
|
||||
grep_output {\[init -\> test-lx_hybrid_ctors\]}
|
||||
|
||||
compare_output_to {
|
||||
[init -> test-lx_hybrid_ctors] Global static constructor of host library called.
|
||||
[init -> test-lx_hybrid_ctors] Global static constructor of Genode application called
|
||||
[init -> test-lx_hybrid_ctors] --- lx_hybrid global static constructor test ---
|
||||
[init -> test-lx_hybrid_ctors] --- returning from main ---
|
||||
}
|
||||
|
||||
exec rm bin/libtestlib.so
|
||||
|
||||
# vi: set ft=tcl :
|
||||
60
base-linux/run/lx_hybrid_exception.run
Normal file
60
base-linux/run/lx_hybrid_exception.run
Normal file
@@ -0,0 +1,60 @@
|
||||
#
|
||||
# \brief Test if the exception mechanism works in hybrid applications
|
||||
# \author Christian Prochaska
|
||||
# \date 2011-11-22
|
||||
#
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
|
||||
build {
|
||||
core init
|
||||
test/lx_hybrid_exception
|
||||
}
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Generate config
|
||||
#
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="LOG"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="test-lx_hybrid_exception">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
|
||||
# generic modules
|
||||
set boot_modules {
|
||||
core init
|
||||
test-lx_hybrid_exception
|
||||
}
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
#
|
||||
# Execute test case
|
||||
#
|
||||
|
||||
# qemu config
|
||||
append qemu_args "-nographic -m 64 "
|
||||
|
||||
run_genode_until "child exited with exit value 0.*\n" 10
|
||||
|
||||
puts "Test succeeded"
|
||||
|
||||
# vi: set ft=tcl :
|
||||
31
base-linux/src/base/console/core_console.h
Normal file
31
base-linux/src/base/console/core_console.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* \brief Printf backend using Linux stdout
|
||||
* \author Norman Feske
|
||||
* \date 2006-04-08
|
||||
*
|
||||
* This console back-end should only be used by core.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/console.h>
|
||||
|
||||
/* Linux syscall bindings */
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Core_console : public Console
|
||||
{
|
||||
protected:
|
||||
|
||||
void _out_char(char c) { lx_write(1, &c, sizeof(c)); }
|
||||
};
|
||||
}
|
||||
|
||||
57
base-linux/src/base/env/debug.cc
vendored
Normal file
57
base-linux/src/base/env/debug.cc
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* \brief Linux-specific debug utilities
|
||||
* \author Norman Feske
|
||||
* \date 2009-05-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* With the enabled 'DEBUG' flag, status information can be printed directly
|
||||
* via a Linux system call by using the 'raw_write_str' function. This output
|
||||
* bypasses the Genode 'LOG' mechanism, which is useful for debugging low-level
|
||||
* code such as a libC back-end.
|
||||
*/
|
||||
#define DEBUG 1
|
||||
|
||||
|
||||
#if DEBUG
|
||||
#include <linux_syscalls.h>
|
||||
#endif /* DEBUG */
|
||||
|
||||
|
||||
/**
|
||||
* Write function targeting directly the Linux system call layer and bypassing
|
||||
* any Genode code.
|
||||
*/
|
||||
extern "C" int raw_write_str(const char *str)
|
||||
{
|
||||
#if DEBUG
|
||||
unsigned len = 0;
|
||||
for (; str[len] != 0; len++);
|
||||
lx_syscall(SYS_write, (int)1, str, len);
|
||||
return len;
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Debug function waiting until the user presses return
|
||||
*
|
||||
* This function is there to delay the execution of a back-end function such
|
||||
* that we have time to attack the GNU debugger to the running process. Once
|
||||
* attached, we can continue execution and use 'gdb' for debugging. In the
|
||||
* normal mode of operation, this function is never used.
|
||||
*/
|
||||
extern "C" void wait_for_continue(void)
|
||||
{
|
||||
#if DEBUG
|
||||
char buf[16];
|
||||
lx_syscall(SYS_read, (int)0, buf, sizeof(buf));
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
97
base-linux/src/base/env/platform_env.cc
vendored
Normal file
97
base-linux/src/base/env/platform_env.cc
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* \brief Support for the Linux-specific environment
|
||||
* \author Norman Feske
|
||||
* \date 2008-12-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008-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 <util/arg_string.h>
|
||||
#include <base/platform_env.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
/********************************
|
||||
** Platform_env::Local_parent **
|
||||
********************************/
|
||||
|
||||
Session_capability
|
||||
Platform_env::Local_parent::session(Service_name const &service_name,
|
||||
Session_args const &args)
|
||||
{
|
||||
if (strcmp(service_name.string(),
|
||||
Rm_session::service_name()) == 0)
|
||||
{
|
||||
size_t size =
|
||||
Arg_string::find_arg(args.string(),"size")
|
||||
.ulong_value(~0);
|
||||
|
||||
if (size == 0)
|
||||
return Parent_client::session(service_name, args);
|
||||
|
||||
Rm_session_mmap *rm = new (env()->heap())
|
||||
Rm_session_mmap(true, size);
|
||||
|
||||
return Local_interface::capability(rm);
|
||||
}
|
||||
|
||||
return Parent_client::session(service_name, args);
|
||||
}
|
||||
|
||||
|
||||
void Platform_env::Local_parent::close(Session_capability session)
|
||||
{
|
||||
/*
|
||||
* Handle non-local capabilities
|
||||
*/
|
||||
if (session.valid()) {
|
||||
Parent_client::close(session);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect capability to local RM session
|
||||
*/
|
||||
try {
|
||||
Capability<Rm_session_mmap> rm =
|
||||
static_cap_cast<Rm_session_mmap>(session);
|
||||
|
||||
destroy(env()->heap(), Local_interface::deref(rm));
|
||||
|
||||
} catch (Local_interface::Non_local_capability) { }
|
||||
}
|
||||
|
||||
|
||||
Platform_env::Local_parent::Local_parent(Parent_capability parent_cap)
|
||||
: Parent_client(parent_cap) { }
|
||||
|
||||
|
||||
/******************
|
||||
** Platform_env **
|
||||
******************/
|
||||
|
||||
/**
|
||||
* List of Unix environment variables, initialized by the startup code
|
||||
*/
|
||||
extern char **lx_environ;
|
||||
|
||||
|
||||
/**
|
||||
* Read environment variable as long value
|
||||
*/
|
||||
unsigned long Platform_env::_get_env_ulong(const char *key)
|
||||
{
|
||||
for (char **curr = lx_environ; curr && *curr; curr++) {
|
||||
|
||||
Arg arg = Arg_string::find_arg(*curr, key);
|
||||
if (arg.valid())
|
||||
return arg.ulong_value(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
283
base-linux/src/base/env/rm_session_mmap.cc
vendored
Normal file
283
base-linux/src/base/env/rm_session_mmap.cc
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* \brief Implementation of Linux-specific local region manager
|
||||
* \author Norman Feske
|
||||
* \date 2008-10-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008-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/platform_env.h>
|
||||
#include <base/thread.h>
|
||||
#include <linux_dataspace/client.h>
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
static size_t dataspace_size(Dataspace_capability ds)
|
||||
{
|
||||
if (ds.valid())
|
||||
return Dataspace_client(ds).size();
|
||||
|
||||
return Local_interface::deref(ds)->size();
|
||||
}
|
||||
|
||||
|
||||
static bool is_sub_rm_session(Dataspace_capability ds)
|
||||
{
|
||||
if (ds.valid())
|
||||
return false;
|
||||
|
||||
try {
|
||||
Local_interface::deref(ds); }
|
||||
catch (Local_interface::Non_local_capability) {
|
||||
return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void *map_local(Dataspace_capability ds, size_t size, addr_t offset,
|
||||
bool use_local_addr, addr_t local_addr)
|
||||
{
|
||||
Linux_dataspace::Filename fname = Linux_dataspace_client(ds).fname();
|
||||
fname.buf[sizeof(fname.buf) - 1] = 0;
|
||||
|
||||
bool writable = Dataspace_client(ds).writable();
|
||||
int fd = lx_open(fname.buf, (writable ? O_RDWR : O_RDONLY) | LX_O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
PERR("map_local: Could not open file \"%s\"", fname.buf);
|
||||
throw Rm_session::Invalid_dataspace();
|
||||
}
|
||||
|
||||
int flags = MAP_SHARED | (use_local_addr ? MAP_FIXED : 0);
|
||||
int prot = PROT_READ | PROT_EXEC | (writable ? PROT_WRITE : 0);
|
||||
void *addr = lx_mmap(use_local_addr ? (void*)local_addr : 0, size,
|
||||
prot, flags, fd, offset);
|
||||
|
||||
lx_close(fd);
|
||||
|
||||
if (((long)addr < 0) && ((long)addr > -4095)) {
|
||||
PERR("map_local: return value of mmap is %ld", (long)addr);
|
||||
throw Rm_session::Region_conflict();
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
void Platform_env::Rm_session_mmap::_add_to_rmap(Region const ®ion)
|
||||
{
|
||||
if (_rmap.add_region(region) < 0) {
|
||||
PERR("_add_to_rmap: could not add region to sub RM session");
|
||||
throw Region_conflict();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rm_session::Local_addr
|
||||
Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
|
||||
size_t size, off_t offset,
|
||||
bool use_local_addr,
|
||||
Rm_session::Local_addr local_addr)
|
||||
{
|
||||
Lock::Guard lock_guard(_lock);
|
||||
|
||||
/* only support attach_at for sub RM sessions */
|
||||
if (_sub_rm && !use_local_addr) {
|
||||
PERR("Rm_session_mmap::attach: attaching w/o local addr not supported\n");
|
||||
throw Out_of_metadata();
|
||||
}
|
||||
|
||||
if (offset < 0) {
|
||||
PERR("Rm_session_mmap::attach: negative offset not supported\n");
|
||||
throw Region_conflict();
|
||||
}
|
||||
|
||||
size_t const remaining_ds_size = dataspace_size(ds) > (addr_t)offset
|
||||
? dataspace_size(ds) - (addr_t)offset : 0;
|
||||
|
||||
/* determine size of virtual address region */
|
||||
size_t const region_size = size ? min(remaining_ds_size, size)
|
||||
: remaining_ds_size;
|
||||
if (region_size == 0)
|
||||
throw Region_conflict();
|
||||
|
||||
/*
|
||||
* We have to distinguish the following cases
|
||||
*
|
||||
* 1 we are a root RM session and ds is a plain dataspace
|
||||
* 2 we are a root RM session and ds is a sub RM session
|
||||
* 2.1 ds is already attached (base != 0)
|
||||
* 2.2 ds is not yet attached
|
||||
* 3 we are a sub RM session and ds is a plain dataspace
|
||||
* 3.1 we are attached to a root RM session
|
||||
* 3.2 we are not yet attached
|
||||
* 4 we are a sub RM session and ds is a sub RM session (not supported)
|
||||
*/
|
||||
|
||||
if (_sub_rm) {
|
||||
|
||||
/*
|
||||
* Case 4
|
||||
*/
|
||||
if (is_sub_rm_session(ds)) {
|
||||
PERR("Rm_session_mmap::attach: nesting sub RM sessions is not supported");
|
||||
throw Invalid_dataspace();
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for the dataspace to not exceed the boundaries of the
|
||||
* sub RM session
|
||||
*/
|
||||
if (region_size + (addr_t)local_addr > _size) {
|
||||
PERR("Rm_session_mmap::attach: dataspace does not fit in sub RM session");
|
||||
throw Region_conflict();
|
||||
}
|
||||
|
||||
_add_to_rmap(Region(local_addr, offset, ds, region_size));
|
||||
|
||||
/*
|
||||
* Case 3.1
|
||||
*
|
||||
* This RM session is a sub RM session. If the sub RM session is
|
||||
* attached (_base > 0), add its attachement offset to the local base
|
||||
* and map it.
|
||||
*/
|
||||
if (_is_attached())
|
||||
map_local(ds, region_size, offset, true, _base + (addr_t)local_addr);
|
||||
|
||||
return (void *)local_addr;
|
||||
|
||||
} else {
|
||||
|
||||
if (is_sub_rm_session(ds)) {
|
||||
|
||||
Dataspace *ds_if = Local_interface::deref<Dataspace>(ds);
|
||||
|
||||
Rm_session_mmap *rm = dynamic_cast<Rm_session_mmap *>(ds_if);
|
||||
|
||||
if (!rm)
|
||||
throw Invalid_dataspace();
|
||||
|
||||
/*
|
||||
* Case 2.1
|
||||
*
|
||||
* Detect if sub RM session is already attached
|
||||
*/
|
||||
if (rm->_base) {
|
||||
PERR("Rm_session_mmap::attach: mapping a sub RM session twice is not supported");
|
||||
throw Out_of_metadata();
|
||||
}
|
||||
|
||||
_add_to_rmap(Region(local_addr, offset, ds, region_size));
|
||||
|
||||
/*
|
||||
* Allocate local address range that can hold the entire sub RM
|
||||
* session.
|
||||
*/
|
||||
rm->_base = lx_vm_reserve(use_local_addr ? (addr_t)local_addr : 0,
|
||||
region_size);
|
||||
|
||||
/*
|
||||
* Cases 2.2, 3.2
|
||||
*
|
||||
* The sub rm session was not attached until now but it may have
|
||||
* been populated with dataspaces. Go through all regions an map
|
||||
* each of them.
|
||||
*/
|
||||
for (int i = 0; i < Region_map::MAX_REGIONS; i++) {
|
||||
Region region = rm->_rmap.region(i);
|
||||
if (!region.used())
|
||||
continue;
|
||||
|
||||
map_local(region.dataspace(), region.size(), region.offset(),
|
||||
true, rm->_base + region.start() + region.offset());
|
||||
}
|
||||
|
||||
return rm->_base;
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Case 1
|
||||
*
|
||||
* Boring, a plain dataspace is attached to a root RM session.
|
||||
*/
|
||||
void *addr = map_local(ds, region_size, offset, use_local_addr, local_addr);
|
||||
|
||||
_add_to_rmap(Region((addr_t)addr, offset, ds, region_size));
|
||||
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Platform_env::Rm_session_mmap::detach(Rm_session::Local_addr local_addr)
|
||||
{
|
||||
Lock::Guard lock_guard(_lock);
|
||||
|
||||
/*
|
||||
* Cases
|
||||
*
|
||||
* 1 we are root RM
|
||||
* 2 we are sub RM (region must be normal dataspace)
|
||||
* 2.1 we are not attached
|
||||
* 2.2 we are attached to a root RM
|
||||
*/
|
||||
|
||||
Region region = _rmap.lookup(local_addr);
|
||||
if (!region.used())
|
||||
return;
|
||||
|
||||
/*
|
||||
* Remove meta data from region map
|
||||
*/
|
||||
_rmap.remove_region(local_addr);
|
||||
|
||||
if (_sub_rm) {
|
||||
|
||||
/*
|
||||
* Case 2.1, 2.2
|
||||
*
|
||||
* By removing a region from an attached sub RM session we mark the
|
||||
* corresponding local address range as reserved. A plain 'munmap'
|
||||
* would mark this range as free to use for the root RM session, which
|
||||
* we need to prevent.
|
||||
*
|
||||
* If we are not attached, no local address-space manipulation is
|
||||
* needed.
|
||||
*/
|
||||
if (_is_attached())
|
||||
lx_vm_reserve((addr_t)local_addr + _base, region.size());
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Case 1
|
||||
*
|
||||
* We need no distiction between detaching normal dataspaces and
|
||||
* sub RM session. In both cases, we simply mark the local address
|
||||
* range as free.
|
||||
*/
|
||||
lx_munmap(local_addr, region.size());
|
||||
}
|
||||
|
||||
/*
|
||||
* If the detached dataspace is sub RM session, mark it as detached
|
||||
*/
|
||||
if (is_sub_rm_session(region.dataspace())) {
|
||||
|
||||
Dataspace *ds_if = Local_interface::deref<Dataspace>(region.dataspace());
|
||||
Rm_session_mmap *rm = dynamic_cast<Rm_session_mmap *>(ds_if);
|
||||
if (rm)
|
||||
rm->_base = 0;
|
||||
}
|
||||
|
||||
}
|
||||
358
base-linux/src/base/ipc/ipc.cc
Normal file
358
base-linux/src/base/ipc/ipc.cc
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* \brief Socket-based IPC implementation for Linux
|
||||
* \author Norman Feske
|
||||
* \author Christian Helmuth
|
||||
* \date 2011-10-11
|
||||
*
|
||||
* We create two sockets under lx_rpath() for each thread: client and server
|
||||
* role. The naming is 'ep-<thread id>-<role>'. The socket descriptors are
|
||||
* cached in Thread_base::_tid.
|
||||
*
|
||||
* Currently two socket files are needed, as the client does not send the reply
|
||||
* socket access-rights in a combined message with the payload. In the future,
|
||||
* only server sockets must be bound in lx_rpath().
|
||||
*
|
||||
* The current request message layout is:
|
||||
*
|
||||
* long server_local_name;
|
||||
* long client_thread_id;
|
||||
* int opcode;
|
||||
* ...payload...
|
||||
*
|
||||
* Response messages look like this:
|
||||
*
|
||||
* long scratch_word;
|
||||
* int exc_code;
|
||||
* ...payload...
|
||||
*
|
||||
* All fields are naturally aligned, i.e., aligend on 4 or 8 byte boundaries on
|
||||
* 32-bit resp. 64-bit systems.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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.h>
|
||||
#include <base/thread.h>
|
||||
#include <base/blocking.h>
|
||||
#include <base/snprintf.h>
|
||||
|
||||
/* Linux includes */
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <linux_syscalls.h>
|
||||
#include <linux_rpath.h>
|
||||
|
||||
|
||||
extern "C" void wait_for_continue(void);
|
||||
extern "C" int raw_write_str(const char *str);
|
||||
|
||||
#define PRAW(fmt, ...) \
|
||||
do { \
|
||||
char str[128]; \
|
||||
snprintf(str, sizeof(str), \
|
||||
ESC_ERR fmt ESC_END "\n", ##__VA_ARGS__); \
|
||||
raw_write_str(str); \
|
||||
} while (0)
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/**
|
||||
* Utility: Create socket address for thread ID and role (client/server)
|
||||
*/
|
||||
static void lx_create_sockaddr(sockaddr_un *addr, long thread_id, char const *role)
|
||||
{
|
||||
addr->sun_family = AF_UNIX;
|
||||
Genode::snprintf(addr->sun_path, sizeof(addr->sun_path), "%s/ep-%ld-%s",
|
||||
lx_rpath(), thread_id, role);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility: Create a socket descriptor and file for given thread and role
|
||||
*/
|
||||
static int create_socket(long thread_id, char const *role)
|
||||
{
|
||||
int sd = lx_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
if (sd < 0) return -1;
|
||||
|
||||
sockaddr_un addr;
|
||||
lx_create_sockaddr(&addr, thread_id, role);
|
||||
|
||||
/* make sure bind succeeds */
|
||||
lx_unlink(addr.sun_path);
|
||||
|
||||
if (lx_bind(sd, (sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
return -2;
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility: Unlink socket file and close descriptor
|
||||
*
|
||||
* XXX Currently, socket destruction is missing. The client socket could be
|
||||
* used from multiple Ipc_client objects. A safe destruction would need
|
||||
* reference counting.
|
||||
*/
|
||||
//static void destroy_socket(int sd, long thread_id, char const *role)
|
||||
//{
|
||||
// sockaddr_un addr;
|
||||
// lx_create_sockaddr(&addr, thread_id, role);
|
||||
//
|
||||
// lx_unlink(addr.sun_path);
|
||||
// lx_close(sd);
|
||||
//}
|
||||
|
||||
|
||||
/**
|
||||
* Get client-socket descriptor for main thread
|
||||
*/
|
||||
static int main_client_socket()
|
||||
{
|
||||
static int sd = create_socket(lx_gettid(), "client");
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility: Get server socket for given thread
|
||||
*/
|
||||
static int server_socket(Thread_base *thread)
|
||||
{
|
||||
/*
|
||||
* Main thread uses Ipc_server for sleep_forever() only.
|
||||
*/
|
||||
if (!thread)
|
||||
return lx_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
|
||||
if (thread->tid().server == -1)
|
||||
thread->tid().server = create_socket(thread->tid().tid, "server");
|
||||
return thread->tid().server;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility: Get client socket for given thread
|
||||
*/
|
||||
static int client_socket(Thread_base *thread)
|
||||
{
|
||||
if (!thread) return main_client_socket();
|
||||
|
||||
if (thread->tid().client == -1)
|
||||
thread->tid().client = create_socket(thread->tid().tid, "client");
|
||||
return thread->tid().client;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility: Send message to thread via given socket descriptor
|
||||
*/
|
||||
static void send_to(int sd, long thread_id, char const *target_role,
|
||||
void *msg, Genode::size_t msg_len)
|
||||
{
|
||||
sockaddr_un addr;
|
||||
lx_create_sockaddr(&addr, thread_id, target_role);
|
||||
|
||||
int res = lx_sendto(sd, msg, msg_len, 0, (sockaddr *)&addr, sizeof(addr));
|
||||
if (res < 0) {
|
||||
PRAW("Send error: %d with %s in %d", res, addr.sun_path, lx_gettid());
|
||||
wait_for_continue();
|
||||
throw Ipc_error();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility: Receive message via given socket descriptor
|
||||
*/
|
||||
static void recv_from(int sd, void *buf, Genode::size_t buf_len)
|
||||
{
|
||||
socklen_t fromlen;
|
||||
int res = lx_recvfrom(sd, buf, buf_len, 0, 0, &fromlen);
|
||||
if (res < 0) {
|
||||
if ((-res) == EINTR)
|
||||
throw Blocking_canceled();
|
||||
else {
|
||||
PRAW("Recv error: %d in %d", res, lx_gettid());
|
||||
wait_for_continue();
|
||||
throw Ipc_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_ostream **
|
||||
*****************/
|
||||
|
||||
/*
|
||||
* XXX This class will be removed soon.
|
||||
*/
|
||||
|
||||
void Ipc_ostream::_prepare_next_send()
|
||||
{
|
||||
PRAW("unexpected call to %s (%p)", __PRETTY_FUNCTION__, this);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_ostream::_send()
|
||||
{
|
||||
PRAW("unexpected call to %s (%p)", __PRETTY_FUNCTION__, this);
|
||||
}
|
||||
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg):
|
||||
Ipc_marshaller(snd_msg->buf, snd_msg->size()), _snd_msg(snd_msg), _dst(dst)
|
||||
{ }
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_istream **
|
||||
*****************/
|
||||
|
||||
/*
|
||||
* XXX This class will be removed soon.
|
||||
*/
|
||||
|
||||
void Ipc_istream::_prepare_next_receive()
|
||||
{
|
||||
PRAW("unexpected call to %s (%p)", __PRETTY_FUNCTION__, this);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_istream::_wait()
|
||||
{
|
||||
PRAW("unexpected call to %s (%p)", __PRETTY_FUNCTION__, this);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
|
||||
: Ipc_unmarshaller(rcv_msg->buf, rcv_msg->size()),
|
||||
Native_capability(lx_gettid(), 0),
|
||||
_rcv_msg(rcv_msg), _rcv_cs(-1)
|
||||
{ }
|
||||
|
||||
|
||||
Ipc_istream::~Ipc_istream() { }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_client **
|
||||
****************/
|
||||
|
||||
void Ipc_client::_prepare_next_call()
|
||||
{
|
||||
/* prepare next request in buffer */
|
||||
long local_name = _dst.local_name();
|
||||
long tid = Native_capability::tid();
|
||||
|
||||
_write_offset = 0;
|
||||
_write_to_buf(local_name);
|
||||
_write_to_buf(tid);
|
||||
|
||||
/* prepare response buffer */
|
||||
_read_offset = sizeof(long);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_client::_call()
|
||||
{
|
||||
if (_dst.valid()) {
|
||||
send_to(_rcv_cs, _dst.tid(), "server",
|
||||
_snd_msg->buf, _write_offset);
|
||||
|
||||
recv_from(_rcv_cs, _rcv_msg->buf, _rcv_msg->size());
|
||||
}
|
||||
_prepare_next_call();
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
_rcv_cs = client_socket(Thread_base::myself());
|
||||
|
||||
_prepare_next_call();
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_server **
|
||||
****************/
|
||||
|
||||
void Ipc_server::_prepare_next_reply_wait()
|
||||
{
|
||||
/* skip server-local name */
|
||||
_read_offset = sizeof(long);
|
||||
|
||||
/* read client thread id from request buffer */
|
||||
long tid;
|
||||
if (_reply_needed) {
|
||||
_read_from_buf(tid);
|
||||
_dst = Native_capability(tid, 0); /* only _tid member is used */
|
||||
}
|
||||
|
||||
/* prepare next reply */
|
||||
_write_offset = 0;
|
||||
long local_name = _dst.local_name();
|
||||
_write_to_buf(local_name); /* XXX unused, needed by de/marshaller */
|
||||
|
||||
/* leave space for exc code at the beginning of the msgbuf */
|
||||
_write_offset += align_natural(sizeof(int));
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_wait()
|
||||
{
|
||||
/* wait for new server request */
|
||||
try {
|
||||
recv_from(_rcv_cs, _rcv_msg->buf, _rcv_msg->size());
|
||||
} catch (Blocking_canceled) { }
|
||||
|
||||
/* now we have a request to reply, determine reply destination */
|
||||
_reply_needed = true;
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply()
|
||||
{
|
||||
try {
|
||||
send_to(_rcv_cs, _dst.tid(), "client", _snd_msg->buf, _write_offset);
|
||||
} catch (Ipc_error) { }
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait()
|
||||
{
|
||||
/* when first called, there was no request yet */
|
||||
if (_reply_needed)
|
||||
send_to(_rcv_cs, _dst.tid(), "client", _snd_msg->buf, _write_offset);
|
||||
|
||||
_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)
|
||||
{
|
||||
_rcv_cs = server_socket(Thread_base::myself());
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
80
base-linux/src/base/lock/lock_helper.h
Normal file
80
base-linux/src/base/lock/lock_helper.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* \brief Linux-specific helper functions for the Lock implementation
|
||||
* \author Norman Feske
|
||||
* \date 2009-07-20
|
||||
*
|
||||
* This file serves as adapter between the generic lock implementation
|
||||
* in 'lock.cc' and the underlying kernel.
|
||||
*
|
||||
* For documentation about the interface, please revisit the 'base-pistachio'
|
||||
* implementation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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/native_types.h>
|
||||
#include <base/thread.h>
|
||||
|
||||
/* Linux includes */
|
||||
#include <linux_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; }
|
||||
|
||||
|
||||
static inline void thread_yield()
|
||||
{
|
||||
struct timespec ts = { 0, 1000 };
|
||||
lx_nanosleep(&ts, 0);
|
||||
}
|
||||
|
||||
|
||||
static bool thread_check_stopped_and_restart(Genode::Native_thread_id tid)
|
||||
{
|
||||
lx_tgkill(tid.pid, tid.tid, LX_SIGUSR1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static inline Genode::Native_thread_id thread_get_my_native_id()
|
||||
{
|
||||
return Genode::Native_thread_id(lx_gettid(), lx_getpid());
|
||||
}
|
||||
|
||||
|
||||
static inline Genode::Native_thread_id thread_invalid_id()
|
||||
{
|
||||
return Genode::Native_thread_id();
|
||||
}
|
||||
|
||||
|
||||
static inline bool thread_id_valid(Genode::Native_thread_id tid)
|
||||
{
|
||||
return (tid.pid != 0);
|
||||
}
|
||||
|
||||
|
||||
static inline void thread_switch_to(Genode::Native_thread_id tid)
|
||||
{
|
||||
thread_yield();
|
||||
}
|
||||
|
||||
|
||||
static inline void thread_stop_myself()
|
||||
{
|
||||
struct timespec ts = { 1000, 0 };
|
||||
while (lx_nanosleep(&ts, 0) == 0);
|
||||
}
|
||||
203
base-linux/src/base/process/process.cc
Normal file
203
base-linux/src/base/process/process.cc
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* \brief Implementation of process creation for Linux
|
||||
* \author Norman Feske
|
||||
* \date 2006-07-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/elf.h>
|
||||
#include <base/env.h>
|
||||
#include <base/process.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/snprintf.h>
|
||||
#include <linux_dataspace/client.h>
|
||||
|
||||
/* Framework-internal includes */
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
Dataspace_capability Process::_dynamic_linker_cap;
|
||||
|
||||
/**
|
||||
* Argument frame for passing 'execve' paremeters through 'clone'
|
||||
*/
|
||||
struct execve_args {
|
||||
const char *filename;
|
||||
char *const*argv;
|
||||
char *const*envp;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Startup code of the new child process
|
||||
*/
|
||||
static int _exec_child(struct execve_args *arg)
|
||||
{
|
||||
return lx_execve(arg->filename, arg->argv, arg->envp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List of Unix environment variables, initialized by the startup code
|
||||
*/
|
||||
extern char **lx_environ;
|
||||
|
||||
|
||||
/**
|
||||
* Read environment variable as string
|
||||
*
|
||||
* If no matching key exists, return an empty string.
|
||||
*/
|
||||
static const char *get_env(const char *key)
|
||||
{
|
||||
Genode::size_t key_len = strlen(key);
|
||||
for (char **curr = lx_environ; curr && *curr; curr++)
|
||||
if ((Genode::strcmp(*curr, key, key_len) == 0) && (*curr)[key_len] == '=')
|
||||
return (const char *)(*curr + key_len + 1);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for dynamic ELF header
|
||||
*/
|
||||
static bool _check_dynamic_elf(Dataspace_capability elf_ds_cap)
|
||||
{
|
||||
/* attach ELF locally */
|
||||
addr_t elf_addr;
|
||||
|
||||
try { elf_addr = env()->rm_session()->attach(elf_ds_cap); }
|
||||
catch (...) { return false; }
|
||||
|
||||
/*
|
||||
* If attach is called within core, it will return zero because
|
||||
* Linux uses Core_rm_session.
|
||||
*/
|
||||
if (!elf_addr) return false;
|
||||
|
||||
/* read program header and interpreter */
|
||||
Elf_binary elf((addr_t)elf_addr);
|
||||
env()->rm_session()->detach((void *)elf_addr);
|
||||
|
||||
return elf.is_dynamically_linked();
|
||||
}
|
||||
|
||||
|
||||
const char *Process::_priv_pd_args(Parent_capability parent_cap,
|
||||
Dataspace_capability elf_data_ds_cap,
|
||||
const char *name, char *const argv[])
|
||||
{
|
||||
/*
|
||||
* Serialize calls of this function because it uses the static 'envbuf' and
|
||||
* 'stack' variables.
|
||||
*/
|
||||
static Lock _priv_pd_args_lock;
|
||||
Lock::Guard _lock_guard(_priv_pd_args_lock);
|
||||
|
||||
/* check for dynamic program header */
|
||||
if (_check_dynamic_elf(elf_data_ds_cap)) {
|
||||
if (!_dynamic_linker_cap.valid()) {
|
||||
PERR("Dynamically linked file found, but no dynamic linker binary present");
|
||||
return 0;
|
||||
}
|
||||
elf_data_ds_cap = _dynamic_linker_cap;
|
||||
}
|
||||
|
||||
/* pass parent capability as environment variable to the child */
|
||||
enum { ENV_STR_LEN = 256 };
|
||||
static char envbuf[5][ENV_STR_LEN];
|
||||
Genode::snprintf(envbuf[0], ENV_STR_LEN, "parent_tid=%ld",
|
||||
parent_cap.tid());
|
||||
Genode::snprintf(envbuf[1], ENV_STR_LEN, "parent_local_name=%lu",
|
||||
parent_cap.local_name());
|
||||
Genode::snprintf(envbuf[2], ENV_STR_LEN, "DISPLAY=%s",
|
||||
get_env("DISPLAY"));
|
||||
Genode::snprintf(envbuf[3], ENV_STR_LEN, "HOME=%s",
|
||||
get_env("HOME"));
|
||||
Genode::snprintf(envbuf[4], ENV_STR_LEN, "LD_LIBRARY_PATH=%s",
|
||||
get_env("LD_LIBRARY_PATH"));
|
||||
|
||||
char *env[] = { &envbuf[0][0], &envbuf[1][0], &envbuf[2][0],
|
||||
&envbuf[3][0], &envbuf[4][0], 0 };
|
||||
|
||||
/* determine name of binary to start */
|
||||
Linux_dataspace_client elf_data_ds(elf_data_ds_cap);
|
||||
Linux_dataspace::Filename fname = elf_data_ds.fname();
|
||||
fname.buf[sizeof(fname.buf) - 1] = 0;
|
||||
|
||||
/* prefix name of Linux program (helps killing some zombies) */
|
||||
char pname_buf[9 + Linux_dataspace::FNAME_LEN];
|
||||
snprintf(pname_buf, sizeof(pname_buf), "[Genode] %s", name);
|
||||
|
||||
/* it may happen, that argv is null */
|
||||
char *argv_buf[2];
|
||||
if (!argv) {
|
||||
argv_buf[0] = pname_buf;
|
||||
argv_buf[1] = 0;
|
||||
argv = argv_buf;
|
||||
} else
|
||||
((char **)argv)[0] = pname_buf;
|
||||
|
||||
/*
|
||||
* We cannot create the new process via 'fork()' because all our used
|
||||
* memory including stack memory is backed by dataspaces, which had been
|
||||
* mapped with the 'MAP_SHARED' flag. Therefore, after being created, the
|
||||
* new process starts using the stack with the same physical memory pages
|
||||
* as used by parent process. This would ultimately lead to stack
|
||||
* corruption. To prevent both processes from concurrently accessing the
|
||||
* same stack, we pause the execution of the parent until the child calls
|
||||
* 'execve'. From then on, the child has its private memory layout. The
|
||||
* desired behaviour is normally provided by 'vfork' but we use the more
|
||||
* modern 'clone' call for this purpose.
|
||||
*/
|
||||
enum { STACK_SIZE = 4096 };
|
||||
static char stack[STACK_SIZE]; /* initial stack used by the child until
|
||||
calling 'execve' */
|
||||
|
||||
/*
|
||||
* Argument frame as passed to 'clone'. Because, we can only pass a single
|
||||
* pointer, all arguments are embedded within the 'execve_args' struct.
|
||||
*/
|
||||
struct execve_args arg = {
|
||||
fname.buf,
|
||||
argv,
|
||||
env
|
||||
};
|
||||
|
||||
pid_t pid = lx_create_process((int (*)(void *))_exec_child,
|
||||
stack + STACK_SIZE - sizeof(umword_t), &arg);
|
||||
|
||||
/*
|
||||
* We create a pseudo pd session with the new pd's pid as argument
|
||||
* to enable Core to kill the process when the pd session gets closed.
|
||||
*/
|
||||
snprintf(_priv_pd_argbuf, sizeof(_priv_pd_argbuf), "PID=%d", pid);
|
||||
|
||||
return _priv_pd_argbuf;
|
||||
}
|
||||
|
||||
|
||||
Process::Process(Dataspace_capability elf_data_ds_cap,
|
||||
Ram_session_capability ram_session_cap,
|
||||
Cpu_session_capability cpu_session_cap,
|
||||
Rm_session_capability rm_session_cap,
|
||||
Parent_capability parent_cap,
|
||||
const char *name,
|
||||
char *const argv[])
|
||||
:
|
||||
_pd(_priv_pd_args(parent_cap, elf_data_ds_cap, name, argv)),
|
||||
_cpu_session_client(Cpu_session_capability()),
|
||||
_rm_session_client(Rm_session_capability())
|
||||
{ }
|
||||
|
||||
|
||||
Process::~Process() { }
|
||||
115
base-linux/src/base/thread/thread_linux.cc
Normal file
115
base-linux/src/base/thread/thread_linux.cc
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* \brief Implementation of the Thread API via Linux threads
|
||||
* \author Norman Feske
|
||||
* \date 2006-06-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <base/thread.h>
|
||||
#include <base/snprintf.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* Linux syscall bindings */
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
static void empty_signal_handler(int) { }
|
||||
|
||||
|
||||
/**
|
||||
* Signal handler for killing the thread
|
||||
*/
|
||||
static void thread_exit_signal_handler(int) { lx_exit(0); }
|
||||
|
||||
|
||||
static void thread_start(void *)
|
||||
{
|
||||
/*
|
||||
* Set signal handler such that canceled system calls get not
|
||||
* transparently retried after a signal gets received.
|
||||
*/
|
||||
lx_sigaction(LX_SIGUSR1, empty_signal_handler);
|
||||
|
||||
Thread_base::myself()->entry();
|
||||
sleep_forever();
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::_init_platform_thread() { }
|
||||
|
||||
|
||||
void Thread_base::_deinit_platform_thread()
|
||||
{
|
||||
/*
|
||||
* Kill thread until it is really really dead
|
||||
*
|
||||
* We use the 'tgkill' system call to kill the thread. This system call
|
||||
* returns immediately and just flags the corresponding signal at the
|
||||
* targeted thread context. However, the thread still lives until the
|
||||
* signal flags are evaluated. When leaving this function, however, we want
|
||||
* to be sure that the thread is no more executing any code such that we
|
||||
* an safely free and unmap the thread's stack. So we call 'tgkill' in a
|
||||
* loop until we get an error indicating that the thread does not exists
|
||||
* anymore.
|
||||
*/
|
||||
for (;;) {
|
||||
|
||||
/* destroy thread locally */
|
||||
int ret = lx_tgkill(_tid.pid, _tid.tid, LX_SIGCANCEL);
|
||||
|
||||
if (ret < 0) break;
|
||||
|
||||
/* if thread still exists, wait a bit and try to kill it again */
|
||||
struct timespec ts = { 0, 500 };
|
||||
lx_nanosleep(&ts, 0);
|
||||
}
|
||||
|
||||
/* inform core about the killed thread */
|
||||
env()->cpu_session()->kill_thread(_thread_cap);
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::start()
|
||||
{
|
||||
/*
|
||||
* The first time we enter this code path, the 'start' function is
|
||||
* called by the main thread as there cannot exist other threads
|
||||
* without executing this function. When first called, we initialize
|
||||
* the thread lib here.
|
||||
*/
|
||||
static bool threadlib_initialized = false;
|
||||
if (!threadlib_initialized) {
|
||||
lx_sigaction(LX_SIGCANCEL, thread_exit_signal_handler);
|
||||
threadlib_initialized = true;
|
||||
}
|
||||
|
||||
/* align initial stack to 16 byte boundary */
|
||||
void *thread_sp = (void *)((addr_t)(_context->stack) & ~0xf);
|
||||
_tid.tid = lx_create_thread(thread_start, thread_sp, this);
|
||||
_tid.pid = lx_getpid();
|
||||
|
||||
/*
|
||||
* Inform core about the new thread by calling create_thread and encoding
|
||||
* the thread's PID in the thread-name argument.
|
||||
*/
|
||||
char name_and_pid[Cpu_session::THREAD_NAME_LEN + 2*16];
|
||||
snprintf(name_and_pid, sizeof(name_and_pid), "%s:0x%x:0x%x",
|
||||
_context->name, _tid.tid, _tid.pid);
|
||||
_thread_cap = env()->cpu_session()->create_thread(name_and_pid);
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::cancel_blocking()
|
||||
{
|
||||
env()->cpu_session()->cancel_blocking(_thread_cap);
|
||||
}
|
||||
112
base-linux/src/core/context_area.cc
Normal file
112
base-linux/src/core/context_area.cc
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* \brief Linux-specific support code for the thread API
|
||||
* \author Norman Feske
|
||||
* \date 2010-01-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <rm_session/rm_session.h>
|
||||
#include <ram_session/ram_session.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/thread.h>
|
||||
|
||||
/* Linux includes */
|
||||
#include <linux_syscalls.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
/**
|
||||
* Region-manager session for allocating thread contexts
|
||||
*
|
||||
* This class corresponds to the managed dataspace that is normally
|
||||
* used for organizing thread contexts with the thread context area.
|
||||
* It "emulates" the sub address space by adjusting the local address
|
||||
* argument to 'attach' with the offset of the thread context area.
|
||||
*/
|
||||
class Context_area_rm_session : public Genode::Rm_session
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Attach backing store to thread-context area
|
||||
*/
|
||||
Local_addr attach(Genode::Dataspace_capability ds_cap,
|
||||
Genode::size_t size, Genode::off_t offset,
|
||||
bool use_local_addr, Local_addr local_addr)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* convert context-area-relative to absolute virtual address */
|
||||
addr_t addr = local_addr;
|
||||
addr += Thread_base::CONTEXT_AREA_VIRTUAL_BASE;
|
||||
|
||||
/* use anonymous mmap for allocating stack backing store */
|
||||
int flags = MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE;
|
||||
int prot = PROT_READ | PROT_WRITE;
|
||||
void *res = lx_mmap((void*)addr, size, prot, flags, -1, 0);
|
||||
|
||||
if ((addr_t)res != addr)
|
||||
throw Region_conflict();
|
||||
|
||||
return local_addr;
|
||||
}
|
||||
|
||||
void detach(Local_addr local_addr) {
|
||||
PWRN("context area detach from 0x%p - not implemented", (void *)local_addr); }
|
||||
|
||||
Genode::Pager_capability add_client(Genode::Thread_capability) {
|
||||
return Genode::Pager_capability(); }
|
||||
|
||||
void fault_handler(Genode::Signal_context_capability) { }
|
||||
|
||||
State state() { return State(); }
|
||||
|
||||
Genode::Dataspace_capability dataspace() {
|
||||
return Genode::Dataspace_capability(); }
|
||||
};
|
||||
|
||||
|
||||
class Context_area_ram_session : public Genode::Ram_session
|
||||
{
|
||||
public:
|
||||
|
||||
Genode::Ram_dataspace_capability alloc(Genode::size_t size) {
|
||||
return Genode::Ram_dataspace_capability(); }
|
||||
|
||||
void free(Genode::Ram_dataspace_capability) { }
|
||||
|
||||
int ref_account(Genode::Ram_session_capability) { return 0; }
|
||||
|
||||
int transfer_quota(Genode::Ram_session_capability, Genode::size_t) { return 0; }
|
||||
|
||||
size_t quota() { return 0; }
|
||||
|
||||
size_t used() { return 0; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return single instance of the context-area RM and RAM session
|
||||
*/
|
||||
namespace Genode {
|
||||
|
||||
Rm_session *env_context_area_rm_session()
|
||||
{
|
||||
static Context_area_rm_session inst;
|
||||
return &inst;
|
||||
}
|
||||
|
||||
Ram_session *env_context_area_ram_session()
|
||||
{
|
||||
static Context_area_ram_session inst;
|
||||
return &inst;
|
||||
}
|
||||
}
|
||||
|
||||
47
base-linux/src/core/include/cap_session_component.h
Normal file
47
base-linux/src/core/include/cap_session_component.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* \brief Capability allocation service
|
||||
* \author Norman Feske
|
||||
* \date 2006-06-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__LINUX__CAP_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__LINUX__CAP_SESSION_COMPONENT_H_
|
||||
|
||||
#include <cap_session/cap_session.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/lock.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Cap_session_component : public Rpc_object<Cap_session>
|
||||
{
|
||||
private:
|
||||
|
||||
static long _unique_id_cnt;
|
||||
static Lock &_lock()
|
||||
{
|
||||
static Lock static_lock;
|
||||
return static_lock;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Native_capability alloc(Native_capability ep)
|
||||
{
|
||||
Lock::Guard lock_guard(_lock());
|
||||
|
||||
return Native_capability(ep.tid(), ++_unique_id_cnt);
|
||||
}
|
||||
|
||||
void free(Native_capability cap) { }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__LINUX__CAP_SESSION_COMPONENT_H_ */
|
||||
91
base-linux/src/core/include/dataspace_component.h
Normal file
91
base-linux/src/core/include/dataspace_component.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* \brief Core-internal dataspace representation on Linux
|
||||
* \author Norman Feske
|
||||
* \date 2006-05-19
|
||||
*
|
||||
* On Linux userland, we do not deal with physical memory. Instead,
|
||||
* we create a file for each dataspace that is to be mmapped.
|
||||
* Therefore, the allocator is not really used for allocating
|
||||
* memory but only as a container for quota.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__LINUX__DATASPACE_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__LINUX__DATASPACE_COMPONENT_H_
|
||||
|
||||
#include <linux_dataspace/linux_dataspace.h>
|
||||
#include <util/string.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Dataspace_component : public Rpc_object<Linux_dataspace>
|
||||
{
|
||||
private:
|
||||
|
||||
size_t _size; /* size of dataspace in bytes */
|
||||
addr_t _addr; /* meaningless on linux */
|
||||
Filename _fname; /* filename for mmap */
|
||||
bool _writable; /* false if read-only */
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Dataspace_component(size_t size, addr_t addr, bool writable)
|
||||
: _size(size), _addr(addr), _writable(writable) { }
|
||||
|
||||
/**
|
||||
* Default constructor returns invalid dataspace
|
||||
*/
|
||||
Dataspace_component() : _size(0), _addr(0), _writable(false) { }
|
||||
|
||||
/**
|
||||
* This constructor is only provided for compatibility
|
||||
* reasons and should not be used.
|
||||
*/
|
||||
Dataspace_component(size_t size, addr_t core_local_addr,
|
||||
addr_t phys_addr, bool write_combined,
|
||||
bool writable)
|
||||
: _size(size), _addr(phys_addr)
|
||||
{
|
||||
PWRN("Should only be used for IOMEM and not within Linux.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Define/request corresponding filename of dataspace
|
||||
*
|
||||
* To use dataspaces as shared memory objects on Linux, we have to
|
||||
* assign a file to each dataspace. This way, multiple Linux process
|
||||
* can mmap this file.
|
||||
*/
|
||||
void fname(const char *fname) { strncpy(_fname.buf, fname, sizeof(_fname.buf)); }
|
||||
|
||||
|
||||
/*************************
|
||||
** Dataspace interface **
|
||||
*************************/
|
||||
|
||||
size_t size() { return _size; }
|
||||
addr_t phys_addr() { return _addr; }
|
||||
bool writable() { return _writable; }
|
||||
|
||||
|
||||
/****************************************
|
||||
** Linux-specific dataspace interface **
|
||||
****************************************/
|
||||
|
||||
Filename fname() { return _fname; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__LINUX__DATASPACE_COMPONENT_H_ */
|
||||
64
base-linux/src/core/include/io_mem_session_component.h
Normal file
64
base-linux/src/core/include/io_mem_session_component.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the IO_MEM session interface (Linux)
|
||||
* \author Christian Helmuth
|
||||
* \date 2007-09-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__LINUX__IO_MEM_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__LINUX__IO_MEM_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <io_mem_session/io_mem_session.h>
|
||||
|
||||
/* core includes */
|
||||
#include <dataspace_component.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Io_mem_session_component : public Rpc_object<Io_mem_session>
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param io_mem_alloc MMIO region allocator
|
||||
* \param ram_alloc RAM allocator that will be checked for
|
||||
* region collisions
|
||||
* \param ds_ep entry point to manage the dataspace
|
||||
* corresponding the io_mem session
|
||||
* \param args session construction arguments, in
|
||||
* particular MMIO region base, size and
|
||||
* caching demands
|
||||
*/
|
||||
Io_mem_session_component(Range_allocator *io_mem_alloc,
|
||||
Range_allocator *ram_alloc,
|
||||
Rpc_entrypoint *ds_ep,
|
||||
const char *args);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Io_mem_session_component() { }
|
||||
|
||||
|
||||
/*****************************
|
||||
** Io-mem session interface **
|
||||
*****************************/
|
||||
|
||||
Io_mem_dataspace_capability dataspace() {
|
||||
return Io_mem_dataspace_capability(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__LINUX__IO_MEM_SESSION_COMPONENT_H_ */
|
||||
60
base-linux/src/core/include/irq_session_component.h
Normal file
60
base-linux/src/core/include/irq_session_component.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the IRQ session interface for Linux
|
||||
* \author Christian Helmuth
|
||||
* \date 2007-09-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__LINUX__IRQ_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__LINUX__IRQ_SESSION_COMPONENT_H_
|
||||
|
||||
#include <util/list.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <irq_session/irq_session.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Irq_session_component : public List<Irq_session_component>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param cap_session capability session to use
|
||||
* \param irq_alloc platform-dependent IRQ allocator
|
||||
* \param args session construction arguments
|
||||
*/
|
||||
Irq_session_component(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
const char *args) { }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Irq_session_component() { }
|
||||
|
||||
/**
|
||||
* Return capability to this session
|
||||
*
|
||||
* Capability is always invalid under Linux.
|
||||
*/
|
||||
Session_capability cap() const { return Session_capability(); }
|
||||
|
||||
|
||||
/***************************
|
||||
** Irq session interface **
|
||||
***************************/
|
||||
|
||||
void wait_for_irq() { }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__LINUX__IRQ_SESSION_COMPONENT_H_ */
|
||||
61
base-linux/src/core/include/pd_session_component.h
Normal file
61
base-linux/src/core/include/pd_session_component.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* \brief CORE-specific instance of the PD session interface for Linux
|
||||
* \author Norman Feske
|
||||
* \date 2006-08-14
|
||||
*
|
||||
* On Linux, we use a pd session only for keeping the information about the
|
||||
* existence of protection domains to enable us to destruct all pds of a whole
|
||||
* subtree. A pd is killed by CORE when closing the corresponding pd session.
|
||||
* The PID of the process is passed to CORE as an argument of the session
|
||||
* construction.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__LINUX__PD_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__LINUX__PD_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/arg_string.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <pd_session/pd_session.h>
|
||||
|
||||
/* local includes */
|
||||
#include "platform.h"
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Pd_session_component : public Rpc_object<Pd_session>
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned long _pid;
|
||||
|
||||
public:
|
||||
|
||||
Pd_session_component(Rpc_entrypoint *thread_ep,
|
||||
const char *args);
|
||||
|
||||
~Pd_session_component();
|
||||
|
||||
|
||||
/****************************/
|
||||
/** Pd session interface **/
|
||||
/****************************/
|
||||
|
||||
/*
|
||||
* This interface is not functional on Linux.
|
||||
*/
|
||||
|
||||
int bind_thread(Thread_capability thread);
|
||||
int assign_parent(Parent_capability);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__LINUX__PD_SESSION_COMPONENT_H_ */
|
||||
62
base-linux/src/core/include/platform.h
Normal file
62
base-linux/src/core/include/platform.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* \brief Linux platform
|
||||
* \author Christian Helmuth
|
||||
* \author Norman Feske
|
||||
* \date 2007-09-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__LINUX__PLATFORM_H_
|
||||
#define _CORE__INCLUDE__LINUX__PLATFORM_H_
|
||||
|
||||
#include <base/sync_allocator.h>
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/lock_guard.h>
|
||||
|
||||
#include <platform_generic.h>
|
||||
#include <platform_pd.h>
|
||||
#include <platform_thread.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
class Platform : public Platform_generic
|
||||
{
|
||||
private:
|
||||
|
||||
Synchronized_range_allocator<Allocator_avl> _ram_alloc; /* RAM allocator */
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Platform();
|
||||
|
||||
|
||||
/********************************
|
||||
** Generic platform interface **
|
||||
********************************/
|
||||
|
||||
Range_allocator *core_mem_alloc() { return &_ram_alloc; }
|
||||
Range_allocator *ram_alloc() { return &_ram_alloc; }
|
||||
Range_allocator *io_mem_alloc() { return 0; }
|
||||
Range_allocator *io_port_alloc() { return 0; }
|
||||
Range_allocator *irq_alloc() { return 0; }
|
||||
Range_allocator *region_alloc() { return 0; }
|
||||
addr_t vm_start() const { return 0; }
|
||||
size_t vm_size() const { return 0; }
|
||||
Rom_fs *rom_fs() { return 0; }
|
||||
|
||||
void wait_for_exit();
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__PLATFORM_H_ */
|
||||
25
base-linux/src/core/include/platform_pd.h
Normal file
25
base-linux/src/core/include/platform_pd.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* \brief Linux protection domain facility
|
||||
* \author Norman Feske
|
||||
* \date 2006-06-13
|
||||
*
|
||||
* Pretty dumb.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__LINUX__PLATFORM_PD_H_
|
||||
#define _CORE__INCLUDE__LINUX__PLATFORM_PD_H_
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Platform_pd
|
||||
{ };
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__LINUX__PLATFORM_PD_H_ */
|
||||
65
base-linux/src/core/include/platform_thread.h
Normal file
65
base-linux/src/core/include/platform_thread.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* \brief Linux thread facility
|
||||
* \author Norman Feske
|
||||
* \date 2006-06-13
|
||||
*
|
||||
* Pretty dumb.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__LINUX__PLATFORM_THREAD_H_
|
||||
#define _CORE__INCLUDE__LINUX__PLATFORM_THREAD_H_
|
||||
|
||||
#include <base/pager.h>
|
||||
#include <base/thread_state.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Platform_thread
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned long _tid;
|
||||
unsigned long _pid;
|
||||
char _name[32];
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Platform_thread(const char *name, unsigned priority);
|
||||
|
||||
/**
|
||||
* Cancel currently blocking operation
|
||||
*/
|
||||
void cancel_blocking();
|
||||
|
||||
/**
|
||||
* Pause this thread
|
||||
*/
|
||||
void pause();
|
||||
|
||||
/**
|
||||
* Resume this thread
|
||||
*/
|
||||
void resume();
|
||||
|
||||
/**
|
||||
* Dummy implementation of platform-thread interface
|
||||
*/
|
||||
Pager_object *pager() { return 0; }
|
||||
void pager(Pager_object *) { }
|
||||
int start(void *ip, void *sp) { return 0; }
|
||||
int state(Thread_state *state_dst) { return 0; }
|
||||
const char *name() { return _name; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__LINUX__PLATFORM_THREAD_H_ */
|
||||
64
base-linux/src/core/include/rm_session_component.h
Normal file
64
base-linux/src/core/include/rm_session_component.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the RM session interface
|
||||
* \author Christian Helmuth
|
||||
* \date 2006-07-17
|
||||
*
|
||||
* Dummies for Linux platform
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__LINUX__RM_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__LINUX__RM_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode */
|
||||
#include <base/pager.h>
|
||||
#include <base/allocator.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <rm_session/rm_session.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Rm_client;
|
||||
|
||||
class Rm_session_component : public Rpc_object<Rm_session>
|
||||
{
|
||||
public:
|
||||
|
||||
Rm_session_component(Rpc_entrypoint *ds_ep,
|
||||
Rpc_entrypoint *thread_ep,
|
||||
Allocator *md_alloc,
|
||||
size_t ram_quota,
|
||||
Pager_entrypoint *pager_ep,
|
||||
addr_t vm_start,
|
||||
size_t vm_size) { }
|
||||
|
||||
void upgrade_ram_quota(size_t ram_quota) { }
|
||||
|
||||
Local_addr attach(Dataspace_capability, size_t, off_t, bool, Local_addr) {
|
||||
return (addr_t)0; }
|
||||
|
||||
void detach(Local_addr) { }
|
||||
|
||||
Pager_capability add_client(Thread_capability) {
|
||||
return Pager_capability(); }
|
||||
|
||||
void fault_handler(Signal_context_capability) { }
|
||||
|
||||
State state() { return State(); }
|
||||
|
||||
Dataspace_capability dataspace() { return Dataspace_capability(); }
|
||||
|
||||
void dissolve(Rm_client *cl) { }
|
||||
};
|
||||
|
||||
struct Rm_member { Rm_session_component *member_rm_session() { return 0; } };
|
||||
struct Rm_client : Pager_object, Rm_member { };
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__LINUX__RM_SESSION_COMPONENT_H_ */
|
||||
27
base-linux/src/core/io_mem_session_component.cc
Normal file
27
base-linux/src/core/io_mem_session_component.cc
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* \brief Linux-specific IO_MEM service
|
||||
* \author Christian Helmuth
|
||||
* \date 2006-09-01
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#include <io_mem_session_component.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Io_mem_session_component::Io_mem_session_component(Range_allocator *io_mem_alloc,
|
||||
Range_allocator *ram_alloc,
|
||||
Rpc_entrypoint *ds_ep,
|
||||
const char *args)
|
||||
{
|
||||
PWRN("no io_mem support on Linux (args=\"%s\")", args);
|
||||
}
|
||||
59
base-linux/src/core/io_port_session_component.cc
Normal file
59
base-linux/src/core/io_port_session_component.cc
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* \brief Linux-specific IO_PORT service
|
||||
* \author Christian Helmuth
|
||||
* \date 2007-04-18
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <base/printf.h>
|
||||
#include <root/root.h>
|
||||
|
||||
#include "io_port_session_component.h"
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
unsigned char Io_port_session_component::inb(unsigned short address) {
|
||||
return 0; }
|
||||
|
||||
|
||||
unsigned short Io_port_session_component::inw(unsigned short address) {
|
||||
return 0; }
|
||||
|
||||
|
||||
unsigned Io_port_session_component::inl(unsigned short address) {
|
||||
return 0; }
|
||||
|
||||
|
||||
void Io_port_session_component::outb(unsigned short address, unsigned char value) {
|
||||
}
|
||||
|
||||
|
||||
void Io_port_session_component::outw(unsigned short address, unsigned short value) {
|
||||
}
|
||||
|
||||
|
||||
void Io_port_session_component::outl(unsigned short address, unsigned value) {
|
||||
}
|
||||
|
||||
|
||||
Io_port_session_component::Io_port_session_component(Range_allocator *io_port_alloc,
|
||||
const char *args)
|
||||
: _io_port_alloc(io_port_alloc)
|
||||
{
|
||||
PWRN("no IO_PORT support under Linux (args=\"%s\")", args);
|
||||
_size = 0;
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
|
||||
|
||||
Io_port_session_component::~Io_port_session_component()
|
||||
{
|
||||
PERR("Implement me, immediately!");
|
||||
}
|
||||
51
base-linux/src/core/pd_session_component.cc
Normal file
51
base-linux/src/core/pd_session_component.cc
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* \brief Core implementation of the PD session interface
|
||||
* \author Christian Helmuth
|
||||
* \date 2006-07-17
|
||||
*
|
||||
* FIXME arg_string and quota missing
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Genode */
|
||||
#include <base/printf.h>
|
||||
|
||||
/* Core */
|
||||
#include <pd_session_component.h>
|
||||
|
||||
/* Linux includes */
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Pd_session_component::Pd_session_component(Rpc_entrypoint *thread_ep,
|
||||
const char *args)
|
||||
{
|
||||
_pid = Arg_string::find_arg(args, "PID").long_value(0);
|
||||
}
|
||||
|
||||
|
||||
Pd_session_component::~Pd_session_component()
|
||||
{
|
||||
if (_pid)
|
||||
lx_kill(_pid, 9);
|
||||
}
|
||||
|
||||
|
||||
int Pd_session_component::bind_thread(Thread_capability)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Pd_session_component::assign_parent(Parent_capability)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
62
base-linux/src/core/platform.cc
Normal file
62
base-linux/src/core/platform.cc
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* \brief Linux platform interface implementation
|
||||
* \author Norman Feske
|
||||
* \date 2006-06-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/lock.h>
|
||||
|
||||
/* local includes */
|
||||
#include "platform.h"
|
||||
#include "core_env.h"
|
||||
|
||||
/* Linux includes */
|
||||
#include <linux_syscalls.h>
|
||||
#include <linux_rpath.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
static char _some_mem[80*1024*1024];
|
||||
static Lock _wait_for_exit_lock(Lock::LOCKED); /* exit() sync */
|
||||
|
||||
|
||||
static void signal_handler(int signum)
|
||||
{
|
||||
_wait_for_exit_lock.unlock();
|
||||
}
|
||||
|
||||
|
||||
Platform::Platform()
|
||||
: _ram_alloc(0)
|
||||
{
|
||||
/* catch control-c */
|
||||
lx_sigaction(2, signal_handler);
|
||||
|
||||
/* create resource directory under /tmp */
|
||||
lx_mkdir(lx_rpath(), S_IRWXU);
|
||||
|
||||
_ram_alloc.add_range((addr_t)_some_mem, sizeof(_some_mem));
|
||||
}
|
||||
|
||||
|
||||
void Platform::wait_for_exit()
|
||||
{
|
||||
/* block until exit condition is satisfied */
|
||||
try { _wait_for_exit_lock.lock(); }
|
||||
catch (Blocking_canceled) { };
|
||||
}
|
||||
|
||||
void Core_parent::exit(int exit_value)
|
||||
{
|
||||
lx_exit_group(exit_value);
|
||||
}
|
||||
86
base-linux/src/core/platform_thread.cc
Normal file
86
base-linux/src/core/platform_thread.cc
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* \brief Linux-specific platform thread 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 <util/token.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
/* local includes */
|
||||
#include "platform_thread.h"
|
||||
|
||||
/* Linux syscall helper */
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
typedef Token<Scanner_policy_identifier_with_underline> Tid_token;
|
||||
|
||||
|
||||
Platform_thread::Platform_thread(const char *name, unsigned)
|
||||
{
|
||||
/* search for thread-id portion of thread name */
|
||||
Tid_token tok(name);
|
||||
while (tok.type() != Tid_token::END && tok[0] != ':')
|
||||
tok = tok.next();
|
||||
|
||||
/* tok points at the colon separator, next token is the id */
|
||||
tok = tok.next();
|
||||
|
||||
if (tok.type() == Tid_token::END) {
|
||||
PWRN("Invalid format of thread name.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* convert string to thread id */
|
||||
ascii_to(tok.start(), &_tid);
|
||||
|
||||
/* search for process-id portion of thread name */
|
||||
while (tok.type() != Tid_token::END && tok[0] != ':')
|
||||
tok = tok.next();
|
||||
|
||||
/* tok points at the colon separator, next token is the id */
|
||||
tok = tok.next();
|
||||
|
||||
if (tok.type() == Tid_token::END) {
|
||||
PWRN("Invalid format of thread name.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* convert string to process id */
|
||||
ascii_to(tok.start(), &_pid);
|
||||
|
||||
/* initialize private members */
|
||||
size_t name_len = tok.start() - name;
|
||||
strncpy(_name, name, min(sizeof(_name), name_len));
|
||||
}
|
||||
|
||||
|
||||
void Platform_thread::cancel_blocking()
|
||||
{
|
||||
PDBG("send cancel-blocking signal to %ld\n", _tid);
|
||||
lx_tgkill(_pid, _tid, LX_SIGUSR1);
|
||||
}
|
||||
|
||||
|
||||
void Platform_thread::pause()
|
||||
{
|
||||
PDBG("not implemented");
|
||||
}
|
||||
|
||||
|
||||
void Platform_thread::resume()
|
||||
{
|
||||
PDBG("not implemented");
|
||||
}
|
||||
59
base-linux/src/core/ram_session_support.cc
Normal file
59
base-linux/src/core/ram_session_support.cc
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* \brief Make dataspace accessible to other Linux processes
|
||||
* \author Norman Feske
|
||||
* \date 2006-07-03
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* glibc includes */
|
||||
#include <fcntl.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/snprintf.h>
|
||||
|
||||
/* local includes */
|
||||
#include "ram_session_component.h"
|
||||
|
||||
/* Linux syscall bindings */
|
||||
#include <linux_syscalls.h>
|
||||
#include <linux_rpath.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
static int ram_ds_cnt = 0; /* counter for creating unique dataspace IDs */
|
||||
|
||||
void Ram_session_component::_export_ram_ds(Dataspace_component *ds)
|
||||
{
|
||||
char fname_buf[Linux_dataspace::FNAME_LEN];
|
||||
|
||||
/* assign filename to dataspace */
|
||||
snprintf(fname_buf, sizeof(fname_buf), "%s/ds-%d", lx_rpath(), ram_ds_cnt++);
|
||||
|
||||
ds->fname(fname_buf);
|
||||
|
||||
/* create new file representing the dataspace */
|
||||
lx_unlink(fname_buf);
|
||||
int fd = lx_open(fname_buf, O_CREAT | O_RDWR | O_TRUNC | LX_O_CLOEXEC, S_IRWXU);
|
||||
lx_ftruncate(fd, ds->size());
|
||||
lx_close(fd);
|
||||
}
|
||||
|
||||
|
||||
void Ram_session_component::_revoke_ram_ds(Dataspace_component *ds)
|
||||
{
|
||||
lx_unlink(ds->fname().buf);
|
||||
}
|
||||
|
||||
|
||||
void Ram_session_component::_clear_ds(Dataspace_component *ds)
|
||||
{
|
||||
memset((void *)ds->phys_addr(), 0, ds->size());
|
||||
}
|
||||
71
base-linux/src/core/rom_session_component.cc
Normal file
71
base-linux/src/core/rom_session_component.cc
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* \brief Linux-specific core implementation of the ROM session interface
|
||||
* \author Norman Feske
|
||||
* \date 2006-07-06
|
||||
*
|
||||
* The Linux version of ROM session component does not use the
|
||||
* Rom_fs as provided as constructor argument. Instead, we map
|
||||
* rom modules directly to files of the host file system.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Linux includes */
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <linux_dataspace/linux_dataspace.h>
|
||||
#include <util/arg_string.h>
|
||||
#include <root/root.h>
|
||||
|
||||
/* local includes */
|
||||
#include "rom_session_component.h"
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
static Genode::size_t file_size(const char *path)
|
||||
{
|
||||
struct stat64 s;
|
||||
if (lx_stat(path, &s) < 0)
|
||||
return 0;
|
||||
else
|
||||
return s.st_size;
|
||||
}
|
||||
|
||||
|
||||
Rom_session_component::Rom_session_component(Rom_fs *rom_fs,
|
||||
Rpc_entrypoint *ds_ep,
|
||||
const char *args)
|
||||
: _ds_ep(ds_ep)
|
||||
{
|
||||
/* extract filename from session arguments */
|
||||
char fname_buf[Linux_dataspace::FNAME_LEN];
|
||||
Arg_string::find_arg(args, "filename").string(fname_buf, sizeof(fname_buf), "");
|
||||
|
||||
Genode::size_t fsize = file_size(fname_buf);
|
||||
|
||||
/* use invalid capability as default value */
|
||||
_ds_cap = Rom_dataspace_capability();
|
||||
|
||||
/* ROM module not found */
|
||||
if (fsize == 0)
|
||||
throw Root::Invalid_args();
|
||||
|
||||
_ds = Dataspace_component(fsize, 0, false);
|
||||
_ds.fname(fname_buf);
|
||||
|
||||
Dataspace_capability ds_cap = _ds_ep->manage(&_ds);
|
||||
_ds_cap = static_cap_cast<Rom_dataspace>(ds_cap);
|
||||
}
|
||||
|
||||
|
||||
Rom_session_component::~Rom_session_component()
|
||||
{
|
||||
_ds_ep->dissolve(&_ds);
|
||||
}
|
||||
36
base-linux/src/core/target.mk
Normal file
36
base-linux/src/core/target.mk
Normal file
@@ -0,0 +1,36 @@
|
||||
TARGET = core
|
||||
REQUIRES = linux
|
||||
LIBS = cxx ipc heap core_printf process lock raw_server syscall rpath
|
||||
|
||||
GEN_CORE_DIR = $(BASE_DIR)/src/core
|
||||
|
||||
SRC_CC = main.cc \
|
||||
platform.cc \
|
||||
platform_thread.cc \
|
||||
ram_session_component.cc \
|
||||
ram_session_support.cc \
|
||||
rom_session_component.cc \
|
||||
cpu_session_component.cc \
|
||||
pd_session_component.cc \
|
||||
io_mem_session_component.cc \
|
||||
io_port_session_component.cc \
|
||||
signal_session_component.cc \
|
||||
signal_source_component.cc \
|
||||
thread.cc \
|
||||
thread_linux.cc \
|
||||
context_area.cc \
|
||||
debug.cc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/core/include \
|
||||
$(GEN_CORE_DIR)/include \
|
||||
$(REP_DIR)/src/platform \
|
||||
/usr/include
|
||||
|
||||
vpath main.cc $(GEN_CORE_DIR)
|
||||
vpath thread.cc $(BASE_DIR)/src/base/thread
|
||||
vpath ram_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath signal_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath signal_source_component.cc $(GEN_CORE_DIR)
|
||||
vpath debug.cc $(REP_DIR)/src/base/env
|
||||
vpath %.cc $(PRG_DIR)
|
||||
55
base-linux/src/core/thread_linux.cc
Normal file
55
base-linux/src/core/thread_linux.cc
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* \brief Implementation of the core-internal Thread API via Linux threads
|
||||
* \author Norman Feske
|
||||
* \date 2006-06-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* Linux syscall bindings */
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
static void empty_signal_handler(int) { }
|
||||
|
||||
|
||||
static void thread_start(void *)
|
||||
{
|
||||
/*
|
||||
* Set signal handler such that canceled system calls get not
|
||||
* transparently retried after a signal gets received.
|
||||
*/
|
||||
lx_sigaction(LX_SIGUSR1, empty_signal_handler);
|
||||
|
||||
Thread_base::myself()->entry();
|
||||
sleep_forever();
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::_init_platform_thread() { }
|
||||
|
||||
|
||||
void Thread_base::_deinit_platform_thread() { }
|
||||
|
||||
|
||||
void Thread_base::start()
|
||||
{
|
||||
/* align initial stack to 16 byte boundary */
|
||||
void *thread_sp = (void *)((addr_t)(_context->stack) & ~0xf);
|
||||
_tid.tid = lx_create_thread(thread_start, thread_sp, this);
|
||||
_tid.pid = lx_getpid();
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::cancel_blocking() { }
|
||||
40
base-linux/src/platform/_main_helper.h
Normal file
40
base-linux/src/platform/_main_helper.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* \brief Platform-specific helper functions for the _main() function
|
||||
* \author Christian Prochaska
|
||||
* \date 2009-08-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PLATFORM___MAIN_HELPER_H_
|
||||
#define _PLATFORM___MAIN_HELPER_H_
|
||||
|
||||
#include <base/thread.h>
|
||||
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
/*
|
||||
* Define 'lx_environ' pointer that is supposed to be initialized by the
|
||||
* startup code.
|
||||
*/
|
||||
__attribute__((weak)) char **lx_environ = (char **)0;
|
||||
|
||||
|
||||
static void main_thread_bootstrap()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* reserve context area */
|
||||
Genode::addr_t base = Thread_base::CONTEXT_AREA_VIRTUAL_BASE;
|
||||
Genode::size_t size = Thread_base::CONTEXT_AREA_VIRTUAL_SIZE;
|
||||
if (lx_vm_reserve(base, size) != base)
|
||||
PERR("reservation of context area [%lx,%lx) failed",
|
||||
(unsigned long) base, (unsigned long) base + size);
|
||||
}
|
||||
|
||||
#endif /* _PLATFORM___MAIN_HELPER_H_ */
|
||||
25
base-linux/src/platform/context_area.nostdlib.ld
Normal file
25
base-linux/src/platform/context_area.nostdlib.ld
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* \brief Linux-specific linker script additions (STDLIB = no)
|
||||
* \author Christian Helmuth
|
||||
* \date 2010-09-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
PHDRS
|
||||
{
|
||||
context_area PT_LOAD FLAGS(0);
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x40000000;
|
||||
_context_area_start = .;
|
||||
.context_area : { . += 0x10000000; } : context_area
|
||||
_context_area_end = .;
|
||||
}
|
||||
20
base-linux/src/platform/context_area.stdlib.ld
Normal file
20
base-linux/src/platform/context_area.stdlib.ld
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* \brief Linux-specific linker script additions (STDLIB = yes)
|
||||
* \author Christian Helmuth
|
||||
* \date 2010-09-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x40000000;
|
||||
_context_area_start = .;
|
||||
.context_area : { . += 0x10000000; }
|
||||
_context_area_end = .;
|
||||
}
|
||||
39
base-linux/src/platform/linux_rpath.cc
Normal file
39
base-linux/src/platform/linux_rpath.cc
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* \brief Linux resource path
|
||||
* \author Christian Helmuth
|
||||
* \date 2011-09-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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/snprintf.h>
|
||||
|
||||
#include <linux_syscalls.h>
|
||||
#include <linux_rpath.h>
|
||||
|
||||
|
||||
namespace {
|
||||
struct Rpath
|
||||
{
|
||||
char string[32];
|
||||
|
||||
Rpath()
|
||||
{
|
||||
Genode::snprintf(string, sizeof(string), "/tmp/genode-%d", lx_getuid());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
char const * lx_rpath()
|
||||
{
|
||||
static Rpath rpath;
|
||||
|
||||
return rpath.string;
|
||||
}
|
||||
25
base-linux/src/platform/linux_rpath.h
Normal file
25
base-linux/src/platform/linux_rpath.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* \brief Linux resource path
|
||||
* \author Christian Helmuth
|
||||
* \date 2011-09-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#ifndef _PLATFORM__LINUX_RPATH_H_
|
||||
#define _PLATFORM__LINUX_RPATH_H_
|
||||
|
||||
|
||||
/**
|
||||
* Return resource path for Genode
|
||||
*
|
||||
* Genode creates files for dataspaces and endpoints under in this directory.
|
||||
*/
|
||||
char const * lx_rpath();
|
||||
|
||||
#endif /* _PLATFORM__LINUX_RPATH_H_ */
|
||||
501
base-linux/src/platform/linux_syscalls.h
Normal file
501
base-linux/src/platform/linux_syscalls.h
Normal file
@@ -0,0 +1,501 @@
|
||||
/*
|
||||
* \brief Linux system-call wrappers
|
||||
* \author Norman Feske
|
||||
* \date 2008-10-22
|
||||
*
|
||||
* This file is meant to be internally used by the framework. It is not public
|
||||
* interface.
|
||||
*
|
||||
* From within the framework libraries, we have to use the Linux syscall
|
||||
* interface directly rather than relying on convenient libC functions to be
|
||||
* able to link this part of the framework to a custom libC. Otherwise, we
|
||||
* would end up with very nasty cyclic dependencies when using framework
|
||||
* functions such as IPC from the libC back end.
|
||||
*
|
||||
* The Linux syscall interface looks different for 32bit and 64bit system, in
|
||||
* particular regarding the socket interface. On 32bit systems, all socket
|
||||
* operations are invoked via the 'socketcall' syscall. On 64bit systems, the
|
||||
* different socket functions have distinct syscalls.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008-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.
|
||||
*/
|
||||
|
||||
#ifndef _PLATFORM__LINUX_SYSCALLS_H_
|
||||
#define _PLATFORM__LINUX_SYSCALLS_H_
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1 /* needed to enable the definition of 'stat64' */
|
||||
#endif
|
||||
|
||||
/* Linux includes */
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/string.h>
|
||||
|
||||
|
||||
/*****************************************
|
||||
** Functions used by the IPC framework **
|
||||
*****************************************/
|
||||
|
||||
#include <linux/net.h>
|
||||
|
||||
extern "C" long lx_syscall(int number, ...);
|
||||
extern "C" int lx_clone(int (*fn)(void *), void *child_stack,
|
||||
int flags, void *arg);
|
||||
|
||||
|
||||
inline Genode::uint16_t lx_bswap16(Genode::uint16_t x)
|
||||
{
|
||||
char v[2] = {
|
||||
(x & 0xff00) >> 8,
|
||||
(x & 0x00ff) >> 0,
|
||||
};
|
||||
return *(Genode::uint16_t *)v;
|
||||
}
|
||||
|
||||
|
||||
inline Genode::uint32_t lx_bswap32(Genode::uint32_t x)
|
||||
{
|
||||
char v[4] = {
|
||||
(x & 0xff000000) >> 24,
|
||||
(x & 0x00ff0000) >> 16,
|
||||
(x & 0x0000ff00) >> 8,
|
||||
(x & 0x000000ff) >> 0,
|
||||
};
|
||||
return *(Genode::uint32_t *)v;
|
||||
}
|
||||
|
||||
#define lx_htonl(x) lx_bswap32(x)
|
||||
#define lx_htons(x) lx_bswap16(x)
|
||||
#define lx_ntohs(x) lx_bswap16(x)
|
||||
|
||||
#ifdef SYS_socketcall
|
||||
|
||||
inline int lx_socketcall(int call, unsigned long *args)
|
||||
{
|
||||
int res = lx_syscall(SYS_socketcall, call, args);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
inline int lx_socket(int domain, int type, int protocol)
|
||||
{
|
||||
unsigned long args[3] = { domain, type, protocol };
|
||||
return lx_socketcall(SYS_SOCKET, args);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_connect(int sockfd, const struct sockaddr *serv_addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
unsigned long args[3] = { sockfd, (unsigned long)serv_addr, addrlen };
|
||||
return lx_socketcall(SYS_CONNECT, args);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_bind(int sockfd, const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
unsigned long args[3] = { sockfd, (unsigned long)addr, addrlen };
|
||||
return lx_socketcall(SYS_BIND, args);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
|
||||
{
|
||||
unsigned long args[3] = { s, (unsigned long)name, (unsigned long)namelen };
|
||||
return lx_socketcall(SYS_GETSOCKNAME, args);
|
||||
}
|
||||
|
||||
|
||||
inline ssize_t lx_recvfrom(int s, void *buf, Genode::size_t len, int flags,
|
||||
struct sockaddr *from, socklen_t *from_len)
|
||||
{
|
||||
unsigned long args[6] = { s, (unsigned long)buf, len, flags,
|
||||
(unsigned long)from, (unsigned long)from_len };
|
||||
return lx_socketcall(SYS_RECVFROM, args);
|
||||
}
|
||||
|
||||
|
||||
inline ssize_t lx_sendto(int s, void *buf, Genode::size_t len, int flags,
|
||||
struct sockaddr *to, socklen_t to_len)
|
||||
{
|
||||
unsigned long args[6] = { s, (unsigned long)buf, len, flags,
|
||||
(unsigned long)to, (unsigned long)to_len };
|
||||
return lx_socketcall(SYS_SENDTO, args);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline int lx_socket(int domain, int type, int protocol)
|
||||
{
|
||||
return lx_syscall(SYS_socket, domain, type, protocol);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_connect(int sockfd, const struct sockaddr *serv_addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
return lx_syscall(SYS_connect, sockfd, serv_addr, addrlen);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_bind(int sockfd, const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
return lx_syscall(SYS_bind, sockfd, addr, addrlen);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
|
||||
{
|
||||
return lx_syscall(SYS_getsockname, s, name, namelen);
|
||||
}
|
||||
|
||||
|
||||
inline ssize_t lx_recvfrom(int s, void *buf, Genode::size_t len, int flags,
|
||||
struct sockaddr *from, socklen_t *from_len)
|
||||
{
|
||||
return lx_syscall(SYS_recvfrom, s, buf, len, flags, from, from_len);
|
||||
}
|
||||
|
||||
|
||||
inline ssize_t lx_sendto(int s, void *buf, Genode::size_t len, int flags,
|
||||
struct sockaddr *to, socklen_t to_len)
|
||||
{
|
||||
return lx_syscall(SYS_sendto, s, buf, len, flags, to, to_len);
|
||||
}
|
||||
|
||||
#endif /* SYS_socketcall */
|
||||
|
||||
|
||||
inline int lx_write(int fd, const void *buf, Genode::size_t count)
|
||||
{
|
||||
return lx_syscall(SYS_write, fd, buf, count);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_close(int fd)
|
||||
{
|
||||
return lx_syscall(SYS_close, fd);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************
|
||||
** Functions used by the process library **
|
||||
*******************************************/
|
||||
|
||||
inline int lx_execve(const char *filename, char *const argv[],
|
||||
char *const envp[])
|
||||
{
|
||||
return lx_syscall(SYS_execve, filename, argv, envp);
|
||||
}
|
||||
|
||||
|
||||
inline void lx_exit(int status)
|
||||
{
|
||||
lx_syscall(SYS_exit, status);
|
||||
}
|
||||
|
||||
|
||||
inline void lx_exit_group(int status)
|
||||
{
|
||||
lx_syscall(SYS_exit_group, status);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************
|
||||
** Functions used by the env library and local rm session **
|
||||
************************************************************/
|
||||
|
||||
/* O_CLOEXEC is a GNU extension so we provide it here */
|
||||
enum { LX_O_CLOEXEC = 02000000 };
|
||||
|
||||
inline int lx_open(const char *pathname, int flags, mode_t mode = 0)
|
||||
{
|
||||
return lx_syscall(SYS_open, pathname, flags, mode);
|
||||
}
|
||||
|
||||
|
||||
inline void *lx_mmap(void *start, Genode::size_t length, int prot, int flags,
|
||||
int fd, off_t offset)
|
||||
{
|
||||
#ifdef _LP64
|
||||
return (void *)lx_syscall(SYS_mmap, start, length, prot, flags, fd, offset);
|
||||
#else
|
||||
return (void *)lx_syscall(SYS_mmap2, start, length, prot, flags, fd, offset/4096);
|
||||
#endif /* _LP64 */
|
||||
}
|
||||
|
||||
|
||||
inline int lx_munmap(void *addr, size_t length)
|
||||
{
|
||||
return lx_syscall(SYS_munmap, addr, length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Exclude local virtual memory area from being used by mmap
|
||||
*
|
||||
* \param base base address of area to reserve
|
||||
* \param size number of bytes to reserve
|
||||
*
|
||||
* \return start of allocated reserved area, or ~0 on failure
|
||||
*/
|
||||
inline Genode::addr_t lx_vm_reserve(Genode::addr_t base, Genode::size_t size)
|
||||
{
|
||||
/* we cannot include sys/mman.h from here */
|
||||
enum {
|
||||
LX_MAP_PRIVATE = 0x02,
|
||||
LX_MAP_FIXED = 0x10,
|
||||
LX_MAP_ANONYMOUS = 0x20,
|
||||
LX_PROT_NONE = 0x0
|
||||
};
|
||||
|
||||
int const flags = LX_MAP_ANONYMOUS | LX_MAP_PRIVATE
|
||||
| (base ? LX_MAP_FIXED : 0);
|
||||
|
||||
void * const res = lx_mmap((void *)base, size, LX_PROT_NONE, flags, -1, 0);
|
||||
|
||||
if (base)
|
||||
return ((Genode::addr_t)res == base) ? base : ~0;
|
||||
else
|
||||
return (Genode::addr_t)res;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************
|
||||
** Functions used by core's ram-session support code **
|
||||
*******************************************************/
|
||||
|
||||
inline int lx_mkdir(char const *pathname, mode_t mode)
|
||||
{
|
||||
return lx_syscall(SYS_mkdir, pathname, mode);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_ftruncate(int fd, unsigned long length)
|
||||
{
|
||||
return lx_syscall(SYS_ftruncate, fd, length);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_unlink(const char *fname)
|
||||
{
|
||||
return lx_syscall(SYS_unlink, fname);
|
||||
}
|
||||
|
||||
/*******************************************************
|
||||
** Functions used by core's rom-session support code **
|
||||
*******************************************************/
|
||||
|
||||
inline int lx_stat(const char *path, struct stat64 *buf)
|
||||
{
|
||||
#ifdef _LP64
|
||||
return lx_syscall(SYS_stat, path, buf);
|
||||
#else
|
||||
return lx_syscall(SYS_stat64, path, buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
** Functions used by thread lib and core's cancel-blocking mechanism **
|
||||
***********************************************************************/
|
||||
|
||||
enum {
|
||||
LX_SIGUSR1 = 10, /* used for cancel-blocking mechanism */
|
||||
LX_SIGCANCEL = 32, /* accoring to glibc, this equals SIGRTMIN,
|
||||
used for killing threads */
|
||||
};
|
||||
|
||||
|
||||
struct kernel_sigaction
|
||||
{
|
||||
void (*handler)(int);
|
||||
unsigned long flags;
|
||||
void (*restorer)(void);
|
||||
sigset_t mask;
|
||||
};
|
||||
|
||||
|
||||
inline int lx_sigemptyset(sigset_t *set)
|
||||
{
|
||||
if (set == 0)
|
||||
return -1;
|
||||
Genode::memset(set, 0, sizeof(sigset_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _LP64
|
||||
extern "C" void lx_restore_rt (void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Simplified binding for sigaction system call
|
||||
*/
|
||||
inline int lx_sigaction(int signum, void (*handler)(int))
|
||||
{
|
||||
struct kernel_sigaction act;
|
||||
act.handler = handler;
|
||||
|
||||
#ifdef _LP64
|
||||
/*
|
||||
* The SA_RESTORER flag is not officially documented, but used internally
|
||||
* by the glibc implementation of sigaction(). Without specifying this flag
|
||||
* tgkill() does not work on x86_64. The restorer function gets called
|
||||
* when leaving the signal handler and it should call the rt_sigreturn syscall.
|
||||
*/
|
||||
enum { SA_RESTORER = 0x04000000 };
|
||||
act.flags = SA_RESTORER;
|
||||
act.restorer = lx_restore_rt;;
|
||||
#else
|
||||
act.flags = 0;
|
||||
act.restorer = 0;
|
||||
#endif
|
||||
lx_sigemptyset(&act.mask);
|
||||
|
||||
return lx_syscall(SYS_rt_sigaction, signum, &act, 0UL, _NSIG/8);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send signal to process
|
||||
*
|
||||
* This function is used by core to kill processes.
|
||||
*/
|
||||
inline int lx_kill(int pid, int signal)
|
||||
{
|
||||
return lx_syscall(SYS_kill, pid, signal);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send signal to thread
|
||||
*
|
||||
* This function is used by core to cancel blocking operations of
|
||||
* threads, and by the thread library to kill threads.
|
||||
*/
|
||||
inline int lx_tgkill(int pid, int tid, int signal)
|
||||
{
|
||||
return lx_syscall(SYS_tgkill, pid, tid, signal);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_create_thread(void (*entry)(void *), void *stack, void *arg)
|
||||
{
|
||||
int flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND
|
||||
| CLONE_THREAD | CLONE_SYSVSEM;
|
||||
|
||||
/*
|
||||
* The syscall binding for clone does not exist in the FreeBSD libc, which
|
||||
* we are using as libc for Genode. In glibc, clone is implemented as a
|
||||
* assembler binding without external libc references. Hence, we are safe
|
||||
* to rely on the glibc version of 'clone' here.
|
||||
*/
|
||||
return lx_clone((int (*)(void *))entry, stack, flags, arg);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_create_process(int (*entry)(void *), void *stack, void *arg)
|
||||
{
|
||||
int flags = CLONE_VFORK | SIGCHLD;
|
||||
return lx_clone((int (*)(void *))entry, stack, flags, arg);
|
||||
}
|
||||
|
||||
|
||||
inline pid_t lx_getpid() { return lx_syscall(SYS_getpid); }
|
||||
inline pid_t lx_gettid() { return lx_syscall(SYS_gettid); }
|
||||
inline uid_t lx_getuid() { return lx_syscall(SYS_getuid); }
|
||||
|
||||
|
||||
/************************************
|
||||
** Functions used by lock library **
|
||||
************************************/
|
||||
|
||||
struct timespec;
|
||||
|
||||
inline int lx_nanosleep(const struct timespec *req, struct timespec *rem)
|
||||
{
|
||||
return lx_syscall(SYS_nanosleep, req, rem);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Signal set corrsponding to glibc's 'sigset_t'
|
||||
*/
|
||||
class Lx_sigset
|
||||
{
|
||||
unsigned long int _value[_SIGSET_NWORDS];
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Lx_sigset() { }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param signum set specified entry of sigset
|
||||
*/
|
||||
Lx_sigset(int signum)
|
||||
{
|
||||
|
||||
for (unsigned i = 0; i < _SIGSET_NWORDS; i++)
|
||||
_value[i] = 0;
|
||||
|
||||
/*
|
||||
* Both '__sigword' and '__sigmask' are macros, defined in the
|
||||
* glibc header file 'bits/sigset.h' and not external functions.
|
||||
* Therefore we can use them here without getting into conflicts
|
||||
* with the linkage of another libc.
|
||||
*/
|
||||
_value[__sigword(signum)] = __sigmask(signum);
|
||||
}
|
||||
|
||||
bool is_set(int signum) {
|
||||
return _value[__sigword(signum)] && __sigmask(signum); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check if signal is pending
|
||||
*
|
||||
* \return true if signal is pending
|
||||
*/
|
||||
inline bool lx_sigpending(int signum)
|
||||
{
|
||||
Lx_sigset sigset;
|
||||
lx_syscall(SYS_rt_sigpending, &sigset, _NSIG/8);
|
||||
return sigset.is_set(signum);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set signal mask state
|
||||
*
|
||||
* \param signum signal to mask or unmask
|
||||
* \param state mask state for the signal,
|
||||
* true enables the signal,
|
||||
* false blocks the signal
|
||||
*/
|
||||
inline bool lx_sigsetmask(int signum, bool state)
|
||||
{
|
||||
Lx_sigset old_sigmask, sigset(signum);
|
||||
lx_syscall(SYS_rt_sigprocmask, state ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old_sigmask, _NSIG/8);
|
||||
return old_sigmask.is_set(signum);
|
||||
}
|
||||
|
||||
#endif /* _PLATFORM__LINUX_SYSCALLS_H_ */
|
||||
47
base-linux/src/platform/lx_hybrid.cc
Normal file
47
base-linux/src/platform/lx_hybrid.cc
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* \brief Supplemental code for hybrid Genode/Linux programs
|
||||
* \author Norman Feske
|
||||
* \date 2011-09-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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/crt0.h>
|
||||
#include <base/printf.h>
|
||||
#include <_main_helper.h>
|
||||
|
||||
|
||||
extern "C" int raw_write_str(const char *str);
|
||||
|
||||
|
||||
/**
|
||||
* Dummy for symbol that is normally provided by '_main.cc'
|
||||
*/
|
||||
int genode___cxa_atexit(void (*func)(void*), void *arg, void *dso)
|
||||
{
|
||||
raw_write_str("genode___cxa_atexit called, not implemented\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Manually initialize the 'lx_environ' pointer. For non-hybrid programs, this
|
||||
* pointer is initialized by the startup code.
|
||||
*/
|
||||
extern char **environ;
|
||||
extern char **lx_environ;
|
||||
|
||||
/*
|
||||
* This function must be called before any other static constructor in the Genode
|
||||
* application, so it gets the highest priority (lowest priority number >100)
|
||||
*/
|
||||
__attribute__((constructor(101))) void lx_hybrid_init()
|
||||
{
|
||||
main_thread_bootstrap();
|
||||
lx_environ = environ;
|
||||
}
|
||||
70
base-linux/src/platform/x86_32/crt0.s
Normal file
70
base-linux/src/platform/x86_32/crt0.s
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* \brief Startup code for Genode applications
|
||||
* \author Christian Helmuth
|
||||
* \date 2006-07-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*--- .text (program code) -------------------------*/
|
||||
.text
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
|
||||
movl %esp, __initial_sp
|
||||
/*
|
||||
* environ = &argv[argc + 1]
|
||||
* in Genode argc is always 1
|
||||
*/
|
||||
popl %eax /* argc */
|
||||
popl %eax /* argv[0] */
|
||||
popl %eax /* NULL */
|
||||
movl %esp, lx_environ
|
||||
|
||||
/* XXX Switch to our own stack. */
|
||||
movl $_stack_high,%esp
|
||||
|
||||
/* Clear the base pointer so that stack backtraces will work. */
|
||||
xorl %ebp,%ebp
|
||||
|
||||
/* Jump into init C code */
|
||||
call _main
|
||||
|
||||
/* We should never get here since _main does not return */
|
||||
1: int $3
|
||||
jmp 2f
|
||||
.ascii "_main() returned."
|
||||
2: jmp 1b
|
||||
|
||||
|
||||
/*--------------------------------------------------*/
|
||||
.data
|
||||
.globl __dso_handle
|
||||
__dso_handle:
|
||||
.long 0
|
||||
|
||||
.globl __initial_sp
|
||||
__initial_sp:
|
||||
.long 0
|
||||
|
||||
/*--- .eh_frame (exception frames) -----------------*/
|
||||
/*
|
||||
.section .eh_frame,"aw"
|
||||
.globl __EH_FRAME_BEGIN__
|
||||
__EH_FRAME_BEGIN__:
|
||||
*/
|
||||
|
||||
/*--- .bss (non-initialized data) ------------------*/
|
||||
.bss
|
||||
.p2align 4
|
||||
.globl _stack_low
|
||||
_stack_low:
|
||||
.space 64*1024
|
||||
.globl _stack_high
|
||||
_stack_high:
|
||||
109
base-linux/src/platform/x86_32/lx_clone.S
Normal file
109
base-linux/src/platform/x86_32/lx_clone.S
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* \brief Linux clone() binding
|
||||
* \author Christian Prochaska
|
||||
* \date 2009-07-14
|
||||
*
|
||||
* based on glibc-2.9/sysdeps/unix/sysv/linux/i386/clone.S
|
||||
*/
|
||||
|
||||
|
||||
#define L(name) name
|
||||
|
||||
#define ENTER_KERNEL int $0x80
|
||||
#define SYS_clone 120
|
||||
#define SYS_exit 1
|
||||
|
||||
#define LINKAGE 4
|
||||
#define PTR_SIZE 4
|
||||
|
||||
#define PARMS LINKAGE /* no space for saved regs */
|
||||
#define FUNC PARMS
|
||||
#define STACK FUNC+4
|
||||
#define FLAGS STACK+PTR_SIZE
|
||||
#define ARG FLAGS+4
|
||||
#define PTID ARG+PTR_SIZE
|
||||
#define TLS PTID+PTR_SIZE
|
||||
#define CTID TLS+PTR_SIZE
|
||||
|
||||
.text
|
||||
.globl lx_clone
|
||||
.type lx_clone, @function
|
||||
lx_clone:
|
||||
.cfi_startproc
|
||||
|
||||
/* Insert the argument onto the new stack. Make sure the new
|
||||
thread is started with an alignment of (mod 16). */
|
||||
movl STACK(%esp),%ecx
|
||||
andl $0xfffffff0, %ecx
|
||||
subl $28,%ecx
|
||||
movl ARG(%esp),%eax /* no negative argument counts */
|
||||
movl %eax,12(%ecx)
|
||||
|
||||
/* Save the function pointer as the zeroth argument.
|
||||
It will be popped off in the child in the ebx frobbing below. */
|
||||
movl FUNC(%esp),%eax
|
||||
movl %eax,8(%ecx)
|
||||
/* Don't leak any information. */
|
||||
movl $0,4(%ecx)
|
||||
movl $0,(%ecx)
|
||||
|
||||
/* Do the system call */
|
||||
pushl %ebx
|
||||
.cfi_adjust_cfa_offset (4)
|
||||
pushl %esi
|
||||
.cfi_adjust_cfa_offset (4)
|
||||
pushl %edi
|
||||
.cfi_adjust_cfa_offset (4)
|
||||
|
||||
movl TLS+12(%esp),%esi
|
||||
.cfi_rel_offset %esi, 4
|
||||
movl PTID+12(%esp),%edx
|
||||
movl FLAGS+12(%esp),%ebx
|
||||
.cfi_rel_offset %ebx, 8
|
||||
movl CTID+12(%esp),%edi
|
||||
.cfi_rel_offset %edi, 0
|
||||
movl $SYS_clone,%eax
|
||||
|
||||
/* End FDE now, because in the child the unwind info will be
|
||||
wrong. */
|
||||
.cfi_endproc
|
||||
|
||||
ENTER_KERNEL
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %ebx
|
||||
|
||||
test %eax,%eax
|
||||
jz L(thread_start)
|
||||
|
||||
L(pseudo_end):
|
||||
ret
|
||||
|
||||
L(thread_start):
|
||||
.cfi_startproc;
|
||||
/* Clearing frame pointer is insufficient, use CFI. */
|
||||
.cfi_undefined %eip;
|
||||
/* Note: %esi is zero. */
|
||||
movl %esi,%ebp /* terminate the stack frame */
|
||||
call *%ebx
|
||||
#ifdef PIC
|
||||
call L(here)
|
||||
L(here):
|
||||
popl %ebx
|
||||
addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
|
||||
#endif
|
||||
movl %eax, %ebx
|
||||
movl $SYS_exit, %eax
|
||||
ENTER_KERNEL
|
||||
|
||||
.cfi_endproc;
|
||||
|
||||
.cfi_startproc
|
||||
.cfi_endproc
|
||||
|
||||
/*
|
||||
* Allow stacks to be mapped executable (needed because Genode does not
|
||||
* offer an API to handle non-execute mappings yet).
|
||||
*/
|
||||
.section .note.GNU-stack, "", @progbits
|
||||
|
||||
77
base-linux/src/platform/x86_32/lx_syscall.S
Normal file
77
base-linux/src/platform/x86_32/lx_syscall.S
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* \brief Linux syscall() binding
|
||||
* \author Christian Prochaska
|
||||
* \date 2009-07-14
|
||||
*
|
||||
* based on glibc-2.9/sysdeps/unix/sysv/linux/i386/syscall.S
|
||||
*
|
||||
* error case:
|
||||
* glibc's syscall() function returns -1 and sets errno
|
||||
* lx_syscall() returns -errno
|
||||
*/
|
||||
|
||||
|
||||
#define L(name) name
|
||||
|
||||
#define ENTER_KERNEL int $0x80
|
||||
|
||||
.text
|
||||
.globl lx_syscall
|
||||
.type lx_syscall, @function
|
||||
lx_syscall:
|
||||
.cfi_startproc
|
||||
/* PUSHARGS_6*/ /* Save register contents. */
|
||||
/* PUSHARGS_6 begin */
|
||||
pushl %ebp;
|
||||
.cfi_adjust_cfa_offset 4;
|
||||
.cfi_rel_offset %ebp, 0;
|
||||
L(PUSHBP1):
|
||||
pushl %edi;
|
||||
.cfi_adjust_cfa_offset 4;
|
||||
.cfi_rel_offset %edi, 0;
|
||||
L(PUSHDI1):
|
||||
pushl %esi;
|
||||
.cfi_adjust_cfa_offset 4;
|
||||
.cfi_rel_offset %esi, 0;
|
||||
L(PUSHSI1):
|
||||
pushl %ebx;
|
||||
.cfi_adjust_cfa_offset 4;
|
||||
.cfi_rel_offset %ebx, 0;
|
||||
L(PUSHBX1):
|
||||
/* PUSHARGS_6 end */
|
||||
|
||||
/*_DOARGS_6(44)*/ /* Load arguments. */
|
||||
/*_DOARGS_6(44) begin*/
|
||||
movl 44(%esp), %ebp;
|
||||
movl 40(%esp), %edi;
|
||||
movl 36(%esp), %esi;
|
||||
movl 32(%esp), %edx;
|
||||
movl 28(%esp), %ecx;
|
||||
movl 24(%esp), %ebx;
|
||||
/*_DOARGS_6(44) end*/
|
||||
movl 20(%esp), %eax /* Load syscall number into %eax. */
|
||||
ENTER_KERNEL /* Do the system call. */
|
||||
/* POPARGS_6*/ /* Restore register contents. */
|
||||
/* POPARGS_6 begin */
|
||||
popl %ebx;
|
||||
.cfi_adjust_cfa_offset -4;
|
||||
.cfi_restore %ebx;
|
||||
L(POPBX1):
|
||||
popl %esi;
|
||||
.cfi_adjust_cfa_offset -4;
|
||||
.cfi_restore %esi;
|
||||
L(POPSI1):
|
||||
popl %edi;
|
||||
.cfi_adjust_cfa_offset -4;
|
||||
.cfi_restore %edi;
|
||||
L(POPDI1):
|
||||
popl %ebp;
|
||||
.cfi_adjust_cfa_offset -4;
|
||||
.cfi_restore %ebp;
|
||||
L(POPBP1):
|
||||
/* POPARGS_6 end */
|
||||
L(pseudo_end):
|
||||
ret /* Return to caller. */
|
||||
|
||||
.cfi_endproc
|
||||
|
||||
74
base-linux/src/platform/x86_64/crt0.s
Normal file
74
base-linux/src/platform/x86_64/crt0.s
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* \brief Startup code for Genode applications
|
||||
* \author Christian Helmuth
|
||||
* \date 2006-07-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*--- .text (program code) -------------------------*/
|
||||
.text
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
|
||||
movq __initial_sp@GOTPCREL(%rip), %rax
|
||||
movq %rsp, (%rax)
|
||||
/*
|
||||
* environ = &argv[argc + 1]
|
||||
* in Genode argc is always 1
|
||||
*/
|
||||
popq %rax /* argc */
|
||||
popq %rax /* argv[0] */
|
||||
popq %rax /* NULL */
|
||||
movq lx_environ@GOTPCREL(%rip), %rax
|
||||
movq %rsp, (%rax)
|
||||
|
||||
/* XXX Switch to our own stack. */
|
||||
leaq _stack_high@GOTPCREL(%rip), %rax
|
||||
movq (%rax), %rsp
|
||||
|
||||
/* Clear the base pointer so that stack backtraces will work. */
|
||||
xorq %rbp,%rbp
|
||||
|
||||
/* Jump into init C code */
|
||||
callq _main
|
||||
|
||||
/* We should never get here since _main does not return */
|
||||
1: int $3
|
||||
jmp 2f
|
||||
.ascii "_main() returned."
|
||||
2: jmp 1b
|
||||
|
||||
|
||||
/*--------------------------------------------------*/
|
||||
.data
|
||||
.p2align 8
|
||||
.globl __dso_handle
|
||||
__dso_handle:
|
||||
.quad 0
|
||||
|
||||
.globl __initial_sp
|
||||
__initial_sp:
|
||||
.quad 0
|
||||
|
||||
/*--- .eh_frame (exception frames) -----------------*/
|
||||
/*
|
||||
.section .eh_frame,"aw"
|
||||
.globl __EH_FRAME_BEGIN__
|
||||
__EH_FRAME_BEGIN__:
|
||||
*/
|
||||
|
||||
/*--- .bss (non-initialized data) ------------------*/
|
||||
.bss
|
||||
.p2align 8
|
||||
.globl _stack_low
|
||||
_stack_low:
|
||||
.space 64*1024
|
||||
.globl _stack_high
|
||||
_stack_high:
|
||||
71
base-linux/src/platform/x86_64/lx_clone.S
Normal file
71
base-linux/src/platform/x86_64/lx_clone.S
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* \brief Linux clone() binding
|
||||
* \author Christian Prochaska
|
||||
* \date 2009-07-14
|
||||
*
|
||||
* based on glibc-2.9/sysdeps/unix/sysv/linux/x86_64/clone.S
|
||||
*/
|
||||
|
||||
#define L(name) name
|
||||
|
||||
#define SYS_clone 56
|
||||
#define SYS_exit 60
|
||||
|
||||
.text
|
||||
.globl lx_clone
|
||||
.type lx_clone, @function
|
||||
lx_clone:
|
||||
.cfi_startproc
|
||||
|
||||
/* Insert the argument onto the new stack. */
|
||||
subq $16,%rsi
|
||||
movq %rcx,8(%rsi)
|
||||
|
||||
/* Save the function pointer. It will be popped off in the
|
||||
child in the ebx frobbing below. */
|
||||
movq %rdi,0(%rsi)
|
||||
|
||||
/* Do the system call. */
|
||||
movq %rdx, %rdi
|
||||
movq %r8, %rdx
|
||||
movq %r9, %r8
|
||||
movq 8(%rsp), %r10
|
||||
movl $SYS_clone,%eax
|
||||
|
||||
/* End FDE now, because in the child the unwind info will be
|
||||
wrong. */
|
||||
.cfi_endproc
|
||||
syscall
|
||||
|
||||
testq %rax,%rax
|
||||
jz L(thread_start)
|
||||
|
||||
L(pseudo_end):
|
||||
/* parent returns */
|
||||
ret
|
||||
|
||||
L(thread_start):
|
||||
.cfi_startproc
|
||||
/* Clearing frame pointer is insufficient, use CFI. */
|
||||
.cfi_undefined (%rip);
|
||||
|
||||
/* Clear the frame pointer. The ABI suggests this be done, to mark
|
||||
the outermost frame obviously. */
|
||||
xorl %ebp, %ebp
|
||||
|
||||
/* Set up arguments for the function call. */
|
||||
popq %rax /* Function to call. */
|
||||
popq %rdi /* Argument. */
|
||||
call *%rax
|
||||
/* Call exit with return value from function call. */
|
||||
movq %rax, %rdi
|
||||
movq $SYS_exit, %rax
|
||||
syscall
|
||||
.cfi_endproc
|
||||
|
||||
/*
|
||||
* Allow stacks to be mapped executable (needed because Genode does not
|
||||
* offer an API to handle non-executable mappings yet).
|
||||
*/
|
||||
.section .note.GNU-stack, "", @progbits
|
||||
|
||||
16
base-linux/src/platform/x86_64/lx_restore_rt.S
Normal file
16
base-linux/src/platform/x86_64/lx_restore_rt.S
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* \brief Linux signal handler restorer function
|
||||
* \author Christian Prochaska
|
||||
* \date 2009-07-14
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#define SYS_rt_sigreturn 15
|
||||
|
||||
.text
|
||||
.globl lx_restore_rt
|
||||
.type lx_restore_rt, @function
|
||||
lx_restore_rt:
|
||||
movq $SYS_rt_sigreturn, %rax
|
||||
syscall
|
||||
29
base-linux/src/platform/x86_64/lx_syscall.S
Normal file
29
base-linux/src/platform/x86_64/lx_syscall.S
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* \brief Linux syscall() binding
|
||||
* \author Christian Prochaska
|
||||
* \date 2009-07-14
|
||||
*
|
||||
* based on glibc-2.9/sysdeps/unix/sysv/linux/x86_64/syscall.S
|
||||
*
|
||||
* error case:
|
||||
* glibc's syscall() function returns -1 and sets errno
|
||||
* lx_syscall() returns -errno
|
||||
*/
|
||||
|
||||
|
||||
#define L(name) name
|
||||
|
||||
.text
|
||||
.globl lx_syscall
|
||||
.type lx_syscall, @function
|
||||
lx_syscall:
|
||||
movq %rdi, %rax /* Syscall number -> rax. */
|
||||
movq %rsi, %rdi /* shift arg1 - arg5. */
|
||||
movq %rdx, %rsi
|
||||
movq %rcx, %rdx
|
||||
movq %r8, %r10
|
||||
movq %r9, %r8
|
||||
movq 8(%rsp),%r9 /* arg6 is on the stack. */
|
||||
syscall /* Do the system call. */
|
||||
L(pseudo_end):
|
||||
ret /* Return to caller. */
|
||||
39
base-linux/src/test/lx_hybrid_ctors/main.cc
Normal file
39
base-linux/src/test/lx_hybrid_ctors/main.cc
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* \brief Test if global static constructors in hybrid applications get called
|
||||
* \author Christian Prochaska
|
||||
* \date 2011-11-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
struct Testapp_testclass
|
||||
{
|
||||
Testapp_testclass()
|
||||
{
|
||||
Genode::printf("Global static constructor of Genode application called\n");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Testapp_testclass testapp_testclass;
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("--- lx_hybrid global static constructor test ---\n");
|
||||
|
||||
printf("--- returning from main ---\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
22
base-linux/src/test/lx_hybrid_ctors/target.mk
Normal file
22
base-linux/src/test/lx_hybrid_ctors/target.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
TARGET = test-lx_hybrid_ctors
|
||||
SRC_CC = main.cc
|
||||
LIBS = env lx_hybrid
|
||||
|
||||
EXT_OBJECTS += $(BUILD_BASE_DIR)/test/lx_hybrid_ctors/libtestlib.so
|
||||
|
||||
TESTLIB_SO = libtestlib.so
|
||||
TESTLIB_SRC_CC = testlib.cc
|
||||
|
||||
$(TARGET): libtestlib.so
|
||||
|
||||
$(TESTLIB_SO): $(TESTLIB_SRC_CC)
|
||||
$(MSG_BUILD)$(TESTLIB_SO)
|
||||
$(VERBOSE)g++ -fPIC -c $^
|
||||
$(VERBOSE)g++ -shared -Wlsoname,$(TESTLIB_SO) -o $@ $(notdir $(^:.cc=.o))
|
||||
|
||||
clean_libtestlib:
|
||||
$(VERBOSE)rm -f $(TESTLIB_SO) $(TESTLIB_SRC_CC:.cc=.o)
|
||||
|
||||
clean: clean_libtestlib
|
||||
|
||||
vpath testlib.cc $(PRG_DIR)
|
||||
24
base-linux/src/test/lx_hybrid_ctors/testlib.cc
Normal file
24
base-linux/src/test/lx_hybrid_ctors/testlib.cc
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* \brief Test if global static constructors in host shared libs get called
|
||||
* \author Christian Prochaska
|
||||
* \date 2011-11-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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 <stdio.h>
|
||||
|
||||
struct Testlib_testclass
|
||||
{
|
||||
Testlib_testclass()
|
||||
{
|
||||
printf("[init -> test-lx_hybrid_ctors] Global static constructor of host library called.\n");
|
||||
}
|
||||
};
|
||||
|
||||
Testlib_testclass testlib_testclass;
|
||||
37
base-linux/src/test/lx_hybrid_exception/main.cc
Normal file
37
base-linux/src/test/lx_hybrid_exception/main.cc
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* \brief Test if the exception mechanism works in hybrid applications
|
||||
* \author Christian Prochaska
|
||||
* \date 2011-11-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
class Test_exception { };
|
||||
|
||||
/**
|
||||
* Main program
|
||||
*/
|
||||
int main(int, char **)
|
||||
{
|
||||
printf("--- lx_hybrid exception test ---\n");
|
||||
|
||||
try {
|
||||
printf("Throwing Test_exception\n");
|
||||
throw Test_exception();
|
||||
} catch(Test_exception) {
|
||||
printf("Caught Test_exception\n");
|
||||
}
|
||||
|
||||
printf("--- returning from main ---\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
3
base-linux/src/test/lx_hybrid_exception/target.mk
Normal file
3
base-linux/src/test/lx_hybrid_exception/target.mk
Normal file
@@ -0,0 +1,3 @@
|
||||
TARGET = test-lx_hybrid_exception
|
||||
SRC_CC = main.cc
|
||||
LIBS = env lx_hybrid
|
||||
22
base-linux/src/test/sub_rm/config.h
Normal file
22
base-linux/src/test/sub_rm/config.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* \brief Linux-specific policy for sub_rm test
|
||||
* \author Norman Feske
|
||||
* \date 2011-11-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The Linux implementation of the RM service does not support attaching
|
||||
* the same sub RM session twice. This configuration enables the respective
|
||||
* error-handling test.
|
||||
*/
|
||||
enum { attach_twice_forbidden = true };
|
||||
|
||||
enum { support_attach_sub_any = false };
|
||||
|
||||
Reference in New Issue
Block a user