Move repositories to 'repos/' subdirectory

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

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

60
repos/base-linux/src/base/env/debug.cc vendored Normal file
View File

@ -0,0 +1,60 @@
/*
* \brief Linux-specific debug utilities
* \author Norman Feske
* \date 2009-05-16
*/
/*
* Copyright (C) 2009-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/*
* 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 */
}
extern "C" int get_pid() { return lx_getpid(); }

View File

@ -0,0 +1,212 @@
/*
* \brief Support for the Linux-specific environment
* \author Norman Feske
* \date 2008-12-12
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <util/arg_string.h>
#include <base/thread.h>
#include <linux_dataspace/client.h>
#include <linux_syscalls.h>
/* local includes */
#include <platform_env.h>
using namespace Genode;
/****************************************************
** Support for Platform_env_base::Rm_session_mmap **
****************************************************/
Genode::size_t
Platform_env_base::Rm_session_mmap::_dataspace_size(Dataspace_capability ds)
{
if (ds.valid())
return Dataspace_client(ds).size();
return Dataspace_capability::deref(ds)->size();
}
int Platform_env_base::Rm_session_mmap::_dataspace_fd(Dataspace_capability ds)
{
return Linux_dataspace_client(ds).fd().dst().socket;
}
bool
Platform_env_base::Rm_session_mmap::_dataspace_writable(Dataspace_capability ds)
{
return Dataspace_client(ds).writable();
}
/********************************
** Platform_env::Local_parent **
********************************/
static inline size_t get_page_size_log2() { return 12; }
Session_capability
Platform_env::Local_parent::session(Service_name const &service_name,
Session_args const &args,
Affinity const &affinity)
{
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 Expanding_parent_client::session(service_name, args, affinity);
if (size != ~0UL)
size = align_addr(size, get_page_size_log2());
Rm_session_mmap *rm = new (env()->heap())
Rm_session_mmap(true, size);
return Session_capability::local_cap(rm);
}
return Expanding_parent_client::session(service_name, args, affinity);
}
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
*/
Capability<Rm_session_mmap> rm = static_cap_cast<Rm_session_mmap>(session);
destroy(env()->heap(), Capability<Rm_session_mmap>::deref(rm));
}
Platform_env::Local_parent::Local_parent(Parent_capability parent_cap,
Emergency_ram_reserve &reserve)
: Expanding_parent_client(parent_cap, reserve)
{ }
/******************
** Platform_env **
******************/
/**
* List of Unix environment variables, initialized by the startup code
*/
extern char **lx_environ;
/**
* Read environment variable as long value
*/
static unsigned long 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;
}
static Parent_capability obtain_parent_cap()
{
long local_name = get_env_ulong("parent_local_name");
/* produce typed capability manually */
typedef Native_capability::Dst Dst;
Dst const dst(PARENT_SOCKET_HANDLE);
return reinterpret_cap_cast<Parent>(Native_capability(dst, local_name));
}
Platform_env::Local_parent &Platform_env::_parent()
{
static Local_parent local_parent(obtain_parent_cap(), *this);
return local_parent;
}
void Platform_env::reinit(Native_capability::Dst, long) { }
void Platform_env::reinit_main_thread(Rm_session_capability &) { }
Platform_env::Platform_env()
:
Platform_env_base(static_cap_cast<Ram_session>(_parent().session("Env::ram_session", "")),
static_cap_cast<Cpu_session>(_parent().session("Env::cpu_session", "")),
static_cap_cast<Pd_session> (_parent().session("Env::pd_session", ""))),
_heap(Platform_env_base::ram_session(), Platform_env_base::rm_session()),
_emergency_ram_ds(ram_session()->alloc(_emergency_ram_size()))
{
/* register TID and PID of the main thread at core */
cpu_session()->thread_id(parent()->main_thread_cap(),
lx_getpid(), lx_gettid());
}
/*****************************
** Support for IPC library **
*****************************/
namespace Genode {
Native_connection_state server_socket_pair()
{
/*
* Obtain access to Linux-specific extension of the CPU session
* interface. We can cast to the specific type because the Linux
* version of 'Platform_env' is hosting a 'Linux_cpu_client' object.
*/
Linux_cpu_session *cpu = dynamic_cast<Linux_cpu_session *>(env()->cpu_session());
if (!cpu) {
PERR("could not obtain Linux extension to CPU session interface");
struct Could_not_access_linux_cpu_session { };
throw Could_not_access_linux_cpu_session();
}
Native_connection_state ncs;
Thread_base *thread = Thread_base::myself();
if (thread) {
ncs.server_sd = cpu->server_sd(thread->cap()).dst().socket;
ncs.client_sd = cpu->client_sd(thread->cap()).dst().socket;
}
return ncs;
}
void destroy_server_socket_pair(Native_connection_state const &ncs)
{
/* close local file descriptor if it is valid */
if (ncs.server_sd != -1) lx_close(ncs.server_sd);
if (ncs.client_sd != -1) lx_close(ncs.client_sd);
}
}

View File

@ -0,0 +1,462 @@
/*
* \brief Linux-specific environment
* \author Norman Feske
* \author Christian Helmuth
* \date 2006-07-28
*/
/*
* Copyright (C) 2006-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _PLATFORM_ENV_H_
#define _PLATFORM_ENV_H_
/* Linux includes */
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
/* Genode includes */
#include <util/misc_math.h>
#include <base/heap.h>
#include <linux_cpu_session/client.h>
/* local includes (from 'base/src/base/env/') */
#include <platform_env_common.h>
namespace Genode {
struct Expanding_cpu_session_client;
class Platform_env;
}
struct Genode::Expanding_cpu_session_client
:
Upgradeable_client<Genode::Linux_cpu_session_client>
{
Expanding_cpu_session_client(Genode::Capability<Linux_cpu_session> cap)
: Upgradeable_client<Genode::Linux_cpu_session_client>(cap) { }
Thread_capability create_thread(Name const &name, addr_t utcb)
{
return retry<Cpu_session::Out_of_metadata>(
[&] () { return Linux_cpu_session_client::create_thread(name, utcb); },
[&] () { upgrade_ram(8*1024); });
}
};
namespace Genode {
/**
* Common base class of the 'Platform_env' implementations for core and
* non-core processes.
*/
class Platform_env_base : 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 &region)
{
/*
* 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();
}
};
protected:
/*
* 'Rm_session_mmap' is 'protected' because it is instantiated by
* 'Platform_env::Local_parent::session()'.
*/
/*
* On Linux, we use a local region manager session that attaches
* dataspaces via mmap to the local address space.
*/
class Rm_session_mmap : 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 &);
/**
* Reserve VM region for sub-rm dataspace
*/
addr_t _reserve_local(bool use_local_addr,
addr_t local_addr,
Genode::size_t size);
/**
* Map dataspace into local address space
*/
void *_map_local(Dataspace_capability ds,
Genode::size_t size,
addr_t offset,
bool use_local_addr,
addr_t local_addr,
bool executable,
bool overmap = false);
/**
* Determine size of dataspace
*
* For core, this function performs a local lookup of the
* 'Dataspace_component' object. For non-core programs, the
* dataspace size is determined via an RPC to core
* (calling 'Dataspace::size()').
*/
size_t _dataspace_size(Capability<Dataspace>);
/**
* Determine file descriptor of dataspace
*/
int _dataspace_fd(Capability<Dataspace>);
/**
* Determine whether dataspace is writable
*/
bool _dataspace_writable(Capability<Dataspace>);
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,
bool executable);
void detach(Local_addr local_addr);
Pager_capability add_client(Thread_capability thread) {
return Pager_capability(); }
void remove_client(Pager_capability pager) { }
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 Dataspace_capability::local_cap(this);
}
};
private:
/*******************************
** Platform-specific members **
*******************************/
Ram_session_capability _ram_session_cap;
Expanding_ram_session_client _ram_session_client;
Cpu_session_capability _cpu_session_cap;
Expanding_cpu_session_client _cpu_session_client;
Rm_session_mmap _rm_session_mmap;
Pd_session_client _pd_session_client;
public:
/**
* Constructor
*/
Platform_env_base(Ram_session_capability ram_cap,
Cpu_session_capability cpu_cap,
Pd_session_capability pd_cap)
:
_ram_session_cap(ram_cap),
_ram_session_client(_ram_session_cap),
_cpu_session_cap(cpu_cap),
_cpu_session_client(static_cap_cast<Linux_cpu_session>(cpu_cap)),
_rm_session_mmap(false),
_pd_session_client(pd_cap)
{ }
/*******************
** Env interface **
*******************/
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; }
Linux_cpu_session *cpu_session() { return &_cpu_session_client; }
Cpu_session_capability cpu_session_cap() { return _cpu_session_cap; }
Pd_session *pd_session() { return &_pd_session_client; }
};
/**
* 'Platform_env' used by all processes except for core
*/
class Platform_env : public Platform_env_base, public Emergency_ram_reserve
{
private:
/**
* 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 Expanding_parent_client
{
public:
/**********************
** Parent interface **
**********************/
Session_capability session(Service_name const &,
Session_args const &,
Affinity const & = Affinity());
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,
Emergency_ram_reserve &);
};
/**
* Return instance of parent interface
*/
Local_parent &_parent();
Heap _heap;
/*
* Emergency RAM reserve
*
* See the comment of '_fallback_sig_cap()' in 'env/env.cc'.
*/
constexpr static size_t _emergency_ram_size() { return 4*1024; }
Ram_dataspace_capability _emergency_ram_ds;
/*************************************
** Linux-specific helper functions **
*************************************/
public:
/**
* Constructor
*/
Platform_env();
/**
* Destructor
*/
~Platform_env() { _parent().exit(0); }
/*
* Support functions for implementing fork on Noux.
*
* Not supported on Linux.
*
* See the documentation in 'base/src/base/env/platform_env.h'
*/
void reinit(Native_capability::Dst, long);
void reinit_main_thread(Rm_session_capability &);
/*************************************
** Emergency_ram_reserve interface **
*************************************/
void release() { ram_session()->free(_emergency_ram_ds); }
/*******************
** Env interface **
*******************/
Parent *parent() { return &_parent(); }
Heap *heap() { return &_heap; }
};
}
#endif /* _PLATFORM_ENV_H_ */

View File

@ -0,0 +1,363 @@
/*
* \brief Implementation of Linux-specific local region manager
* \author Norman Feske
* \date 2008-10-22
*
* Under Linux, region management happens at the mercy of the Linux kernel. So,
* all we can do in user land is 1) keep track of regions and (managed)
* dataspaces and 2) get the kernel to manage VM regions as we intent.
*
* The kernel sets up mappings for the binary on execve(), which are text and
* data segments, the context area and special regions (stack, vdso, vsyscall).
* Later mappings are done by the Genode program itself, which knows nothing
* about these initial mappings. Therefore, most mmap() operations are _soft_
* to detect region conflicts with existing mappings or let the kernel find
* some empty VM area (as core does on other platforms). The only _hard_
* overmaps happen on attachment and population of managed dataspaces. Mapped,
* but not populated dataspaces are "holes" in the Linux VM space represented
* by PROT_NONE mappings (see _reserve_local()).
*
* The context area is a managed dataspace as on other platforms, which is
* created and attached during program launch. The managed dataspace replaces
* the inital reserved area, which is therefore flushed beforehand. Hybrid
* programs have no context area.
*
* Note, we do not support nesting of managed dataspaces.
*/
/*
* Copyright (C) 2008-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/thread.h>
#include <linux_dataspace/client.h>
#include <linux_syscalls.h>
#include <context_area.h>
/* local includes */
#include <platform_env.h>
using namespace Genode;
static bool is_sub_rm_session(Dataspace_capability ds)
{
if (ds.valid())
return false;
return Dataspace_capability::deref(ds) != 0;
}
addr_t Platform_env_base::Rm_session_mmap::_reserve_local(bool use_local_addr,
addr_t local_addr,
Genode::size_t size)
{
/* special handling for context area */
if (use_local_addr
&& local_addr == Native_config::context_area_virtual_base()
&& size == Native_config::context_area_virtual_size()) {
/*
* On the first request to reserve the context area, we flush the
* initial mapping preserved in linker script and apply the actual
* reservation. Subsequent requests are just ignored.
*/
static struct Context
{
Context()
{
flush_context_area();
reserve_context_area();
}
} inst;
return local_addr;
}
int const flags = MAP_ANONYMOUS | MAP_PRIVATE;
int const prot = PROT_NONE;
void * const addr_in = use_local_addr ? (void *)local_addr : 0;
void * const addr_out = lx_mmap(addr_in, size, prot, flags, -1, 0);
/* reserve at local address failed - unmap incorrect mapping */
if (use_local_addr && addr_in != addr_out)
lx_munmap((void *)addr_out, size);
if ((use_local_addr && addr_in != addr_out)
|| (((long)addr_out < 0) && ((long)addr_out > -4095))) {
PERR("_reserve_local: lx_mmap failed (addr_in=%p,addr_out=%p/%ld)",
addr_in, addr_out, (long)addr_out);
throw Rm_session::Region_conflict();
}
return (addr_t) addr_out;
}
void *
Platform_env_base::Rm_session_mmap::_map_local(Dataspace_capability ds,
Genode::size_t size,
addr_t offset,
bool use_local_addr,
addr_t local_addr,
bool executable,
bool overmap)
{
int const fd = _dataspace_fd(ds);
bool const writable = _dataspace_writable(ds);
int const flags = MAP_SHARED | (overmap ? MAP_FIXED : 0);
int const prot = PROT_READ
| (writable ? PROT_WRITE : 0)
| (executable ? PROT_EXEC : 0);
void * const addr_in = use_local_addr ? (void*)local_addr : 0;
void * const addr_out = lx_mmap(addr_in, size, prot, flags, fd, offset);
/*
* We can close the file after calling mmap. The Linux kernel will still
* keep the file mapped. By immediately closing the file descriptor, we
* won't need to keep track of dataspace file descriptors within the
* process.
*/
lx_close(fd);
/* attach at local address failed - unmap incorrect mapping */
if (use_local_addr && addr_in != addr_out)
lx_munmap((void *)addr_out, size);
if ((use_local_addr && addr_in != addr_out)
|| (((long)addr_out < 0) && ((long)addr_out > -4095))) {
PERR("_map_local: lx_mmap failed (addr_in=%p,addr_out=%p/%ld) overmap=%d",
addr_in, addr_out, (long)addr_out, overmap);
throw Rm_session::Region_conflict();
}
return addr_out;
}
void Platform_env::Rm_session_mmap::_add_to_rmap(Region const &region)
{
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,
bool executable)
{
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 attachment offset to the local base
* and map it. We have to enforce the mapping via the 'overmap'
* argument as the region was reserved by a PROT_NONE mapping.
*/
if (_is_attached())
_map_local(ds, region_size, offset, true, _base + (addr_t)local_addr, executable, true);
return (void *)local_addr;
} else {
if (is_sub_rm_session(ds)) {
Dataspace *ds_if = Dataspace_capability::deref(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();
}
/*
* Reserve local address range that can hold the entire sub RM
* session.
*/
rm->_base = _reserve_local(use_local_addr, local_addr, region_size);
_add_to_rmap(Region(rm->_base, offset, ds, 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 and map
* each of them.
*/
for (int i = 0; i < Region_map::MAX_REGIONS; i++) {
Region region = rm->_rmap.region(i);
if (!region.used())
continue;
/*
* We have to enforce the mapping via the 'overmap' argument as
* the region was reserved by a PROT_NONE mapping.
*/
_map_local(region.dataspace(), region.size(), region.offset(),
true, rm->_base + region.start() + region.offset(),
executable, true);
}
return rm->_base;
} else {
/*
* Case 1
*
* Boring, a plain dataspace is attached to a root RM session.
* Note, we do not overmap.
*/
void *addr = _map_local(ds, region_size, offset, use_local_addr,
local_addr, executable);
_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_munmap((void *)((addr_t)local_addr + _base), region.size());
_reserve_local(true, (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 = Dataspace_capability::deref(region.dataspace());
Rm_session_mmap *rm = dynamic_cast<Rm_session_mmap *>(ds_if);
if (rm)
rm->_base = 0;
}
}