Linux: remove 'some_mem' array in core

The Linux version of core used a part of the BSS to simulate access to
physical memory. All dataspaces would refer to a portion of 'some_mem'.
So every time when core would access the dataspace content, it would
access its local BSS. For all processes outside of core, dataspaces were
represented as files. This patch removes the distinction between core
and non-core processes. Now, core uses the same 'Rm_session_mmap'
implementation as regular processes. This way, the 'some_mem' could be
abandoned. We still use BSS variable for allocating core-local meta
data through.
This commit is contained in:
Norman Feske 2012-12-04 16:51:24 +01:00
parent 8930ce765d
commit f081733f4b
10 changed files with 486 additions and 85 deletions

View File

@ -31,7 +31,11 @@
namespace Genode {
class Platform_env : public Env
/**
* Common base class of the 'Platform_env' implementations for core and
* non-core processes.
*/
class Platform_env_base : public Env
{
private:
@ -146,6 +150,12 @@ namespace Genode {
}
};
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
@ -186,6 +196,36 @@ namespace Genode {
void _add_to_rmap(Region const &);
/**
* Map dataspace into local address space
*/
static void *_map_local(Dataspace_capability ds,
Genode::size_t size,
addr_t offset,
bool use_local_addr,
addr_t local_addr,
bool executable);
/**
* 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()').
*/
static size_t _dataspace_size(Capability<Dataspace>);
/**
* Determine file descriptor of dataspace
*/
static int _dataspace_fd(Capability<Dataspace>);
/**
* Determine whether dataspace is writable
*/
static bool _dataspace_writable(Capability<Dataspace>);
public:
Rm_session_mmap(bool sub_rm, size_t size = ~0)
@ -240,6 +280,7 @@ namespace Genode {
}
};
private:
class Expanding_ram_session_client : public Ram_session_client
{
@ -274,6 +315,55 @@ namespace Genode {
};
/*******************************
** Platform-specific members **
*******************************/
Ram_session_capability _ram_session_cap;
Expanding_ram_session_client _ram_session_client;
Cpu_session_capability _cpu_session_cap;
Linux_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
{
private:
/**
* Local interceptor of parent requests
*
@ -308,62 +398,32 @@ namespace Genode {
Local_parent(Parent_capability parent_cap);
};
/**
* Obtain singleton instance of parent interface
*/
static Local_parent &_parent();
Heap _heap;
/*************************************
** Linux-specific helper functions **
*************************************/
/**
* Read Unix environment variable as long value
*/
static unsigned long _get_env_ulong(const char *key);
Parent_capability _parent_cap()
{
long 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-specific members **
*******************************/
Local_parent _parent;
Ram_session_capability _ram_session_cap;
Expanding_ram_session_client _ram_session_client;
Cpu_session_capability _cpu_session_cap;
Linux_cpu_session_client _cpu_session_client;
Rm_session_mmap _rm_session_mmap;
Pd_session_client _pd_session_client;
Heap _heap;
public:
/**
* Standard constructor
*/
Platform_env()
:
_parent(_parent_cap()),
_ram_session_cap(static_cap_cast<Ram_session>(parent()->session("Env::ram_session", ""))),
_ram_session_client(_ram_session_cap),
_cpu_session_cap(static_cap_cast<Cpu_session>(parent()->session("Env::cpu_session", ""))),
_cpu_session_client(static_cap_cast<Linux_cpu_session>(parent()->session("Env::cpu_session", ""))),
_rm_session_mmap(false),
_pd_session_client(static_cap_cast<Pd_session>(parent()->session("Env::pd_session", ""))),
_heap(&_ram_session_client, &_rm_session_mmap)
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())
{ }
/**
* Destructor
*/
~Platform_env() { parent()->exit(0); }
~Platform_env() { _parent().exit(0); }
/**
* Reload parent capability and reinitialize environment resources
@ -378,14 +438,8 @@ namespace Genode {
** Env interface **
*******************/
Parent *parent() { return &_parent; }
Ram_session *ram_session() { return &_ram_session_client; }
Ram_session_capability ram_session_cap() { return _ram_session_cap; }
Rm_session *rm_session() { return &_rm_session_mmap; }
Heap *heap() { return &_heap; }
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; }
Parent *parent() { return &_parent(); }
Heap *heap() { return &_heap; }
};
}

View File

@ -14,11 +14,39 @@
#include <util/arg_string.h>
#include <base/platform_env.h>
#include <base/thread.h>
#include <linux_dataspace/client.h>
#include <linux_syscalls.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 **
********************************/
@ -83,7 +111,7 @@ extern char **lx_environ;
/**
* Read environment variable as long value
*/
unsigned long Platform_env::_get_env_ulong(const char *key)
static unsigned long get_env_ulong(const char *key)
{
for (char **curr = lx_environ; curr && *curr; curr++) {
@ -96,6 +124,24 @@ unsigned long Platform_env::_get_env_ulong(const char *key)
}
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());
return local_parent;
}
/*****************************
** Support for IPC library **
*****************************/

View File

@ -19,15 +19,6 @@
using namespace Genode;
static Genode::size_t dataspace_size(Dataspace_capability ds)
{
if (ds.valid())
return Dataspace_client(ds).size();
return Dataspace_capability::deref(ds)->size();
}
static bool is_sub_rm_session(Dataspace_capability ds)
{
if (ds.valid())
@ -37,12 +28,16 @@ static bool is_sub_rm_session(Dataspace_capability ds)
}
static void *map_local(Dataspace_capability ds, Genode::size_t size,
addr_t offset, bool use_local_addr, addr_t local_addr,
bool executable)
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)
{
int const fd = Linux_dataspace_client(ds).fd().dst().socket;
bool const writable = Dataspace_client(ds).writable();
int const fd = _dataspace_fd(ds);
bool const writable = _dataspace_writable(ds);
int const flags = MAP_SHARED | (use_local_addr ? MAP_FIXED : 0);
int const prot = PROT_READ
@ -60,7 +55,7 @@ static void *map_local(Dataspace_capability ds, Genode::size_t size,
lx_close(fd);
if (((long)addr_out < 0) && ((long)addr_out > -4095)) {
PERR("map_local: return value of mmap is %ld", (long)addr_out);
PERR("_map_local: return value of mmap is %ld", (long)addr_out);
throw Rm_session::Region_conflict();
}
@ -97,8 +92,8 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
throw Region_conflict();
}
size_t const remaining_ds_size = dataspace_size(ds) > (addr_t)offset
? dataspace_size(ds) - (addr_t)offset : 0;
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)
@ -148,7 +143,7 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
* and map it.
*/
if (_is_attached())
map_local(ds, region_size, offset, true, _base + (addr_t)local_addr, executable);
_map_local(ds, region_size, offset, true, _base + (addr_t)local_addr, executable);
return (void *)local_addr;
@ -194,9 +189,9 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
if (!region.used())
continue;
map_local(region.dataspace(), region.size(), region.offset(),
true, rm->_base + region.start() + region.offset(),
executable);
_map_local(region.dataspace(), region.size(), region.offset(),
true, rm->_base + region.start() + region.offset(),
executable);
}
return rm->_base;
@ -208,8 +203,8 @@ Platform_env::Rm_session_mmap::attach(Dataspace_capability ds,
*
* Boring, a plain dataspace is attached to a root RM session.
*/
void *addr = map_local(ds, region_size, offset, use_local_addr,
local_addr, executable);
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));

View File

@ -0,0 +1,213 @@
/*
* \brief Core-specific environment for Linux
* \author Norman Feske
* \author Christian Helmuth
* \date 2006-07-28
*
* The Core-specific environment ensures that all sessions of Core's
* environment a local.
*/
/*
* Copyright (C) 2006-2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _CORE__INCLUDE__CORE_ENV_H_
#define _CORE__INCLUDE__CORE_ENV_H_
/* Genode includes */
#include <base/platform_env.h>
/* core includes */
#include <platform.h>
#include <core_parent.h>
#include <cap_session_component.h>
#include <ram_session_component.h>
namespace Genode {
/**
* Lock-guarded version of a RAM-session implementation
*
* \param RAM_SESSION_IMPL non-thread-safe RAM-session class
*
* In contrast to normal processes, core's 'env()->ram_session()' is not
* synchronized by an RPC interface. However, it is accessed by different
* threads using the 'env()->heap()' and the sliced heap used for
* allocating sessions to core's services.
*/
template <typename RAM_SESSION_IMPL>
class Synchronized_ram_session : public RAM_SESSION_IMPL
{
private:
Lock _lock;
public:
/**
* Constructor
*/
Synchronized_ram_session(Rpc_entrypoint *ds_ep,
Rpc_entrypoint *ram_session_ep,
Range_allocator *ram_alloc,
Allocator *md_alloc,
const char *args,
size_t quota_limit = 0)
:
RAM_SESSION_IMPL(ds_ep, ram_session_ep, ram_alloc, md_alloc, args, quota_limit)
{ }
/***************************
** RAM-session interface **
***************************/
Ram_dataspace_capability alloc(size_t size, bool cached)
{
Lock::Guard lock_guard(_lock);
return RAM_SESSION_IMPL::alloc(size, cached);
}
void free(Ram_dataspace_capability ds)
{
Lock::Guard lock_guard(_lock);
RAM_SESSION_IMPL::free(ds);
}
int ref_account(Ram_session_capability session)
{
Lock::Guard lock_guard(_lock);
return RAM_SESSION_IMPL::ref_account(session);
}
int transfer_quota(Ram_session_capability session, size_t size)
{
Lock::Guard lock_guard(_lock);
return RAM_SESSION_IMPL::transfer_quota(session, size);
}
size_t quota()
{
Lock::Guard lock_guard(_lock);
return RAM_SESSION_IMPL::quota();
}
size_t used()
{
Lock::Guard lock_guard(_lock);
return RAM_SESSION_IMPL::used();
}
};
class Core_env : public Platform_env_base
{
public:
/**
* Entrypoint with support for local object access
*
* Within core, there are a few cases where the RPC objects must
* be invoked by direct function calls instead of using RPC.
* I.e., when an entrypoint dispatch function performs a memory
* allocation via the 'Sliced_heap', the 'attach' function of
* 'Rm_session_mmap' tries to obtain the dataspace's size and fd.
* Normally, this would be done by calling the entrypoint but the
* entrypoint cannot call itself. To support this special case,
* the 'Entrypoint' extends the 'Rpc_entrypoint' with the
* functionality needed to lookup an RPC object by its capability.
*/
struct Entrypoint : Rpc_entrypoint
{
enum { STACK_SIZE = 2048 * sizeof(Genode::addr_t) };
template <typename T>
T *lookup(Capability<T> cap)
{
Rpc_object_base *obj = obj_by_cap(cap);
return obj ? dynamic_cast<T *>(obj) : 0;
}
Entrypoint(Cap_session *cap_session)
:
Rpc_entrypoint(cap_session, STACK_SIZE, "entrypoint")
{ }
};
private:
typedef Synchronized_ram_session<Ram_session_component> Core_ram_session;
Core_parent _core_parent;
Cap_session_component _cap_session;
Entrypoint _entrypoint;
Core_ram_session _ram_session;
Heap _heap;
Ram_session_capability const _ram_session_cap;
public:
/**
* Constructor
*/
Core_env()
:
Platform_env_base(Ram_session_capability(),
Cpu_session_capability(),
Pd_session_capability()),
_entrypoint(&_cap_session),
_ram_session(&_entrypoint, &_entrypoint,
platform()->ram_alloc(), platform()->core_mem_alloc(),
"ram_quota=4M", platform()->ram_alloc()->avail()),
_heap(&_ram_session, Platform_env_base::rm_session()),
_ram_session_cap(_entrypoint.manage(&_ram_session))
{ }
/**
* Destructor
*/
~Core_env() { parent()->exit(0); }
/**************************************
** Core-specific accessor functions **
**************************************/
Cap_session *cap_session() { return &_cap_session; }
Entrypoint *entrypoint() { return &_entrypoint; }
/*******************
** Env interface **
*******************/
Parent *parent() { return &_core_parent; }
Ram_session *ram_session() { return &_ram_session; }
Ram_session_capability ram_session_cap() { return _ram_session_cap; }
Allocator *heap() { return &_heap; }
Cpu_session_capability cpu_session_cap() {
PWRN("%s:%u not implemented", __FILE__, __LINE__);
return Cpu_session_capability();
}
Pd_session *pd_session()
{
PWRN("%s:%u not implemented", __FILE__, __LINE__);
return 0;
}
};
/**
* Request pointer to static environment of Core
*/
extern Core_env *core_env();
}
#endif /* _CORE__INCLUDE__CORE_ENV_H_ */

View File

@ -31,7 +31,43 @@ namespace Genode {
{
private:
Synchronized_range_allocator<Allocator_avl> _ram_alloc; /* RAM allocator */
/**
* Allocator for core-internal meta data
*/
Synchronized_range_allocator<Allocator_avl> _core_mem_alloc;
/**
* Allocator for pseudo physical memory
*/
struct Pseudo_ram_allocator : Range_allocator
{
bool alloc(size_t size, void **out_addr)
{
*out_addr = 0;
return true;
}
Alloc_return alloc_aligned(size_t, void **out_addr, int)
{
*out_addr = 0;
return Alloc_return::OK;
}
Alloc_return alloc_addr(size_t, addr_t)
{
return Alloc_return::OK;;
}
int add_range(addr_t, size_t) { return 0; }
int remove_range(addr_t, size_t) { return 0; }
void free(void *) { }
void free(void *, size_t) { }
size_t avail() { return ~0; }
bool valid_addr(addr_t) { return true; }
size_t overhead(size_t) { return 0; }
};
Pseudo_ram_allocator _ram_alloc;
public:
@ -45,7 +81,7 @@ namespace Genode {
** Generic platform interface **
********************************/
Range_allocator *core_mem_alloc() { return &_ram_alloc; }
Range_allocator *core_mem_alloc() { return &_core_mem_alloc; }
Range_allocator *ram_alloc() { return &_ram_alloc; }
Range_allocator *io_mem_alloc() { return 0; }
Range_allocator *io_port_alloc() { return 0; }

View File

@ -13,6 +13,7 @@
/* Genode includes */
#include <base/lock.h>
#include <linux_dataspace/client.h>
/* local includes */
#include "platform.h"
@ -26,7 +27,10 @@
using namespace Genode;
static char _some_mem[80*1024*1024];
/**
* Memory pool used for for core-local meta data
*/
static char _core_mem[80*1024*1024];
static Lock _wait_for_exit_lock(Lock::LOCKED); /* exit() sync */
@ -37,7 +41,7 @@ static void signal_handler(int signum)
Platform::Platform()
: _ram_alloc(0)
: _core_mem_alloc(0)
{
/* catch control-c */
lx_sigaction(2, signal_handler);
@ -45,7 +49,7 @@ Platform::Platform()
/* create resource directory under /tmp */
lx_mkdir(resource_path(), S_IRWXU);
_ram_alloc.add_range((addr_t)_some_mem, sizeof(_some_mem));
_core_mem_alloc.add_range((addr_t)_core_mem, sizeof(_core_mem));
/*
* Occupy the socket handle that will be used to propagate the parent
@ -95,3 +99,46 @@ namespace Genode {
}
}
/****************************************************
** Support for Platform_env_base::Rm_session_mmap **
****************************************************/
Genode::size_t
Platform_env_base::Rm_session_mmap::_dataspace_size(Capability<Dataspace> ds_cap)
{
if (!ds_cap.valid())
return Dataspace_capability::deref(ds_cap)->size();
/* use RPC if called from a different thread */
if (!core_env()->entrypoint()->is_myself())
return Dataspace_client(ds_cap).size();
/* use local function call if called from the entrypoint */
Dataspace *ds = core_env()->entrypoint()->lookup(ds_cap);
return ds ? ds->size() : 0;
}
int Platform_env_base::Rm_session_mmap::_dataspace_fd(Capability<Dataspace> ds_cap)
{
if (!core_env()->entrypoint()->is_myself())
return Linux_dataspace_client(ds_cap).fd().dst().socket;
Capability<Linux_dataspace> lx_ds_cap = static_cap_cast<Linux_dataspace>(ds_cap);
Linux_dataspace *ds = core_env()->entrypoint()->lookup(lx_ds_cap);
return ds ? ds->fd().dst().socket : -1;
}
bool Platform_env_base::Rm_session_mmap::_dataspace_writable(Dataspace_capability ds_cap)
{
if (!core_env()->entrypoint()->is_myself())
return Dataspace_client(ds_cap).writable();
Dataspace *ds = core_env()->entrypoint()->lookup(ds_cap);
return ds ? ds->writable() : false;
}

View File

@ -61,7 +61,4 @@ void Ram_session_component::_revoke_ram_ds(Dataspace_component *ds)
}
void Ram_session_component::_clear_ds(Dataspace_component *ds)
{
memset((void *)ds->phys_addr(), 0, ds->size());
}
void Ram_session_component::_clear_ds(Dataspace_component *ds) { }

View File

@ -21,7 +21,8 @@ SRC_CC = main.cc \
thread.cc \
thread_linux.cc \
context_area.cc \
debug.cc
debug.cc \
rm_session_mmap.cc
INC_DIR += $(REP_DIR)/src/core/include \
$(GEN_CORE_DIR)/include \
@ -38,4 +39,5 @@ vpath platform_services.cc $(GEN_CORE_DIR)
vpath signal_session_component.cc $(GEN_CORE_DIR)
vpath signal_source_component.cc $(GEN_CORE_DIR)
vpath debug.cc $(REP_DIR)/src/base/env
vpath rm_session_mmap.cc $(REP_DIR)/src/base/env
vpath %.cc $(PRG_DIR)

View File

@ -399,6 +399,11 @@ namespace Genode {
* answering the original call.
*/
void explicit_reply(Untyped_capability reply_cap, int return_value);
/**
* Return true if the caller corresponds to the entrypoint called
*/
bool is_myself() const;
};
}

View File

@ -91,6 +91,12 @@ void Rpc_entrypoint::activate()
}
bool Rpc_entrypoint::is_myself() const
{
return (Thread_base::myself() == this);
}
Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size,
char const *name, bool start_on_construction)
: