Unification of native_capability.h

This patch establishes the sole use of generic headers across all
kernels. The common 'native_capability.h' is based on the version of
base-sel4. All traditional L4 kernels and Linux use the same
implementation of the capability-lifetime management. On base-hw, NOVA,
Fiasco.OC, and seL4, custom implementations (based on their original
mechanisms) are used, with the potential to unify them further in the
future.

This change achieves binary compatibility of dynamically linked programs
across all kernels.

Furthermore, the patch introduces a Native_capability::print method,
which allows the easy output of the kernel-specific capability
representation using the base/log.h API.

Issue #1993
This commit is contained in:
Norman Feske
2016-06-15 15:04:54 +02:00
parent d71f0a9606
commit 88b358c5ef
173 changed files with 2614 additions and 1333 deletions

View File

@ -210,8 +210,6 @@ namespace Genode {
PWRN("%s:%u not implemented", __FILE__, __LINE__);
return Cpu_session_capability();
}
void reload_parent_cap(Capability<Parent>::Dst, long) { }
};

View File

@ -25,6 +25,9 @@
#include <base/rpc_server.h>
#include <base/printf.h>
/* base-internal includes */
#include <base/internal/capability_space_tpl.h>
namespace Genode {
/**
@ -122,9 +125,10 @@ namespace Genode {
Untyped_capability fd()
{
typedef Untyped_capability::Dst Dst;
enum { DUMMY_LOCAL_NAME = 0 };
return Untyped_capability(Dst(_fd), DUMMY_LOCAL_NAME);
Untyped_capability fd_cap =
Capability_space::import(Rpc_destination(_fd), Rpc_obj_key());
return fd_cap;
}
};
}

View File

@ -0,0 +1,39 @@
/*
* \brief RPC capability factory
* \author Norman Feske
* \date 2016-01-19
*/
/*
* Copyright (C) 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.
*/
#ifndef _CORE__INCLUDE__RPC_CAP_FACTORY_H_
#define _CORE__INCLUDE__RPC_CAP_FACTORY_H_
#include <base/allocator.h>
#include <base/lock.h>
#include <base/capability.h>
namespace Genode { class Rpc_cap_factory; }
class Genode::Rpc_cap_factory
{
private:
static Native_capability _alloc(Rpc_cap_factory *owner,
Native_capability ep);
public:
Rpc_cap_factory(Allocator &md_alloc) { }
Native_capability alloc(Native_capability ep);
void free(Native_capability cap);
};
#endif /* _CORE__INCLUDE__RPC_CAP_FACTORY_H_ */

View File

@ -15,6 +15,9 @@
#include <cpu_session_component.h>
#include <native_cpu_component.h>
/* base-internal includes */
#include <base/internal/capability_space_tpl.h>
using namespace Genode;
@ -30,10 +33,8 @@ Untyped_capability Native_cpu_component::server_sd(Thread_capability thread_cap)
auto lambda = [] (Cpu_thread_component *thread) {
if (!thread) return Untyped_capability();
enum { DUMMY_LOCAL_NAME = 0 };
typedef Native_capability::Dst Dst;
return Untyped_capability(Dst(thread->platform_thread().server_sd()),
DUMMY_LOCAL_NAME);
return Capability_space::import(Rpc_destination(thread->platform_thread().server_sd()),
Rpc_obj_key());
};
return _thread_ep.apply(thread_cap, lambda);
}
@ -44,10 +45,8 @@ Untyped_capability Native_cpu_component::client_sd(Thread_capability thread_cap)
auto lambda = [] (Cpu_thread_component *thread) {
if (!thread) return Untyped_capability();
enum { DUMMY_LOCAL_NAME = 0 };
typedef Native_capability::Dst Dst;
return Untyped_capability(Dst(thread->platform_thread().client_sd()),
DUMMY_LOCAL_NAME);
return Capability_space::import(Rpc_destination(thread->platform_thread().client_sd()),
Rpc_obj_key());
};
return _thread_ep.apply(thread_cap, lambda);
}

View File

@ -22,6 +22,7 @@
/* base-internal includes */
#include <base/internal/parent_socket_handle.h>
#include <base/internal/capability_space_tpl.h>
/* Linux includes */
#include <core_linux_syscalls.h>
@ -117,7 +118,8 @@ void Native_pd_component::_start(Dataspace_component &ds)
char buf[4096];
int num_bytes = 0;
while ((num_bytes = lx_read(ds.fd().dst().socket, buf, sizeof(buf))) != 0)
int const fd_socket = Capability_space::ipc_cap_data(ds.fd()).dst.socket;
while ((num_bytes = lx_read(fd_socket, buf, sizeof(buf))) != 0)
lx_write(tmp_binary_fd, buf, num_bytes);
lx_close(tmp_binary_fd);
@ -167,7 +169,7 @@ void Native_pd_component::_start(Dataspace_component &ds)
* pointer, all arguments are embedded within the 'execve_args' struct.
*/
Execve_args arg(filename, argv_buf, env,
_pd_session._parent.dst().socket);
Capability_space::ipc_cap_data(_pd_session._parent).dst.socket);
_pid = lx_create_process((int (*)(void *))_exec_child,
stack + STACK_SIZE - sizeof(umword_t), &arg);

View File

@ -18,6 +18,7 @@
/* base-internal includes */
#include <base/internal/native_thread.h>
#include <base/internal/parent_socket_handle.h>
#include <base/internal/capability_space_tpl.h>
/* local includes */
#include "platform.h"
@ -206,7 +207,8 @@ int Region_map_mmap::_dataspace_fd(Capability<Dataspace> ds_cap)
if (!core_env()->entrypoint()->is_myself()) {
/* release Region_map_mmap::_lock during RPC */
_lock.unlock();
int socket = Linux_dataspace_client(ds_cap).fd().dst().socket;
Untyped_capability fd_cap = Linux_dataspace_client(ds_cap).fd();
int socket = Capability_space::ipc_cap_data(fd_cap).dst.socket;
_lock.lock();
return socket;
}
@ -223,7 +225,7 @@ int Region_map_mmap::_dataspace_fd(Capability<Dataspace> ds_cap)
* dataspace, the descriptor would unexpectedly be closed again.
*/
return core_env()->entrypoint()->apply(lx_ds_cap, [] (Linux_dataspace *ds) {
return ds ? lx_dup(ds->fd().dst().socket) : -1; });
return ds ? lx_dup(Capability_space::ipc_cap_data(ds->fd()).dst.socket) : -1; });
}

View File

@ -21,6 +21,9 @@
#include <ram_session_component.h>
#include <resource_path.h>
/* base-internal includes */
#include <base/internal/capability_space_tpl.h>
/* Linux syscall bindings */
#include <core_linux_syscalls.h>
@ -55,7 +58,7 @@ void Ram_session_component::_export_ram_ds(Dataspace_component *ds)
void Ram_session_component::_revoke_ram_ds(Dataspace_component *ds)
{
int const fd = ds->fd().dst().socket;
int const fd = Capability_space::ipc_cap_data(ds->fd()).dst.socket;
if (fd != -1)
lx_close(fd);
}

View File

@ -24,6 +24,9 @@
#include <util/arg_string.h>
#include <root/root.h>
/* base-internal includes */
#include <base/internal/capability_space_tpl.h>
/* local includes */
#include "rom_session_component.h"
@ -44,7 +47,7 @@ Rom_session_component::~Rom_session_component()
{
_ds_ep->dissolve(&_ds);
int const fd = _ds.fd().dst().socket;
int const fd = Capability_space::ipc_cap_data(_ds.fd()).dst.socket;
if (fd != -1)
lx_close(fd);
}

View File

@ -19,7 +19,8 @@ SRC_CC = main.cc \
dataspace_component.cc \
native_pd_component.cc \
native_cpu_component.cc \
rpc_cap_factory.cc \
capability_space.cc \
rpc_cap_factory_l4.cc \
core_rpc_cap_alloc.cc \
io_mem_session_component.cc \
signal_source_component.cc \
@ -47,7 +48,8 @@ vpath cpu_session_component.cc $(GEN_CORE_DIR)
vpath cpu_session_support.cc $(GEN_CORE_DIR)
vpath cpu_thread_component.cc $(GEN_CORE_DIR)
vpath pd_upgrade_ram_quota.cc $(GEN_CORE_DIR)
vpath rpc_cap_factory.cc $(GEN_CORE_DIR)
vpath capability_space.cc $(GEN_CORE_DIR)
vpath rpc_cap_factory_l4.cc $(GEN_CORE_DIR)
vpath platform_services.cc $(GEN_CORE_DIR)
vpath signal_source_component.cc $(GEN_CORE_DIR)
vpath trace_session_component.cc $(GEN_CORE_DIR)

View File

@ -14,15 +14,24 @@
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__BASE__LOCAL_CAPABILITY_H_
#define _INCLUDE__BASE__LOCAL_CAPABILITY_H_
#ifndef _INCLUDE__BASE__INTERNAL__LOCAL_CAPABILITY_H_
#define _INCLUDE__BASE__INTERNAL__LOCAL_CAPABILITY_H_
#include <base/capability.h>
#include <base/internal/capability_space_tpl.h>
namespace Genode {
template <typename> class Local_capability;
/**
* Return true if argument is a local capability
*/
static inline bool local(Untyped_capability const &cap)
{
return Capability_space::ipc_cap_data(cap).dst.socket == -1;
}
}
/**
* Local capability referring to a specific RPC interface
*
@ -44,7 +53,9 @@ class Genode::Local_capability
* \return a capability that represents the local object.
*/
static Capability<RPC_INTERFACE> local_cap(RPC_INTERFACE* ptr) {
Untyped_capability cap(Cap_dst_policy::Dst(), (long)ptr);
Untyped_capability cap =
Capability_space::import(invalid_rpc_destination(),
Rpc_obj_key((long)ptr));
return reinterpret_cap_cast<RPC_INTERFACE>(cap); }
/**
@ -57,4 +68,4 @@ class Genode::Local_capability
return reinterpret_cast<RPC_INTERFACE*>(c.local_name()); }
};
#endif /* _INCLUDE__BASE__LOCAL_CAPABILITY_H_ */
#endif /* _INCLUDE__BASE__INTERNAL__LOCAL_CAPABILITY_H_ */

View File

@ -0,0 +1,41 @@
/*
* \brief RPC destination type
* \author Norman Feske
* \date 2016-03-11
*/
/*
* Copyright (C) 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.
*/
#ifndef _INCLUDE__BASE__INTERNAL__RPC_DESTINATION_H_
#define _INCLUDE__BASE__INTERNAL__RPC_DESTINATION_H_
#include <base/output.h>
namespace Genode {
struct Rpc_destination
{
int socket = -1;
explicit Rpc_destination(int socket) : socket(socket) { }
Rpc_destination() { }
};
static inline Rpc_destination invalid_rpc_destination()
{
return Rpc_destination();
}
static void print(Output &out, Rpc_destination const &dst)
{
Genode::print(out, "socket=", dst.socket);
}
}
#endif /* _INCLUDE__BASE__INTERNAL__RPC_DESTINATION_H_ */

View File

@ -0,0 +1,31 @@
/*
* \brief Capability
* \author Norman Feske
* \date 2016-06-16
*/
/*
* Copyright (C) 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.
*/
#include <base/log.h>
/* base-internal includes */
#include <base/internal/capability_space_tpl.h>
using namespace Genode;
Native_capability::Raw Native_capability::raw() const
{
/*
* On Linux, we don't pass information as a 'raw' representation to
* child components. So this function remains unused. We still need
* to provide it to prevent link errors of noux, which relies on this
* function for implementing 'fork' (not supported on base-linux).
*/
return { { 0, 0, 0, 0 } };
}

View File

@ -24,6 +24,7 @@
#include <base/internal/native_thread.h>
#include <base/internal/ipc_server.h>
#include <base/internal/server_socket_pair.h>
#include <base/internal/capability_space_tpl.h>
/* Linux includes */
#include <linux_syscalls.h>
@ -33,6 +34,19 @@
using namespace Genode;
namespace {
struct Pid
{
int value;
Pid() : value(lx_getpid()) { }
void print(Output &out) const { Genode::print(out, "[", value, "]"); }
};
}
/*
* The request message layout is:
*
@ -60,12 +74,21 @@ struct Protocol_header
/* badges of the transferred capability arguments */
unsigned long badges[Msgbuf_base::MAX_CAPS_PER_MSG];
enum { INVALID_BADGE = ~0UL };
enum { INVALID_BADGE = ~1UL };
void *msg_start() { return &protocol_word; }
};
/*
* The INVALID_BADGE must be different from the representation of an
* invalid RPC object key because this key value is used by manually
* created NON-RPC-object capabilities (client_sd, server_sd, dataspace fd).
*/
static_assert((int)Protocol_header::INVALID_BADGE != (int)Rpc_obj_key::INVALID,
"ambigious INVALID_BADGE");
/******************************
** File-descriptor registry **
******************************/
@ -242,8 +265,11 @@ static void insert_sds_into_message(Message &msg,
Native_capability const &cap = snd_msgbuf.cap(i);
if (cap.valid()) {
msg.marshal_socket(cap.dst().socket);
header.badges[i] = cap.local_name();
Capability_space::Ipc_cap_data cap_data =
Capability_space::ipc_cap_data(cap);
msg.marshal_socket(cap_data.dst.socket);
header.badges[i] = cap_data.rpc_obj_key.value();
} else {
header.badges[i] = Protocol_header::INVALID_BADGE;
}
@ -277,7 +303,8 @@ static void extract_sds_from_message(unsigned start_index,
int const associated_sd = Genode::ep_sd_registry()->try_associate(sd, id);
buf.insert(Native_capability(Cap_dst_policy::Dst(associated_sd), badge));
buf.insert(Capability_space::import(Rpc_destination(associated_sd),
Rpc_obj_key(badge)));
if ((associated_sd >= 0) && (associated_sd != sd)) {
@ -374,10 +401,13 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
/* marshal capabilities contained in 'snd_msgbuf' */
insert_sds_into_message(snd_msg, snd_header, snd_msgbuf);
int const send_ret = lx_sendmsg(dst.dst().socket, snd_msg.msg(), 0);
int const dst_socket = Capability_space::ipc_cap_data(dst).dst.socket;
int const send_ret = lx_sendmsg(dst_socket, snd_msg.msg(), 0);
if (send_ret < 0) {
PRAW("[%d] lx_sendmsg to sd %d failed with %d in lx_call()",
lx_getpid(), dst.dst().socket, send_ret);
raw(Pid(), " lx_sendmsg to sd ", dst_socket,
" failed with ", send_ret, " in lx_call()");
for (;;);
throw Genode::Ipc_error();
}
@ -414,7 +444,9 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc,
Msgbuf_base &snd_msg)
{
try { lx_reply(caller.dst().socket, exc, snd_msg); } catch (Ipc_error) { }
int const reply_socket = Capability_space::ipc_cap_data(caller).dst.socket;
try { lx_reply(reply_socket, exc, snd_msg); } catch (Ipc_error) { }
}
@ -425,7 +457,7 @@ Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
{
/* when first called, there was no request yet */
if (last_caller.valid() && exc.value != Rpc_exception_code::INVALID_OBJECT)
lx_reply(last_caller.dst().socket, exc, reply_msg);
lx_reply(Capability_space::ipc_cap_data(last_caller).dst.socket, exc, reply_msg);
/*
* Block infinitely if called from the main thread. This may happen if the
@ -464,15 +496,15 @@ Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
/* start at offset 1 to skip the reply channel */
extract_sds_from_message(1, msg, header, request_msg);
typedef Native_capability::Dst Dst;
return Rpc_request(Native_capability(Dst(reply_socket), ~0UL), badge);
return Rpc_request(Capability_space::import(Rpc_destination(reply_socket),
Rpc_obj_key()), badge);
}
}
Ipc_server::Ipc_server()
:
Native_capability(Dst(-1), 0)
Native_capability(Capability_space::import(Rpc_destination(), Rpc_obj_key()))
{
/*
* If 'thread' is 0, the constructor was called by the main thread. By
@ -498,7 +530,8 @@ Ipc_server::Ipc_server()
/* override capability initialization */
*static_cast<Native_capability *>(this) =
Native_capability(Native_capability::Dst(socket_pair.client_sd), 0);
Capability_space::import(Rpc_destination(socket_pair.client_sd),
Rpc_obj_key());
}

View File

@ -22,6 +22,7 @@
#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;
@ -32,16 +33,18 @@ using namespace Genode;
size_t Region_map_mmap::_dataspace_size(Dataspace_capability ds)
{
if (ds.valid())
return Dataspace_client(ds).size();
if (local(ds))
return Local_capability<Dataspace>::deref(ds)->size();
return Dataspace_client(ds).size();
return Local_capability<Dataspace>::deref(ds)->size();
}
int Region_map_mmap::_dataspace_fd(Dataspace_capability ds)
{
return Linux_dataspace_client(ds).fd().dst().socket;
Untyped_capability fd_cap = Linux_dataspace_client(ds).fd();
return Capability_space::ipc_cap_data(fd_cap).dst.socket;
}
@ -126,12 +129,13 @@ static unsigned long get_env_ulong(const char *key)
static Parent_capability obtain_parent_cap()
{
long local_name = get_env_ulong("parent_local_name");
long const 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));
Untyped_capability parent_cap =
Capability_space::import(Rpc_destination(PARENT_SOCKET_HANDLE),
Rpc_obj_key(local_name));
return reinterpret_cap_cast<Parent>(parent_cap);
}
@ -178,8 +182,10 @@ namespace Genode {
Thread *thread = Thread::myself();
if (thread) {
socket_pair.server_sd = native_cpu.server_sd(thread->cap()).dst().socket;
socket_pair.client_sd = native_cpu.client_sd(thread->cap()).dst().socket;
Untyped_capability server_cap = native_cpu.server_sd(thread->cap());
Untyped_capability client_cap = native_cpu.client_sd(thread->cap());
socket_pair.server_sd = Capability_space::ipc_cap_data(server_cap).dst.socket;
socket_pair.client_sd = Capability_space::ipc_cap_data(client_cap).dst.socket;
thread->native_thread().socket_pair = socket_pair;
}
return socket_pair;

View File

@ -53,7 +53,7 @@ using namespace Genode;
static bool is_sub_rm_session(Dataspace_capability ds)
{
if (ds.valid())
if (ds.valid() && !local(ds))
return false;
return Local_capability<Dataspace>::deref(ds) != 0;