mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-19 07:38:28 +00:00
base: introduce platform_init function
The new 'init_platform' function performs the platform-specific component-local low-level initialization. It allows for the differentiation between core and regular components as well as kernel-dependent peculiarities. This patch introduces a consistent notion of a 'Platform'. Within core, the 'Platform' contains the kernel-specific initialization. Outside core, the platform sets up the interplay with the parent component. In all cases, the platform is constructed while running on the initial stack. Issue #4784
This commit is contained in:
@ -16,14 +16,14 @@
|
||||
*/
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/platform_env.h>
|
||||
#include <base/internal/platform.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Platform_env::_attach_stack_area()
|
||||
void Platform::_attach_stack_area()
|
||||
{
|
||||
_local_pd_session._address_space.attach_at(_local_pd_session._stack_area.dataspace(),
|
||||
stack_area_virtual_base(),
|
||||
stack_area_virtual_size());
|
||||
pd._address_space.attach_at(pd._stack_area.dataspace(),
|
||||
stack_area_virtual_base(),
|
||||
stack_area_virtual_size());
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ using namespace Genode;
|
||||
*
|
||||
* At this point in time, we do not yet know the TID and PID of the new
|
||||
* thread. Those information will be provided to core by the constructor of
|
||||
* the 'Platform_env' of the new process.
|
||||
* the 'Platform' of the new process.
|
||||
*/
|
||||
Child::Initial_thread::Initial_thread(Cpu_session &cpu,
|
||||
Pd_session_capability pd,
|
||||
|
@ -1,42 +1,230 @@
|
||||
/*
|
||||
* \brief Platform dependant hook after binary ready
|
||||
* \brief Support for the Linux-specific environment
|
||||
* \author Norman Feske
|
||||
* \author Stefan Thoeni
|
||||
* \date 2019-12-13
|
||||
* \date 2008-12-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Genode Labs GmbH
|
||||
* Copyright (C) 2019 gapfruit AG
|
||||
* Copyright (C) 2008-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/log.h>
|
||||
#include <util/arg_string.h>
|
||||
#include <base/thread.h>
|
||||
#include <linux_dataspace/client.h>
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/platform.h>
|
||||
#include <base/internal/native_thread.h>
|
||||
#include <base/internal/globals.h>
|
||||
#include <linux_syscalls.h>
|
||||
#include <base/internal/parent_socket_handle.h>
|
||||
#include <base/internal/capability_space_tpl.h>
|
||||
|
||||
#include <deprecated/env.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/*********************************
|
||||
** Support for Rm_session_mmap **
|
||||
*********************************/
|
||||
|
||||
size_t Region_map_mmap::_dataspace_size(Dataspace_capability ds)
|
||||
{
|
||||
if (local(ds))
|
||||
return Local_capability<Dataspace>::deref(ds)->size();
|
||||
|
||||
return Dataspace_client(ds).size();
|
||||
|
||||
}
|
||||
|
||||
|
||||
int Region_map_mmap::_dataspace_fd(Dataspace_capability ds)
|
||||
{
|
||||
Untyped_capability fd_cap = Linux_dataspace_client(ds).fd();
|
||||
return lx_dup(Capability_space::ipc_cap_data(fd_cap).dst.socket.value);
|
||||
}
|
||||
|
||||
|
||||
bool Region_map_mmap::_dataspace_writeable(Dataspace_capability ds)
|
||||
{
|
||||
return Dataspace_client(ds).writeable();
|
||||
}
|
||||
|
||||
|
||||
/******************
|
||||
** Local_parent **
|
||||
******************/
|
||||
|
||||
Session_capability Local_parent::session(Parent::Client::Id id,
|
||||
Service_name const &service_name,
|
||||
Session_args const &args,
|
||||
Affinity const &affinity)
|
||||
{
|
||||
if (strcmp(service_name.string(), Rm_session::service_name()) == 0) {
|
||||
|
||||
Local_rm_session *local_rm_session = new (_alloc)
|
||||
Local_rm_session(_local_rm, _alloc, _local_sessions_id_space, id);
|
||||
|
||||
return local_rm_session->local_session_cap();
|
||||
}
|
||||
|
||||
return Expanding_parent_client::session(id, service_name, args, affinity);
|
||||
}
|
||||
|
||||
|
||||
Parent::Close_result Local_parent::close(Client::Id id)
|
||||
{
|
||||
auto close_local_fn = [&] (Local_session &local_session)
|
||||
{
|
||||
Capability<Rm_session> rm =
|
||||
static_cap_cast<Rm_session>(local_session.local_session_cap());
|
||||
destroy(_alloc, Local_capability<Rm_session>::deref(rm));
|
||||
};
|
||||
|
||||
/*
|
||||
* Local RM sessions are present in the '_local_sessions_id_space'. If the
|
||||
* apply succeeds, 'id' referred to the local session. Otherwise, we
|
||||
* forward the request to the parent.
|
||||
*/
|
||||
try {
|
||||
_local_sessions_id_space.apply<Local_session>(id, close_local_fn);
|
||||
return CLOSE_DONE;
|
||||
}
|
||||
catch (Id_space<Client>::Unknown_id) { }
|
||||
|
||||
return Parent_client::close(id);
|
||||
}
|
||||
|
||||
|
||||
Local_parent::Local_parent(Parent_capability parent_cap,
|
||||
Region_map &local_rm, Allocator &alloc)
|
||||
:
|
||||
Expanding_parent_client(parent_cap), _local_rm(local_rm), _alloc(alloc)
|
||||
{ }
|
||||
|
||||
|
||||
/**************
|
||||
** Platform **
|
||||
**************/
|
||||
|
||||
/**
|
||||
* 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 Platform *_platform_ptr;
|
||||
|
||||
|
||||
Env_deprecated *Genode::env_deprecated()
|
||||
{
|
||||
if (!_platform_ptr) {
|
||||
error("missing call of init_platform");
|
||||
for (;;);
|
||||
}
|
||||
|
||||
struct Impl : Env_deprecated, Noncopyable
|
||||
{
|
||||
Platform &_pf;
|
||||
|
||||
Impl(Platform &pf) : _pf(pf) { }
|
||||
|
||||
Parent *parent() override { return &_pf.parent; }
|
||||
Cpu_session *cpu_session() override { return &_pf.cpu; }
|
||||
Cpu_session_capability cpu_session_cap() override { return _pf.cpu_cap; }
|
||||
Region_map *rm_session() override { return &_pf.rm; }
|
||||
Pd_session *pd_session() override { return &_pf.pd; }
|
||||
Pd_session_capability pd_session_cap() override { return _pf.pd_cap; }
|
||||
};
|
||||
|
||||
static Impl impl { *_platform_ptr };
|
||||
|
||||
return &impl;
|
||||
}
|
||||
|
||||
|
||||
static Parent_capability obtain_parent_cap()
|
||||
{
|
||||
long const local_name = get_env_ulong("parent_local_name");
|
||||
|
||||
Untyped_capability parent_cap =
|
||||
Capability_space::import(Rpc_destination(Lx_sd{PARENT_SOCKET_HANDLE}),
|
||||
Rpc_obj_key(local_name));
|
||||
|
||||
return reinterpret_cap_cast<Parent>(parent_cap);
|
||||
}
|
||||
|
||||
|
||||
void Genode::init_parent_resource_requests(Genode::Env & env)
|
||||
{
|
||||
/**
|
||||
* Catch up asynchronous resource request and notification
|
||||
* mechanism construction of the expanding parent environment
|
||||
*/
|
||||
using Parent = Expanding_parent_client;
|
||||
static_cast<Parent*>(&env.parent())->init_fallback_signal_handling();
|
||||
}
|
||||
|
||||
|
||||
void Genode::init_platform()
|
||||
{
|
||||
static Platform platform { obtain_parent_cap() };
|
||||
|
||||
/* allow use of deprecated_env */
|
||||
_platform_ptr = &platform;
|
||||
|
||||
init_log(platform.parent);
|
||||
init_rpc_cap_alloc(platform.parent);
|
||||
|
||||
env_stack_area_region_map = &platform.pd._stack_area;
|
||||
env_stack_area_ram_allocator = &platform.pd;
|
||||
|
||||
/* register TID and PID of the main thread at core */
|
||||
Linux_native_cpu_client native_cpu(platform.cpu.native_cpu());
|
||||
|
||||
native_cpu.thread_id(platform.parent.main_thread_cap(),
|
||||
lx_getpid(), lx_gettid());
|
||||
|
||||
init_rpc_cap_alloc(platform.parent);
|
||||
}
|
||||
|
||||
|
||||
/*************************
|
||||
** Support for seccomp **
|
||||
*************************/
|
||||
|
||||
/* Linux includes */
|
||||
#include <errno.h>
|
||||
#include <sys/prctl.h> /* prctl */
|
||||
#include <linux/seccomp.h> /* seccomp's constants */
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
extern char _binary_seccomp_bpf_policy_bin_start[];
|
||||
extern char _binary_seccomp_bpf_policy_bin_end[];
|
||||
|
||||
|
||||
namespace Genode {
|
||||
|
||||
struct Bpf_program
|
||||
{
|
||||
uint16_t blk_cnt;
|
||||
uint64_t *blks;
|
||||
};
|
||||
}
|
||||
|
||||
void Genode::binary_ready_hook_for_platform()
|
||||
{
|
||||
if (lx_prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) {
|
||||
@ -44,6 +232,12 @@ void Genode::binary_ready_hook_for_platform()
|
||||
throw Exception();
|
||||
}
|
||||
|
||||
struct Bpf_program
|
||||
{
|
||||
uint16_t blk_cnt;
|
||||
uint64_t *blks;
|
||||
};
|
||||
|
||||
for (char* i = _binary_seccomp_bpf_policy_bin_start;
|
||||
i < _binary_seccomp_bpf_policy_bin_end - sizeof(uint32_t); i++) {
|
||||
|
||||
@ -67,4 +261,3 @@ void Genode::binary_ready_hook_for_platform()
|
||||
throw Exception();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,180 +0,0 @@
|
||||
/*
|
||||
* \brief Support for the Linux-specific environment
|
||||
* \author Norman Feske
|
||||
* \date 2008-12-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/arg_string.h>
|
||||
#include <base/thread.h>
|
||||
#include <linux_dataspace/client.h>
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/platform_env.h>
|
||||
#include <base/internal/native_thread.h>
|
||||
#include <base/internal/globals.h>
|
||||
#include <base/internal/parent_socket_handle.h>
|
||||
#include <base/internal/capability_space_tpl.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/****************************************************
|
||||
** Support for Platform_env_base::Rm_session_mmap **
|
||||
****************************************************/
|
||||
|
||||
size_t Region_map_mmap::_dataspace_size(Dataspace_capability ds)
|
||||
{
|
||||
if (local(ds))
|
||||
return Local_capability<Dataspace>::deref(ds)->size();
|
||||
|
||||
return Dataspace_client(ds).size();
|
||||
|
||||
}
|
||||
|
||||
|
||||
int Region_map_mmap::_dataspace_fd(Dataspace_capability ds)
|
||||
{
|
||||
Untyped_capability fd_cap = Linux_dataspace_client(ds).fd();
|
||||
return lx_dup(Capability_space::ipc_cap_data(fd_cap).dst.socket.value);
|
||||
}
|
||||
|
||||
|
||||
bool Region_map_mmap::_dataspace_writeable(Dataspace_capability ds)
|
||||
{
|
||||
return Dataspace_client(ds).writeable();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************
|
||||
** Local_parent **
|
||||
******************/
|
||||
|
||||
Session_capability Local_parent::session(Parent::Client::Id id,
|
||||
Service_name const &service_name,
|
||||
Session_args const &args,
|
||||
Affinity const &affinity)
|
||||
{
|
||||
if (strcmp(service_name.string(), Rm_session::service_name()) == 0) {
|
||||
|
||||
Local_rm_session *local_rm_session = new (_alloc)
|
||||
Local_rm_session(_local_rm, _alloc, _local_sessions_id_space, id);
|
||||
|
||||
return local_rm_session->local_session_cap();
|
||||
}
|
||||
|
||||
return Expanding_parent_client::session(id, service_name, args, affinity);
|
||||
}
|
||||
|
||||
|
||||
Parent::Close_result Local_parent::close(Client::Id id)
|
||||
{
|
||||
auto close_local_fn = [&] (Local_session &local_session)
|
||||
{
|
||||
Capability<Rm_session> rm =
|
||||
static_cap_cast<Rm_session>(local_session.local_session_cap());
|
||||
destroy(_alloc, Local_capability<Rm_session>::deref(rm));
|
||||
};
|
||||
|
||||
/*
|
||||
* Local RM sessions are present in the '_local_sessions_id_space'. If the
|
||||
* apply succeeds, 'id' referred to the local session. Otherwise, we
|
||||
* forward the request to the parent.
|
||||
*/
|
||||
try {
|
||||
_local_sessions_id_space.apply<Local_session>(id, close_local_fn);
|
||||
return CLOSE_DONE;
|
||||
}
|
||||
catch (Id_space<Client>::Unknown_id) { }
|
||||
|
||||
return Parent_client::close(id);
|
||||
}
|
||||
|
||||
|
||||
Local_parent::Local_parent(Parent_capability parent_cap,
|
||||
Region_map &local_rm, Allocator &alloc)
|
||||
:
|
||||
Expanding_parent_client(parent_cap), _local_rm(local_rm), _alloc(alloc)
|
||||
{ }
|
||||
|
||||
|
||||
/******************
|
||||
** 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 const local_name = get_env_ulong("parent_local_name");
|
||||
|
||||
Untyped_capability parent_cap =
|
||||
Capability_space::import(Rpc_destination(Lx_sd{PARENT_SOCKET_HANDLE}),
|
||||
Rpc_obj_key(local_name));
|
||||
|
||||
return reinterpret_cap_cast<Parent>(parent_cap);
|
||||
}
|
||||
|
||||
|
||||
static Region_map_mmap &local_rm()
|
||||
{
|
||||
static Region_map_mmap local_rm(false);
|
||||
return local_rm;
|
||||
}
|
||||
|
||||
|
||||
Local_parent &Platform_env::_parent()
|
||||
{
|
||||
static Local_parent local_parent(obtain_parent_cap(), local_rm(), _heap);
|
||||
return local_parent;
|
||||
}
|
||||
|
||||
|
||||
Platform_env::Platform_env()
|
||||
:
|
||||
Platform_env_base(_parent(), local_rm(),
|
||||
static_cap_cast<Cpu_session>(_parent().session_cap(Parent::Env::cpu())),
|
||||
static_cap_cast<Pd_session> (_parent().session_cap(Parent::Env::pd()))),
|
||||
_heap(Platform_env_base::pd_session(), Platform_env_base::rm_session())
|
||||
{
|
||||
_attach_stack_area();
|
||||
|
||||
env_stack_area_region_map = &_local_pd_session._stack_area;
|
||||
env_stack_area_ram_allocator = Platform_env_base::pd_session();
|
||||
|
||||
/* register TID and PID of the main thread at core */
|
||||
Linux_native_cpu_client native_cpu(cpu_session()->native_cpu());
|
||||
native_cpu.thread_id(parent()->main_thread_cap(), lx_getpid(), lx_gettid());
|
||||
|
||||
init_rpc_cap_alloc(_parent());
|
||||
}
|
||||
|
Reference in New Issue
Block a user