mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-18 23:28:29 +00:00
Imported Genode release 11.11
This commit is contained in:
committed by
Christian Helmuth
parent
6bcc9aef0e
commit
da4e1feaa5
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;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user