Consolidate RM service into PD session
This patch integrates three region maps into each PD session to reduce the session overhead and to simplify the PD creation procedure. Please refer to the issue cited below for an elaborative discussion. Note the API change: With this patch, the semantics of core's RM service have changed. Now, the service is merely a tool for creating and destroying managed dataspaces, which are rarely needed. Regular components no longer need a RM session. For this reason, the corresponding argument for the 'Process' and 'Child' constructors has been removed. The former interface of the 'Rm_session' is not named 'Region_map'. As a minor refinement, the 'Fault_type' enum values are now part of the 'Region_map::State' struct. Issue #1938
This commit is contained in:
committed by
Christian Helmuth
parent
e20bbe7002
commit
511acad507
@@ -16,12 +16,13 @@ SRC_CC += child/child.cc
|
||||
SRC_CC += process/process.cc
|
||||
SRC_CC += elf/elf_binary.cc
|
||||
SRC_CC += lock/lock.cc
|
||||
SRC_CC += env/rm_session_mmap.cc env/debug.cc
|
||||
SRC_CC += env/region_map_mmap.cc env/debug.cc
|
||||
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
|
||||
SRC_CC += server/server.cc server/common.cc
|
||||
SRC_CC += thread/trace.cc thread/thread_env.cc thread/stack_allocator.cc
|
||||
SRC_CC += irq/platform.cc
|
||||
SRC_CC += sleep.cc
|
||||
SRC_CC += region_map_client.cc
|
||||
SRC_CC += rm_session_client.cc
|
||||
SRC_CC += entrypoint/entrypoint.cc
|
||||
SRC_CC += component/component.cc
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
build "core init test/rm_session_mmap drivers/timer test/signal"
|
||||
build "core init test/region_map_mmap drivers/timer test/signal"
|
||||
|
||||
create_boot_directory
|
||||
|
||||
@@ -20,7 +20,7 @@ install_config {
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="test-rm_session_mmap">
|
||||
<start name="test-region_map_mmap">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
</start>
|
||||
|
||||
@@ -34,7 +34,7 @@ install_config {
|
||||
</start>
|
||||
</config>}
|
||||
|
||||
build_boot_image "core init test-rm_session_mmap timer test-signal"
|
||||
build_boot_image "core init test-region_map_mmap timer test-signal"
|
||||
|
||||
run_genode_until forever
|
||||
|
||||
36
repos/base-linux/src/base/env/platform_env.cc
vendored
36
repos/base-linux/src/base/env/platform_env.cc
vendored
@@ -29,7 +29,7 @@ using namespace Genode;
|
||||
****************************************************/
|
||||
|
||||
Genode::size_t
|
||||
Platform_env_base::Rm_session_mmap::_dataspace_size(Dataspace_capability ds)
|
||||
Platform_env_base::Region_map_mmap::_dataspace_size(Dataspace_capability ds)
|
||||
{
|
||||
if (ds.valid())
|
||||
return Dataspace_client(ds).size();
|
||||
@@ -38,19 +38,20 @@ Platform_env_base::Rm_session_mmap::_dataspace_size(Dataspace_capability ds)
|
||||
}
|
||||
|
||||
|
||||
int Platform_env_base::Rm_session_mmap::_dataspace_fd(Dataspace_capability ds)
|
||||
int Platform_env_base::Region_map_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)
|
||||
Platform_env_base::Region_map_mmap::_dataspace_writable(Dataspace_capability ds)
|
||||
{
|
||||
return Dataspace_client(ds).writable();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************
|
||||
** Platform_env::Local_parent **
|
||||
********************************/
|
||||
@@ -63,22 +64,11 @@ 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)
|
||||
if (strcmp(service_name.string(), Rm_session::service_name()) == 0)
|
||||
{
|
||||
size_t size =
|
||||
Arg_string::find_arg(args.string(),"size")
|
||||
.ulong_value(~0);
|
||||
Local_rm_session *session = new (_alloc) Local_rm_session(_alloc);
|
||||
|
||||
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 (_alloc) Rm_session_mmap(true, size);
|
||||
|
||||
return Local_capability<Session>::local_cap(rm);
|
||||
return Local_capability<Session>::local_cap(session);
|
||||
}
|
||||
|
||||
return Expanding_parent_client::session(service_name, args, affinity);
|
||||
@@ -98,9 +88,9 @@ void Platform_env::Local_parent::close(Session_capability session)
|
||||
/*
|
||||
* Detect capability to local RM session
|
||||
*/
|
||||
Capability<Rm_session_mmap> rm = static_cap_cast<Rm_session_mmap>(session);
|
||||
Capability<Rm_session> rm = static_cap_cast<Rm_session>(session);
|
||||
|
||||
destroy(env()->heap(), Local_capability<Rm_session_mmap>::deref(rm));
|
||||
destroy(_alloc, Local_capability<Rm_session>::deref(rm));
|
||||
}
|
||||
|
||||
|
||||
@@ -162,11 +152,15 @@ Platform_env::Platform_env()
|
||||
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()),
|
||||
_stack_area(*parent(), *rm_session()),
|
||||
_emergency_ram_ds(ram_session()->alloc(_emergency_ram_size()))
|
||||
{
|
||||
/* attach stack area to local address space */
|
||||
_local_pd_session._address_space.attach_at(_local_pd_session._stack_area.dataspace(),
|
||||
stack_area_virtual_base(),
|
||||
stack_area_virtual_size());
|
||||
|
||||
env_stack_area_region_map = &_local_pd_session._stack_area;
|
||||
env_stack_area_ram_session = ram_session();
|
||||
env_stack_area_rm_session = &_stack_area;
|
||||
|
||||
/* register TID and PID of the main thread at core */
|
||||
Linux_native_cpu_client native_cpu(cpu_session()->native_cpu());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Implementation of Linux-specific local region manager
|
||||
* \brief Implementation of Linux-specific local region map
|
||||
* \author Norman Feske
|
||||
* \date 2008-10-22
|
||||
*
|
||||
@@ -54,7 +54,7 @@ static bool is_sub_rm_session(Dataspace_capability ds)
|
||||
}
|
||||
|
||||
|
||||
addr_t Platform_env_base::Rm_session_mmap::_reserve_local(bool use_local_addr,
|
||||
addr_t Platform_env_base::Region_map_mmap::_reserve_local(bool use_local_addr,
|
||||
addr_t local_addr,
|
||||
Genode::size_t size)
|
||||
{
|
||||
@@ -94,7 +94,7 @@ addr_t Platform_env_base::Rm_session_mmap::_reserve_local(bool use_loc
|
||||
|| (((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();
|
||||
throw Region_map::Region_conflict();
|
||||
}
|
||||
|
||||
return (addr_t) addr_out;
|
||||
@@ -102,7 +102,7 @@ addr_t Platform_env_base::Rm_session_mmap::_reserve_local(bool use_loc
|
||||
|
||||
|
||||
void *
|
||||
Platform_env_base::Rm_session_mmap::_map_local(Dataspace_capability ds,
|
||||
Platform_env_base::Region_map_mmap::_map_local(Dataspace_capability ds,
|
||||
Genode::size_t size,
|
||||
addr_t offset,
|
||||
bool use_local_addr,
|
||||
@@ -136,14 +136,14 @@ Platform_env_base::Rm_session_mmap::_map_local(Dataspace_capability ds,
|
||||
|| (((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();
|
||||
throw Region_map::Region_conflict();
|
||||
}
|
||||
|
||||
return addr_out;
|
||||
}
|
||||
|
||||
|
||||
void Platform_env::Rm_session_mmap::_add_to_rmap(Region const ®ion)
|
||||
void Platform_env::Region_map_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");
|
||||
@@ -152,23 +152,23 @@ void Platform_env::Rm_session_mmap::_add_to_rmap(Region const ®ion)
|
||||
}
|
||||
|
||||
|
||||
Rm_session::Local_addr
|
||||
Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
|
||||
Region_map::Local_addr
|
||||
Platform_env::Region_map_mmap::attach(Dataspace_capability ds,
|
||||
size_t size, off_t offset,
|
||||
bool use_local_addr,
|
||||
Rm_session::Local_addr local_addr,
|
||||
Region_map::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");
|
||||
PERR("Region_map_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");
|
||||
PERR("Region_map_mmap::attach: negative offset not supported\n");
|
||||
throw Region_conflict();
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
|
||||
* Case 4
|
||||
*/
|
||||
if (is_sub_rm_session(ds)) {
|
||||
PERR("Rm_session_mmap::attach: nesting sub RM sessions is not supported");
|
||||
PERR("Region_map_mmap::attach: nesting sub RM sessions is not supported");
|
||||
throw Invalid_dataspace();
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
|
||||
* sub RM session
|
||||
*/
|
||||
if (region_size + (addr_t)local_addr > _size) {
|
||||
PERR("Rm_session_mmap::attach: dataspace does not fit in sub RM session");
|
||||
PERR("Region_map_mmap::attach: dataspace does not fit in sub RM session");
|
||||
throw Region_conflict();
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
|
||||
|
||||
Dataspace *ds_if = Local_capability<Dataspace>::deref(ds);
|
||||
|
||||
Rm_session_mmap *rm = dynamic_cast<Rm_session_mmap *>(ds_if);
|
||||
Region_map_mmap *rm = dynamic_cast<Region_map_mmap *>(ds_if);
|
||||
|
||||
if (!rm)
|
||||
throw Invalid_dataspace();
|
||||
@@ -245,7 +245,7 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
|
||||
* 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");
|
||||
PERR("Region_map_mmap::attach: mapping a sub RM session twice is not supported");
|
||||
throw Out_of_metadata();
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
|
||||
* been populated with dataspaces. Go through all regions and map
|
||||
* each of them.
|
||||
*/
|
||||
for (int i = 0; i < Region_map::MAX_REGIONS; i++) {
|
||||
for (int i = 0; i < Region_registry::MAX_REGIONS; i++) {
|
||||
Region region = rm->_rmap.region(i);
|
||||
if (!region.used())
|
||||
continue;
|
||||
@@ -299,7 +299,7 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
|
||||
}
|
||||
|
||||
|
||||
void Platform_env::Rm_session_mmap::detach(Rm_session::Local_addr local_addr)
|
||||
void Platform_env::Region_map_mmap::detach(Region_map::Local_addr local_addr)
|
||||
{
|
||||
Lock::Guard lock_guard(_lock);
|
||||
|
||||
@@ -357,7 +357,7 @@ void Platform_env::Rm_session_mmap::detach(Rm_session::Local_addr local_addr)
|
||||
if (is_sub_rm_session(region.dataspace())) {
|
||||
|
||||
Dataspace *ds_if = Local_capability<Dataspace>::deref(region.dataspace());
|
||||
Rm_session_mmap *rm = dynamic_cast<Rm_session_mmap *>(ds_if);
|
||||
Region_map_mmap *rm = dynamic_cast<Region_map_mmap *>(ds_if);
|
||||
if (rm)
|
||||
rm->_base = 0;
|
||||
}
|
||||
@@ -56,13 +56,11 @@ Process::Process(Dataspace_capability elf_data_ds_cap,
|
||||
Pd_session_capability pd_session_cap,
|
||||
Ram_session_capability ram_session_cap,
|
||||
Cpu_session_capability cpu_session_cap,
|
||||
Rm_session_capability rm_session_cap,
|
||||
Parent_capability parent_cap,
|
||||
char const *name)
|
||||
:
|
||||
_pd_session_client(pd_session_cap),
|
||||
_cpu_session_client(cpu_session_cap),
|
||||
_rm_session_client(Rm_session_capability())
|
||||
_cpu_session_client(cpu_session_cap)
|
||||
{
|
||||
/* check for dynamic program header */
|
||||
if (_check_dynamic_elf(elf_data_ds_cap)) {
|
||||
|
||||
77
repos/base-linux/src/base/region_map_client.cc
Normal file
77
repos/base-linux/src/base/region_map_client.cc
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* \brief Pseudo region map client stub targeting the process-local implementation
|
||||
* \author Norman Feske
|
||||
* \date 2011-11-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2016 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 <region_map/client.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/local_capability.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/**
|
||||
* Return pointer to locally implemented region map
|
||||
*
|
||||
* \throw Local_interface::Non_local_capability
|
||||
*/
|
||||
static Region_map *_local(Capability<Region_map> cap)
|
||||
{
|
||||
return Local_capability<Region_map>::deref(cap);
|
||||
}
|
||||
|
||||
|
||||
Region_map_client::Region_map_client(Capability<Region_map> session)
|
||||
: Rpc_client<Region_map>(session) { }
|
||||
|
||||
|
||||
Region_map::Local_addr
|
||||
Region_map_client::attach(Dataspace_capability ds, size_t size,
|
||||
off_t offset, bool use_local_addr,
|
||||
Region_map::Local_addr local_addr,
|
||||
bool executable)
|
||||
{
|
||||
return _local(*this)->attach(ds, size, offset, use_local_addr,
|
||||
local_addr, executable);
|
||||
}
|
||||
|
||||
|
||||
void Region_map_client::detach(Local_addr local_addr) {
|
||||
return _local(*this)->detach(local_addr); }
|
||||
|
||||
|
||||
Pager_capability Region_map_client::add_client(Thread_capability thread) {
|
||||
return _local(*this)->add_client(thread); }
|
||||
|
||||
|
||||
void Region_map_client::remove_client(Pager_capability pager) {
|
||||
_local(*this)->remove_client(pager); }
|
||||
|
||||
|
||||
void Region_map_client::fault_handler(Signal_context_capability /*handler*/)
|
||||
{
|
||||
/*
|
||||
* On Linux, page faults are never reflected to the user land. They
|
||||
* are always handled by the kernel. If a segmentation fault
|
||||
* occurs, this condition is being reflected as a CPU exception
|
||||
* to the handler registered via 'Cpu_session::exception_handler'.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
Region_map::State Region_map_client::state() { return _local(*this)->state(); }
|
||||
|
||||
|
||||
Dataspace_capability Region_map_client::dataspace() {
|
||||
return _local(*this)->dataspace(); }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Pseudo RM-session client stub targeting the process-local RM service
|
||||
* \brief Pseudo RM session client stub targeting the process-local implementation
|
||||
* \author Norman Feske
|
||||
* \date 2011-11-21
|
||||
*/
|
||||
@@ -25,52 +25,19 @@ using namespace Genode;
|
||||
*
|
||||
* \throw Local_interface::Non_local_capability
|
||||
*/
|
||||
static Rm_session *_local(Rm_session_capability cap)
|
||||
static Rm_session *_local(Capability<Rm_session> cap)
|
||||
{
|
||||
return Local_capability<Rm_session>::deref(cap);
|
||||
}
|
||||
|
||||
|
||||
Rm_session_client::Rm_session_client(Rm_session_capability session)
|
||||
Rm_session_client::Rm_session_client(Capability<Rm_session> session)
|
||||
: Rpc_client<Rm_session>(session) { }
|
||||
|
||||
|
||||
Rm_session::Local_addr
|
||||
Rm_session_client::attach(Dataspace_capability ds, size_t size,
|
||||
off_t offset, bool use_local_addr,
|
||||
Rm_session::Local_addr local_addr,
|
||||
bool executable)
|
||||
{
|
||||
return _local(*this)->attach(ds, size, offset, use_local_addr,
|
||||
local_addr, executable);
|
||||
}
|
||||
|
||||
void Rm_session_client::detach(Local_addr local_addr) {
|
||||
return _local(*this)->detach(local_addr); }
|
||||
Capability<Region_map> Rm_session_client::create(size_t size) {
|
||||
return _local(*this)->create(size); }
|
||||
|
||||
|
||||
Pager_capability Rm_session_client::add_client(Thread_capability thread) {
|
||||
return _local(*this)->add_client(thread); }
|
||||
|
||||
|
||||
void Rm_session_client::remove_client(Pager_capability pager) {
|
||||
_local(*this)->remove_client(pager); }
|
||||
|
||||
|
||||
void Rm_session_client::fault_handler(Signal_context_capability /*handler*/)
|
||||
{
|
||||
/*
|
||||
* On Linux, page faults are never reflected to RM clients. They
|
||||
* are always handled by the kernel. If a segmentation fault
|
||||
* occurs, this condition is being reflected as a CPU exception
|
||||
* to the handler registered via 'Cpu_session::exception_handler'.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
Rm_session::State Rm_session_client::state() { return _local(*this)->state(); }
|
||||
|
||||
|
||||
Dataspace_capability Rm_session_client::dataspace() {
|
||||
return _local(*this)->dataspace(); }
|
||||
|
||||
void Rm_session_client::destroy(Capability<Region_map> cap) {
|
||||
_local(*this)->destroy(cap); }
|
||||
|
||||
74
repos/base-linux/src/core/include/region_map_component.h
Normal file
74
repos/base-linux/src/core/include/region_map_component.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the region-map interface
|
||||
* \author Christian Helmuth
|
||||
* \date 2006-07-17
|
||||
*
|
||||
* Dummies for Linux platform
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _CORE__INCLUDE__REGION_MAP_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__REGION_MAP_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/list.h>
|
||||
#include <base/allocator.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <region_map/region_map.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <pager.h>
|
||||
|
||||
namespace Genode {
|
||||
struct Rm_client;
|
||||
struct Rm_member;
|
||||
class Region_map_component;
|
||||
}
|
||||
|
||||
|
||||
class Genode::Region_map_component : public Rpc_object<Region_map>,
|
||||
public List<Region_map_component>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
struct Rm_dataspace_component { void sub_rm(Native_capability) { } };
|
||||
|
||||
public:
|
||||
|
||||
Region_map_component(Rpc_entrypoint &, Allocator &, Pager_entrypoint &,
|
||||
addr_t, size_t) { }
|
||||
|
||||
void upgrade_ram_quota(size_t ram_quota) { }
|
||||
|
||||
Local_addr attach(Dataspace_capability, size_t, off_t, bool, Local_addr, bool) {
|
||||
return (addr_t)0; }
|
||||
|
||||
void detach(Local_addr) { }
|
||||
|
||||
Pager_capability add_client(Thread_capability) {
|
||||
return Pager_capability(); }
|
||||
|
||||
void remove_client(Pager_capability) { }
|
||||
|
||||
void fault_handler(Signal_context_capability) { }
|
||||
|
||||
State state() { return State(); }
|
||||
|
||||
Dataspace_capability dataspace() { return Dataspace_capability(); }
|
||||
|
||||
Rm_dataspace_component *dataspace_component() { return 0; }
|
||||
};
|
||||
|
||||
|
||||
struct Genode::Rm_member { Region_map_component *member_rm() { return 0; } };
|
||||
|
||||
|
||||
struct Genode::Rm_client : Pager_object, Rm_member { };
|
||||
|
||||
#endif /* _CORE__INCLUDE__REGION_MAP_COMPONENT_H_ */
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the RM session interface
|
||||
* \author Christian Helmuth
|
||||
* \date 2006-07-17
|
||||
*
|
||||
* Dummies for Linux platform
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _CORE__INCLUDE__RM_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__RM_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <rm_session/rm_session.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <pager.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Rm_client;
|
||||
|
||||
class Rm_session_component : public Rpc_object<Rm_session>
|
||||
{
|
||||
private:
|
||||
|
||||
class Rm_dataspace_component {
|
||||
|
||||
public:
|
||||
|
||||
void sub_rm_session(Native_capability _cap) { }
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
Rm_session_component(Rpc_entrypoint *ds_ep,
|
||||
Rpc_entrypoint *thread_ep,
|
||||
Rpc_entrypoint *session_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, bool) {
|
||||
return (addr_t)0; }
|
||||
|
||||
void detach(Local_addr) { }
|
||||
|
||||
Pager_capability add_client(Thread_capability) {
|
||||
return Pager_capability(); }
|
||||
|
||||
void remove_client(Pager_capability) { }
|
||||
|
||||
void fault_handler(Signal_context_capability) { }
|
||||
|
||||
State state() { return State(); }
|
||||
|
||||
Dataspace_capability dataspace() { return Dataspace_capability(); }
|
||||
|
||||
Rm_dataspace_component *dataspace_component() { return 0; }
|
||||
};
|
||||
|
||||
struct Rm_member { Rm_session_component *member_rm_session() { return 0; } };
|
||||
struct Rm_client : Pager_object, Rm_member { };
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__RM_SESSION_COMPONENT_H_ */
|
||||
@@ -177,18 +177,18 @@ namespace Genode {
|
||||
|
||||
|
||||
/****************************************************
|
||||
** Support for Platform_env_base::Rm_session_mmap **
|
||||
** Support for Platform_env_base::Region_map_mmap **
|
||||
****************************************************/
|
||||
|
||||
Genode::size_t
|
||||
Platform_env_base::Rm_session_mmap::_dataspace_size(Capability<Dataspace> ds_cap)
|
||||
Platform_env_base::Region_map_mmap::_dataspace_size(Capability<Dataspace> ds_cap)
|
||||
{
|
||||
if (!ds_cap.valid())
|
||||
return Local_capability<Dataspace>::deref(ds_cap)->size();
|
||||
|
||||
/* use RPC if called from a different thread */
|
||||
if (!core_env()->entrypoint()->is_myself()) {
|
||||
/* release Rm_session_mmap::_lock during RPC */
|
||||
/* release Region_map_mmap::_lock during RPC */
|
||||
_lock.unlock();
|
||||
Genode::size_t size = Dataspace_client(ds_cap).size();
|
||||
_lock.lock();
|
||||
@@ -201,10 +201,10 @@ Platform_env_base::Rm_session_mmap::_dataspace_size(Capability<Dataspace> ds_cap
|
||||
}
|
||||
|
||||
|
||||
int Platform_env_base::Rm_session_mmap::_dataspace_fd(Capability<Dataspace> ds_cap)
|
||||
int Platform_env_base::Region_map_mmap::_dataspace_fd(Capability<Dataspace> ds_cap)
|
||||
{
|
||||
if (!core_env()->entrypoint()->is_myself()) {
|
||||
/* release Rm_session_mmap::_lock during RPC */
|
||||
/* release Region_map_mmap::_lock during RPC */
|
||||
_lock.unlock();
|
||||
int socket = Linux_dataspace_client(ds_cap).fd().dst().socket;
|
||||
_lock.lock();
|
||||
@@ -215,7 +215,7 @@ int Platform_env_base::Rm_session_mmap::_dataspace_fd(Capability<Dataspace> ds_c
|
||||
|
||||
/*
|
||||
* Return a duplicate of the dataspace file descriptor, which will be freed
|
||||
* immediately after mmap'ing the file (see 'Rm_session_mmap').
|
||||
* immediately after mmap'ing the file (see 'Region_map_mmap').
|
||||
*
|
||||
* Handing out the original file descriptor would result in the premature
|
||||
* release of the descriptor. So the descriptor could be reused (i.e., as a
|
||||
@@ -227,10 +227,10 @@ int Platform_env_base::Rm_session_mmap::_dataspace_fd(Capability<Dataspace> ds_c
|
||||
}
|
||||
|
||||
|
||||
bool Platform_env_base::Rm_session_mmap::_dataspace_writable(Dataspace_capability ds_cap)
|
||||
bool Platform_env_base::Region_map_mmap::_dataspace_writable(Dataspace_capability ds_cap)
|
||||
{
|
||||
if (!core_env()->entrypoint()->is_myself()) {
|
||||
/* release Rm_session_mmap::_lock during RPC */
|
||||
/* release Region_map_mmap::_lock during RPC */
|
||||
_lock.unlock();
|
||||
bool writable = Dataspace_client(ds_cap).writable();
|
||||
_lock.lock();
|
||||
|
||||
@@ -19,21 +19,22 @@
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack_area.h>
|
||||
#include <base/internal/platform_env_common.h>
|
||||
|
||||
|
||||
/**
|
||||
* Region-manager session for allocating stacks
|
||||
* Region-map for allocating stacks
|
||||
*
|
||||
* This class corresponds to the managed dataspace that is normally used for
|
||||
* organizing stacks within the stack. It "emulates" the sub address space by
|
||||
* adjusting the local address argument to 'attach' with the offset of the
|
||||
* stack area.
|
||||
*/
|
||||
class Stack_area_rm_session : public Genode::Rm_session
|
||||
class Stack_area_region_map : public Genode::Region_map
|
||||
{
|
||||
public:
|
||||
|
||||
Stack_area_rm_session()
|
||||
Stack_area_region_map()
|
||||
{
|
||||
flush_stack_area();
|
||||
reserve_stack_area();
|
||||
@@ -105,13 +106,13 @@ class Stack_area_ram_session : public Genode::Ram_session
|
||||
*/
|
||||
namespace Genode {
|
||||
|
||||
Rm_session *env_stack_area_rm_session;
|
||||
Region_map *env_stack_area_region_map;
|
||||
Ram_session *env_stack_area_ram_session;
|
||||
|
||||
void init_stack_area()
|
||||
{
|
||||
static Stack_area_rm_session rm_inst;
|
||||
env_stack_area_rm_session = &rm_inst;
|
||||
static Stack_area_region_map rm_inst;
|
||||
env_stack_area_region_map = &rm_inst;
|
||||
|
||||
static Stack_area_ram_session ram_inst;
|
||||
env_stack_area_ram_session = &ram_inst;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
namespace Genode {
|
||||
struct Expanding_cpu_session_client;
|
||||
class Platform_env_base;
|
||||
class Platform_env;
|
||||
}
|
||||
|
||||
@@ -53,418 +54,460 @@ struct Genode::Expanding_cpu_session_client
|
||||
};
|
||||
|
||||
|
||||
namespace Genode {
|
||||
/**
|
||||
* Common base class of the 'Platform_env' implementations for core and
|
||||
* non-core processes.
|
||||
*/
|
||||
class Genode::Platform_env_base : public Env
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Common base class of the 'Platform_env' implementations for core and
|
||||
* non-core processes.
|
||||
*/
|
||||
class Platform_env_base : public Env
|
||||
{
|
||||
private:
|
||||
/**************************
|
||||
** Local region manager **
|
||||
**************************/
|
||||
|
||||
/**************************
|
||||
** Local region manager **
|
||||
**************************/
|
||||
class Region
|
||||
{
|
||||
private:
|
||||
|
||||
class Region
|
||||
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_registry
|
||||
{
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
* 'Region_map_mmap' is 'protected' because it is instantiated by
|
||||
* 'Platform_env::Local_parent::session()'.
|
||||
*/
|
||||
|
||||
/*
|
||||
* On Linux, we use a locally implemented region map that attaches
|
||||
* dataspaces via mmap to the local address space.
|
||||
*/
|
||||
class Region_map_mmap : public Region_map,
|
||||
public Dataspace
|
||||
{
|
||||
private:
|
||||
|
||||
Lock _lock; /* protect '_rmap' */
|
||||
Region_registry _rmap;
|
||||
bool const _sub_rm; /* false if region map 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
|
||||
* stack 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:
|
||||
|
||||
Region_map_mmap(bool sub_rm, size_t size = ~0)
|
||||
: _sub_rm(sub_rm), _size(size), _base(0) { }
|
||||
|
||||
~Region_map_mmap()
|
||||
{
|
||||
/* detach sub RM session when destructed */
|
||||
if (_sub_rm && _is_attached())
|
||||
env()->rm_session()->detach((void *)_base);
|
||||
}
|
||||
|
||||
|
||||
/**************************
|
||||
** Region map 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 'Region_map_mmap::attach'. It is not a
|
||||
* real capability.
|
||||
*/
|
||||
Dataspace_capability dataspace() {
|
||||
return Local_capability<Dataspace>::local_cap(this); }
|
||||
};
|
||||
|
||||
struct Local_rm_session : Genode::Rm_session
|
||||
{
|
||||
Genode::Allocator &md_alloc;
|
||||
|
||||
Local_rm_session(Genode::Allocator &md_alloc) : md_alloc(md_alloc) { }
|
||||
|
||||
Capability<Region_map> create(size_t size)
|
||||
{
|
||||
private:
|
||||
Region_map *rm = new (md_alloc) Region_map_mmap(true, size);
|
||||
return Local_capability<Region_map>::local_cap(rm);
|
||||
}
|
||||
|
||||
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
|
||||
void destroy(Capability<Region_map> cap)
|
||||
{
|
||||
public:
|
||||
Region_map *rm = Local_capability<Region_map>::deref(cap);
|
||||
Genode::destroy(md_alloc, rm);
|
||||
}
|
||||
};
|
||||
|
||||
enum { MAX_REGIONS = 4096 };
|
||||
struct Local_pd_session : Pd_session_client
|
||||
{
|
||||
Region_map_mmap _address_space { false };
|
||||
Region_map_mmap _stack_area { true, stack_area_virtual_size() };
|
||||
Region_map_mmap _linker_area { true, Pd_session::LINKER_AREA_SIZE };
|
||||
|
||||
private:
|
||||
Local_pd_session(Pd_session_capability pd) : Pd_session_client(pd) { }
|
||||
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
Capability<Region_map> address_space()
|
||||
{
|
||||
private:
|
||||
return Local_capability<Region_map>::local_cap(&_address_space);
|
||||
}
|
||||
|
||||
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
|
||||
* stack 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 Local_capability<Dataspace>::local_cap(this); }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
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_capability _pd_session_cap;
|
||||
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(cpu_cap),
|
||||
_rm_session_mmap(false),
|
||||
_pd_session_cap(pd_cap),
|
||||
_pd_session_client(_pd_session_cap)
|
||||
{ }
|
||||
|
||||
|
||||
/*******************
|
||||
** Env interface **
|
||||
*******************/
|
||||
|
||||
Ram_session *ram_session() override { return &_ram_session_client; }
|
||||
Ram_session_capability ram_session_cap() override { return _ram_session_cap; }
|
||||
Rm_session *rm_session() override { return &_rm_session_mmap; }
|
||||
Cpu_session *cpu_session() override { return &_cpu_session_client; }
|
||||
Cpu_session_capability cpu_session_cap() override { return _cpu_session_cap; }
|
||||
Pd_session *pd_session() override { return &_pd_session_client; }
|
||||
Pd_session_capability pd_session_cap() override { return _pd_session_cap; }
|
||||
|
||||
/*
|
||||
* Support functions for implementing fork on Noux.
|
||||
*
|
||||
* Not supported on Linux.
|
||||
*/
|
||||
void reinit(Native_capability::Dst, long) override { }
|
||||
void reinit_main_thread(Rm_session_capability &) override { }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* '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
|
||||
Capability<Region_map> stack_area()
|
||||
{
|
||||
private:
|
||||
return Local_capability<Region_map>::local_cap(&_stack_area);
|
||||
}
|
||||
|
||||
Allocator &_alloc;
|
||||
Capability<Region_map> linker_area()
|
||||
{
|
||||
return Local_capability<Region_map>::local_cap(&_linker_area);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
private:
|
||||
|
||||
/**********************
|
||||
** Parent interface **
|
||||
**********************/
|
||||
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;
|
||||
Region_map_mmap _region_map_mmap;
|
||||
Pd_session_capability _pd_session_cap;
|
||||
|
||||
Session_capability session(Service_name const &,
|
||||
Session_args const &,
|
||||
Affinity const & = Affinity());
|
||||
void close(Session_capability);
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param parent_cap real parent capability used to
|
||||
* promote requests to non-local
|
||||
* services
|
||||
*/
|
||||
Local_parent(Parent_capability parent_cap,
|
||||
Emergency_ram_reserve &,
|
||||
Allocator &);
|
||||
};
|
||||
/*
|
||||
* The '_local_pd_session' is protected because it is needed by
|
||||
* 'Platform_env' to initialize the stack area. This must not happen
|
||||
* in 'Platform_env_base' because the procedure differs between
|
||||
* core and non-core components.
|
||||
*/
|
||||
Local_pd_session _local_pd_session { _pd_session_cap };
|
||||
|
||||
/**
|
||||
* Return instance of parent interface
|
||||
*/
|
||||
Local_parent &_parent();
|
||||
public:
|
||||
|
||||
Heap _heap;
|
||||
|
||||
/*
|
||||
* The '_heap' must be initialized before the '_stack_area'
|
||||
* because the 'Local_parent' performs a dynamic memory allocation
|
||||
* due to the creation of the stack area's sub-RM session.
|
||||
*/
|
||||
Attached_stack_area _stack_area;
|
||||
|
||||
/*
|
||||
* Emergency RAM reserve
|
||||
*
|
||||
* See the comment of '_fallback_sig_cap()' in 'env/env.cc'.
|
||||
*/
|
||||
constexpr static size_t _emergency_ram_size() { return 8*1024; }
|
||||
Ram_dataspace_capability _emergency_ram_ds;
|
||||
/**
|
||||
* 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(cpu_cap),
|
||||
_region_map_mmap(false),
|
||||
_pd_session_cap(pd_cap),
|
||||
_local_pd_session(_pd_session_cap)
|
||||
{ }
|
||||
|
||||
|
||||
/*************************************
|
||||
** Linux-specific helper functions **
|
||||
*************************************/
|
||||
/*******************
|
||||
** Env interface **
|
||||
*******************/
|
||||
|
||||
public:
|
||||
Ram_session *ram_session() override { return &_ram_session_client; }
|
||||
Ram_session_capability ram_session_cap() override { return _ram_session_cap; }
|
||||
Region_map *rm_session() override { return &_region_map_mmap; }
|
||||
Cpu_session *cpu_session() override { return &_cpu_session_client; }
|
||||
Cpu_session_capability cpu_session_cap() override { return _cpu_session_cap; }
|
||||
Pd_session *pd_session() override { return &_local_pd_session; }
|
||||
Pd_session_capability pd_session_cap() override { return _pd_session_cap; }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Platform_env();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Platform_env() { _parent().exit(0); }
|
||||
/*
|
||||
* Support functions for implementing fork on Noux.
|
||||
*
|
||||
* Not supported on Linux.
|
||||
*/
|
||||
void reinit(Native_capability::Dst, long) override { }
|
||||
void reinit_main_thread(Capability<Region_map> &) override { }
|
||||
};
|
||||
|
||||
|
||||
/*************************************
|
||||
** Emergency_ram_reserve interface **
|
||||
*************************************/
|
||||
/**
|
||||
* 'Platform_env' used by all processes except for core
|
||||
*/
|
||||
class Genode::Platform_env : public Platform_env_base, public Emergency_ram_reserve
|
||||
{
|
||||
private:
|
||||
|
||||
void release() { ram_session()->free(_emergency_ram_ds); }
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
private:
|
||||
|
||||
Allocator &_alloc;
|
||||
|
||||
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 &,
|
||||
Allocator &);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 8*1024; }
|
||||
Ram_dataspace_capability _emergency_ram_ds;
|
||||
|
||||
|
||||
/*******************
|
||||
** Env interface **
|
||||
*******************/
|
||||
/*************************************
|
||||
** Linux-specific helper functions **
|
||||
*************************************/
|
||||
|
||||
Parent *parent() override { return &_parent(); }
|
||||
Heap *heap() override { return &_heap; }
|
||||
};
|
||||
}
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Platform_env();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Platform_env() { _parent().exit(0); }
|
||||
|
||||
|
||||
/*************************************
|
||||
** Emergency_ram_reserve interface **
|
||||
*************************************/
|
||||
|
||||
void release() { ram_session()->free(_emergency_ram_ds); }
|
||||
|
||||
|
||||
/*******************
|
||||
** Env interface **
|
||||
*******************/
|
||||
|
||||
Parent *parent() override { return &_parent(); }
|
||||
Heap *heap() override { return &_heap; }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__BASE__INTERNAL__PLATFORM_ENV_H_ */
|
||||
|
||||
@@ -53,7 +53,7 @@ static inline void flush_stack_area()
|
||||
int ret;
|
||||
if ((ret = lx_munmap(base, size)) < 0) {
|
||||
PERR("%s: failed ret=%d", __func__, ret);
|
||||
throw Rm_session::Region_conflict();
|
||||
throw Region_map::Region_conflict();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ static inline Genode::addr_t reserve_stack_area()
|
||||
|
||||
PERR("%s: failed addr_in=%p addr_out=%p ret=%ld)", __func__,
|
||||
addr_in, addr_out, (long)addr_out);
|
||||
throw Rm_session::Region_conflict();
|
||||
throw Region_map::Region_conflict();
|
||||
}
|
||||
|
||||
return (addr_t) addr_out;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <base/thread.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <rm_session/connection.h>
|
||||
#include <region_map/client.h>
|
||||
|
||||
|
||||
static void blob() __attribute__((used));
|
||||
@@ -66,26 +67,28 @@ int main()
|
||||
env()->rm_session()->attach_at(ds, beg);
|
||||
PERR("after RAM dataspace attach -- ERROR");
|
||||
sleep_forever();
|
||||
} catch (Rm_session::Region_conflict) {
|
||||
} catch (Region_map::Region_conflict) {
|
||||
PLOG("OK caught Region_conflict exception");
|
||||
}
|
||||
|
||||
/* empty managed dataspace overlapping binary */
|
||||
try {
|
||||
Rm_connection rm(0, size);
|
||||
Rm_connection rm_connection;
|
||||
Region_map_client rm(rm_connection.create(size));
|
||||
Dataspace_capability ds(rm.dataspace());
|
||||
|
||||
PLOG("before sub-RM dataspace attach");
|
||||
env()->rm_session()->attach_at(ds, beg);
|
||||
PERR("after sub-RM dataspace attach -- ERROR");
|
||||
sleep_forever();
|
||||
} catch (Rm_session::Region_conflict) {
|
||||
} catch (Region_map::Region_conflict) {
|
||||
PLOG("OK caught Region_conflict exception");
|
||||
}
|
||||
|
||||
/* sparsely populated managed dataspace in free VM area */
|
||||
try {
|
||||
Rm_connection rm(0, 0x100000);
|
||||
Rm_connection rm_connection;
|
||||
Region_map_client rm(rm_connection.create(0x100000));
|
||||
|
||||
rm.attach_at(env()->ram_session()->alloc(0x1000), 0x1000);
|
||||
|
||||
@@ -97,7 +100,7 @@ int main()
|
||||
char const val = *addr;
|
||||
*addr = 0x55;
|
||||
PLOG("after touch (%x/%x)", val, *addr);
|
||||
} catch (Rm_session::Region_conflict) {
|
||||
} catch (Region_map::Region_conflict) {
|
||||
PERR("Caught Region_conflict exception -- ERROR");
|
||||
sleep_forever();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Linux: Test bug in rm_session_mmap.cc
|
||||
* \brief Linux: Test bug in region_map_mmap.cc
|
||||
* \author Christian Helmuth
|
||||
* \date 2012-12-19
|
||||
*/
|
||||
@@ -1,3 +1,3 @@
|
||||
TARGET = test-rm_session_mmap
|
||||
TARGET = test-region_map_mmap
|
||||
LIBS = base
|
||||
SRC_CC = main.cc
|
||||
Reference in New Issue
Block a user