diff --git a/repos/base-nova/include/base/cap_map.h b/repos/base-nova/include/base/cap_map.h
index 41ab802ee0..3b5231b0be 100644
--- a/repos/base-nova/include/base/cap_map.h
+++ b/repos/base-nova/include/base/cap_map.h
@@ -60,7 +60,7 @@ namespace Genode {
Cap_range *find_by_id(addr_t);
- void inc(unsigned id, bool inc_if_one = false);
+ void inc(unsigned id);
void dec(unsigned id, bool revoke = true, unsigned num_log2 = 0);
addr_t alloc(size_t const num_log2);
@@ -88,10 +88,10 @@ namespace Genode {
bool valid() const { return _range; }
- inline void inc(bool inc_if_one = false)
+ inline void inc()
{
if (_range)
- _range->inc(_local_name - _range->base(), inc_if_one);
+ _range->inc(_local_name - _range->base());
}
inline void dec()
diff --git a/repos/base-nova/include/base/native_types.h b/repos/base-nova/include/base/native_types.h
index 246536bbf3..dade6aa975 100644
--- a/repos/base-nova/include/base/native_types.h
+++ b/repos/base-nova/include/base/native_types.h
@@ -60,10 +60,10 @@ namespace Genode {
protected:
- inline void _inc(bool inc_if_one = false) const
+ inline void _inc() const
{
Cap_index idx(cap_map()->find(local_name()));
- idx.inc(inc_if_one);
+ idx.inc();
}
inline void _dec() const
@@ -106,15 +106,6 @@ namespace Genode {
bool operator==(const Native_capability &o) const {
return local_name() == o.local_name(); }
- /**
- * Inhibit removal of capability from cap map if it's the last reference
- */
- void keep_if_last_reference()
- {
- if (valid())
- _inc(true);
- }
-
/**
* Copy constructor
*/
diff --git a/repos/base-nova/include/spec/32bit/nova/syscalls.h b/repos/base-nova/include/spec/32bit/nova/syscalls.h
index d345f9ad99..94bad1a928 100644
--- a/repos/base-nova/include/spec/32bit/nova/syscalls.h
+++ b/repos/base-nova/include/spec/32bit/nova/syscalls.h
@@ -298,21 +298,37 @@ namespace Nova {
* \param sm SM selector which gets an up() by the kernel if the
* memory of the current revoke invocation gets freed up
* (end of RCU period)
+ * \param kim keep_in_mdb - if set to true the kernel will make the
+ * resource inaccessible for solely for the specified pd.
+ * All already beforehand delegated resources will not be
+ * changed, e.g. revoked. All rights of the local resource
+ * will be removed (independent of what is specified by crd).
*/
ALWAYS_INLINE
inline uint8_t revoke(Crd crd, bool self = true, bool remote = false,
- mword_t pd = 0, mword_t sm = 0)
+ mword_t pd = 0, mword_t sm = 0, bool kim = false)
{
uint8_t flags = self ? 0x1 : 0;
if (remote)
flags |= 0x2;
+ if (kim)
+ flags |= 0x4;
mword_t value_crd = crd.value();
return syscall_5(NOVA_REVOKE, flags, sm, value_crd, pd);
}
+ /*
+ * Shortcut for revoke, where solely the local cap should be revoked and
+ * not all subsequent delegations of the local cap.
+ */
+ ALWAYS_INLINE
+ inline uint8_t drop(Crd crd) {
+ return revoke(crd, true, false, 0, 0, true); }
+
+
ALWAYS_INLINE
inline uint8_t lookup(Crd &crd)
{
diff --git a/repos/base-nova/include/spec/64bit/nova/syscalls.h b/repos/base-nova/include/spec/64bit/nova/syscalls.h
index 40063bfb45..80c68fb31e 100644
--- a/repos/base-nova/include/spec/64bit/nova/syscalls.h
+++ b/repos/base-nova/include/spec/64bit/nova/syscalls.h
@@ -250,21 +250,38 @@ namespace Nova {
* \param sm SM selector which gets an up() by the kernel if the
* memory of the current revoke invocation gets freed up
* (end of RCU period)
+ * \param kim keep_in_mdb - if set to true the kernel will make the
+ * resource inaccessible solely inside the specified pd.
+ * All already beforehand delegated resources will not be
+ * changed, e.g. revoked. All rights of the local resource
+ * will be removed (independent of what is specified by crd).
*/
ALWAYS_INLINE
inline uint8_t revoke(Crd crd, bool self = true, bool remote = false,
- mword_t pd = 0, mword_t sm = 0)
+ mword_t pd = 0, mword_t sm = 0, bool kim = false)
{
uint8_t flags = self ? 0x1 : 0;
if (remote)
flags |= 0x2;
+ if (kim)
+ flags |= 0x4;
+
mword_t value_crd = crd.value();
return syscall_5(NOVA_REVOKE, flags, sm, value_crd, pd);
}
+ /*
+ * Shortcut for revoke, where solely the local cap should be revoked and
+ * not all subsequent delegations of the local cap.
+ */
+ ALWAYS_INLINE
+ inline uint8_t drop(Crd crd) {
+ return revoke(crd, true, false, 0, 0, true); }
+
+
ALWAYS_INLINE
inline uint8_t lookup(Crd &crd)
{
diff --git a/repos/base-nova/ports/nova.hash b/repos/base-nova/ports/nova.hash
index 8ee2b74ac8..a675f6a8aa 100644
--- a/repos/base-nova/ports/nova.hash
+++ b/repos/base-nova/ports/nova.hash
@@ -1 +1 @@
-061565ecaea829f5a5ab48e39b4fae9148da7e4b
+bde8909f6367ea2767c54b85ddf90afc2e6baee8
diff --git a/repos/base-nova/ports/nova.port b/repos/base-nova/ports/nova.port
index 2e0f1333a4..0e29278868 100644
--- a/repos/base-nova/ports/nova.port
+++ b/repos/base-nova/ports/nova.port
@@ -4,7 +4,7 @@ DOWNLOADS := nova.git
# r9 branch - use r9_debug for more verbose kernel messages
URL(nova) := https://github.com/alex-ab/NOVA.git
-REV(nova) := 172fe0dc1b6228fec20e220d2524f25b1016f6ab
+REV(nova) := 8548c34df01504789b01f4e1a31b71e6d08a79c7
DIR(nova) := src/kernel/nova
PATCHES := $(wildcard $(REP_DIR)/patches/*.patch)
diff --git a/repos/base-nova/src/lib/base/cap_map.cc b/repos/base-nova/src/lib/base/cap_map.cc
index 5a85b15b96..6217eb6e98 100644
--- a/repos/base-nova/src/lib/base/cap_map.cc
+++ b/repos/base-nova/src/lib/base/cap_map.cc
@@ -42,15 +42,12 @@ Cap_range *Cap_range::find_by_id(addr_t id)
}
-void Cap_range::inc(unsigned id, bool inc_if_one)
+void Cap_range::inc(unsigned id)
{
bool failure = false;
{
Lock::Guard guard(_lock);
- if (inc_if_one && _cap_array[id] != 1)
- return;
-
if (_cap_array[id] + 1 == 0)
failure = true;
else
@@ -78,7 +75,7 @@ void Cap_range::dec(unsigned const id_start, bool revoke, unsigned num_log_2)
}
if (revoke && _cap_array[id] == 1)
- Nova::revoke(Nova::Obj_crd(_base + id, 0));
+ Nova::drop(Nova::Obj_crd(_base + id, 0));
_cap_array[id]--;
}
diff --git a/repos/base-nova/src/lib/base/rpc_entrypoint.cc b/repos/base-nova/src/lib/base/rpc_entrypoint.cc
index 7442f71400..ad4f786293 100644
--- a/repos/base-nova/src/lib/base/rpc_entrypoint.cc
+++ b/repos/base-nova/src/lib/base/rpc_entrypoint.cc
@@ -166,15 +166,6 @@ void Rpc_entrypoint::_activation_entry()
return;
}
- /*
- * Inhibit removal of capabilities sent as results of client requests.
- * This prevents the recursive revocation of NOVA portal caps and,
- * therefore, permits clients to use result capabilities after server
- * code dropped all references.
- */
- for (unsigned i = 0; i < ep._snd_buf.used_caps(); ++i)
- ep._snd_buf.cap(i).keep_if_last_reference();
-
/* dispatch request */
ep._snd_buf.reset();
try { exc = obj->dispatch(opcode, unmarshaller, ep._snd_buf); }
diff --git a/repos/base-nova/src/test/platform/ipc.cc b/repos/base-nova/src/test/platform/ipc.cc
new file mode 100644
index 0000000000..c3a819e495
--- /dev/null
+++ b/repos/base-nova/src/test/platform/ipc.cc
@@ -0,0 +1,59 @@
+/*
+ * \brief Helper classes to make raw Nova IPC calls which can't be expressed
+ * via the Genode base RPC abstractions
+ * \author Alexander Boettcher
+ *
+ */
+
+/*
+ * 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
+
+/* Genode includes */
+#include
+#include
+
+/* test specific includes */
+#include "server.h"
+
+using namespace Test;
+
+long Test::cap_void_manual(Genode::Native_capability dst,
+ Genode::Native_capability arg1,
+ Genode::addr_t &local_reply)
+{
+ Genode::Thread * myself = Genode::Thread::myself();
+ Nova::Utcb *utcb = reinterpret_cast(myself->utcb());
+
+ /* save original receive window */
+ Nova::Crd orig_crd = utcb->crd_rcv;
+
+ /* don't open receive window */
+ utcb->crd_rcv = Nova::Obj_crd();
+ /* not used on base-nova */
+ utcb->msg[0] = 0;
+ /* method number of RPC interface to be called on server side */
+ utcb->msg[1] = 0;
+ utcb->set_msg_word(2);
+
+ if (!arg1.valid())
+ return Genode::Rpc_exception_code::INVALID_OBJECT;
+
+ Nova::Obj_crd crd(arg1.local_name(), 0, arg1.dst().rights());
+ if (!utcb->append_item(crd, 0, false, false, false))
+ return Genode::Rpc_exception_code::INVALID_OBJECT;
+
+ Genode::uint8_t res = Nova::call(dst.local_name());
+
+ /* restore original receive window */
+ utcb->crd_rcv = orig_crd;
+
+ local_reply = utcb->msg[2];
+ return (res == Nova::NOVA_OK && utcb->msg_words() == 3)
+ ? utcb->msg[0] : Genode::Rpc_exception_code::INVALID_OBJECT;
+}
diff --git a/repos/base-nova/src/test/platform/main.cc b/repos/base-nova/src/test/platform/main.cc
index bd00ae80cf..f911ab658d 100644
--- a/repos/base-nova/src/test/platform/main.cc
+++ b/repos/base-nova/src/test/platform/main.cc
@@ -32,8 +32,236 @@ static unsigned failed = 0;
static unsigned check_pat = 1;
+static Genode::Cap_connection cap;
+
using namespace Genode;
+void test_translate()
+{
+ enum { STACK_SIZE = 4096 };
+ static Rpc_entrypoint ep(&cap, STACK_SIZE, "rpc_ep_translate");
+
+ Test::Component component;
+ Test::Capability session_cap = ep.manage(&component);
+ Test::Client client(session_cap);
+
+ Genode::addr_t local_name = Native_thread::INVALID_INDEX;
+
+ long rpc = Test::cap_void_manual(session_cap, session_cap, local_name);
+ if (rpc != Genode::Rpc_exception_code::SUCCESS ||
+ local_name == session_cap.local_name() ||
+ local_name == Native_thread::INVALID_INDEX)
+ {
+ failed ++;
+ PERR("%s: ipc call failed %lx", __func__, rpc);
+ ep.dissolve(&component);
+ return;
+ }
+
+ Genode::Native_capability copy1(local_name);
+
+ rpc = Test::cap_void_manual(session_cap, copy1, local_name);
+ if (rpc != Genode::Rpc_exception_code::SUCCESS ||
+ local_name == copy1.local_name() ||
+ local_name == Native_thread::INVALID_INDEX)
+ {
+ failed ++;
+ PERR("%s: ipc call failed %lx", __func__, rpc);
+ ep.dissolve(&component);
+ return;
+ }
+
+ Genode::Native_capability copy2(local_name);
+
+ PINF("delegation session_cap->copy1->copy2 0x%lx->0x%lx->0x%lx",
+ session_cap.local_name(), copy1.local_name(), copy2.local_name());
+
+ /* sanity checks translate which must work */
+ Genode::Native_capability got_cap = client.cap_cap(copy2.local_name());
+ if (got_cap.local_name() != copy1.local_name()) {
+ failed ++;
+ PERR("%u:%s translate failed", __LINE__, __func__);
+ ep.dissolve(&component);
+ return;
+ }
+
+ got_cap = client.cap_cap(copy1.local_name());
+ if (got_cap.local_name() != session_cap.local_name()) {
+ failed ++;
+ PERR("%u:%s translate failed", __LINE__, __func__);
+ ep.dissolve(&component);
+ return;
+ }
+
+ got_cap = client.cap_cap(session_cap.local_name());
+ if (got_cap.local_name() != session_cap.local_name()) {
+ failed ++;
+ PERR("%u:%s translate failed", __LINE__, __func__);
+ ep.dissolve(&component);
+ return;
+ }
+
+ /**
+ * Test special revoke by make the intermediate cap (copy1) inaccessible
+ * and check that translate of copy2 get the right results.
+ */
+
+ Nova::Obj_crd crd_ses(copy1.local_name(), 0);
+ enum { SELF = true, LOCAL_REVOKE = false, LOCAL_PD = 0, NO_BLOCKING = 0, KEEP_IN_MDB = true };
+ Nova::revoke(crd_ses, SELF, LOCAL_REVOKE, LOCAL_PD, NO_BLOCKING, KEEP_IN_MDB);
+
+ crd_ses = Nova::Obj_crd(copy1.local_name(), 0);
+ Genode::uint8_t res = Nova::lookup(crd_ses);
+ if (res != Nova::NOVA_OK || !crd_ses.is_null()) {
+ failed ++;
+ PERR("%u - lookup call failed err=%x", __LINE__, res);
+ ep.dissolve(&component);
+ return;
+ }
+
+ /* copy1 should be skipped and session_cap is the valid response */
+ got_cap = client.cap_cap(copy2.local_name());
+ if (got_cap.local_name() != session_cap.local_name()) {
+ failed ++;
+ PERR("%u:%s translate failed", __LINE__, __func__);
+ ep.dissolve(&component);
+ return;
+ }
+
+ ep.dissolve(&component);
+}
+
+void test_revoke()
+{
+ enum { STACK_SIZE = 4096 };
+ static Rpc_entrypoint ep(&cap, STACK_SIZE, "rpc_ep_revoke");
+
+ Test::Component component;
+ Test::Capability session_cap = ep.manage(&component);
+ Test::Client client(session_cap);
+
+ Genode::addr_t local_name = Native_thread::INVALID_INDEX;
+
+ long rpc = Test::cap_void_manual(session_cap, session_cap, local_name);
+ if (rpc != Genode::Rpc_exception_code::SUCCESS ||
+ local_name == session_cap.local_name() ||
+ local_name == Native_thread::INVALID_INDEX)
+ {
+ failed ++;
+ PERR("test_revoke ipc call failed %lx", rpc);
+ ep.dissolve(&component);
+ return;
+ }
+
+ Genode::Native_capability copy_session_cap(local_name);
+
+ rpc = Test::cap_void_manual(copy_session_cap, copy_session_cap, local_name);
+ if (rpc != Genode::Rpc_exception_code::SUCCESS ||
+ local_name == copy_session_cap.local_name() ||
+ local_name == Native_thread::INVALID_INDEX)
+ {
+ failed ++;
+ PERR("test_revoke ipc call failed %lx", rpc);
+ ep.dissolve(&component);
+ return;
+ }
+
+ Nova::Obj_crd crd_dst(local_name, 0);
+ Genode::uint8_t res = Nova::lookup(crd_dst);
+ if (res != Nova::NOVA_OK || crd_dst.base() != local_name || crd_dst.type() != 3 ||
+ crd_dst.order() != 0) {
+ failed ++;
+ PERR("%u - lookup call failed %x", __LINE__, res);
+ ep.dissolve(&component);
+ return;
+ }
+
+ Nova::Obj_crd crd_ses(copy_session_cap.local_name(), 0);
+ res = Nova::lookup(crd_ses);
+ if (res != Nova::NOVA_OK || crd_ses.base() != copy_session_cap.local_name() || crd_ses.type() != 3 ||
+ crd_ses.order() != 0) {
+ failed ++;
+ PERR("%u - lookup call failed err=%x is_null=%u", __LINE__, res, crd_ses.is_null());
+ ep.dissolve(&component);
+ return;
+ }
+
+ res = Nova::lookup(crd_dst);
+ if (res != Nova::NOVA_OK || crd_dst.base() != local_name || crd_dst.type() != 3 ||
+ crd_dst.order() != 0) {
+ failed ++;
+ PERR("%u - lookup call failed err=%x is_null=%u", __LINE__, res, crd_dst.is_null());
+ ep.dissolve(&component);
+ return;
+ }
+
+ crd_ses = Nova::Obj_crd(copy_session_cap.local_name(), 0);
+ enum { SELF = true, LOCAL_REVOKE = false, LOCAL_PD = 0, NO_BLOCKING = 0, KEEP_IN_MDB = true };
+ Nova::revoke(crd_ses, SELF, LOCAL_REVOKE, LOCAL_PD, NO_BLOCKING, KEEP_IN_MDB);
+
+ crd_ses = Nova::Obj_crd(copy_session_cap.local_name(), 0);
+ res = Nova::lookup(crd_ses);
+ if (res != Nova::NOVA_OK || !crd_ses.is_null()) {
+ failed ++;
+ PERR("%u - lookup call failed err=%x", __LINE__, res);
+ ep.dissolve(&component);
+ return;
+ }
+
+ res = Nova::lookup(crd_dst);
+ if (res != Nova::NOVA_OK || crd_dst.base() != local_name || crd_dst.type() != 3 ||
+ crd_dst.order() != 0) {
+ failed ++;
+ PERR("%u - lookup call failed err=%x is_null=%u", __LINE__, res, crd_dst.is_null());
+ ep.dissolve(&component);
+ return;
+ }
+
+ /*
+ * Request some other capability and place it on very same selector
+ * as used before by copy_session_cap
+ */
+ Genode::Thread * myself = Genode::Thread::myself();
+ Genode::Native_capability pager_cap(myself->native_thread().ec_sel + 1);
+ request_event_portal(pager_cap, copy_session_cap.local_name(), 0, 0);
+
+ /* check whether the requested cap before is valid and placed well */
+ crd_ses = Nova::Obj_crd(copy_session_cap.local_name(), 0);
+ res = Nova::lookup(crd_ses);
+ if (res != Nova::NOVA_OK || crd_ses.base() != copy_session_cap.local_name() ||
+ crd_ses.type() != 3 || crd_ses.order() != 0) {
+ failed ++;
+ PERR("%u - lookup call failed err=%x is_null=%u", __LINE__, res, crd_ses.is_null());
+ ep.dissolve(&component);
+ return;
+ }
+
+ /* revoke it */
+ Nova::revoke(crd_ses, SELF, LOCAL_REVOKE, LOCAL_PD, NO_BLOCKING);
+
+ /* the delegated cap to the client should still be there */
+ res = Nova::lookup(crd_dst);
+ if (res != Nova::NOVA_OK || crd_dst.base() != local_name || crd_dst.type() != 3 ||
+ crd_dst.order() != 0) {
+ failed ++;
+ PERR("%u - lookup call failed err=%x is_null=%u", __LINE__, res, crd_dst.is_null());
+ ep.dissolve(&component);
+ return;
+ }
+
+ /* kill the original session capability */
+ ep.dissolve(&component);
+ /* manually: cap.free_rpc_cap(session_cap); */
+
+ /* the delegated cap to the client should be now invalid */
+ res = Nova::lookup(crd_dst);
+ if (res != Nova::NOVA_OK || !crd_dst.is_null()) {
+ failed ++;
+ PERR("%u - lookup call failed err=%x is_null=%u", __LINE__, res, crd_dst.is_null());
+ return;
+ }
+}
+
void test_pat()
{
/* read out the tsc frequenzy once */
@@ -47,8 +275,7 @@ void test_pat()
enum { STACK_SIZE = 4096 };
- static Cap_connection cap;
- static Rpc_entrypoint ep(&cap, STACK_SIZE, "rpc_ep");
+ static Rpc_entrypoint ep(&cap, STACK_SIZE, "rpc_ep_pat");
Test::Component component;
Test::Capability session_cap = ep.manage(&component);
@@ -138,8 +365,7 @@ void test_server_oom()
enum { STACK_SIZE = 4096 };
- static Cap_connection cap;
- static Rpc_entrypoint ep(&cap, STACK_SIZE, "rpc_ep");
+ static Rpc_entrypoint ep(&cap, STACK_SIZE, "rpc_ep_oom");
Test::Component component;
Test::Capability session_cap = ep.manage(&component);
@@ -317,6 +543,12 @@ int main(int argc, char **argv)
/* test PAT kernel feature */
test_pat();
+ /* test special revoke */
+ test_revoke();
+
+ /* test translate together with special revoke */
+ test_translate();
+
/**
* Test to provoke out of memory during capability transfer of
* server/client.
diff --git a/repos/base-nova/src/test/platform/server.h b/repos/base-nova/src/test/platform/server.h
index 74e8576705..dfd0c87a36 100644
--- a/repos/base-nova/src/test/platform/server.h
+++ b/repos/base-nova/src/test/platform/server.h
@@ -21,7 +21,15 @@
#include
#include
-namespace Test { struct Session; struct Client; struct Component; }
+namespace Test {
+ struct Session;
+ struct Client;
+ struct Component;
+
+ long cap_void_manual(Genode::Native_capability dst,
+ Genode::Native_capability arg1,
+ Genode::addr_t &local_name);
+}
/**
* Test session interface definition
@@ -30,25 +38,31 @@ struct Test::Session : Genode::Session
{
static const char *service_name() { return "TEST"; }
- GENODE_RPC(Rpc_cap_void, bool, cap_void,
- Genode::Native_capability);
+ GENODE_RPC(Rpc_cap_void, bool, cap_void, Genode::Native_capability,
+ Genode::addr_t &);
GENODE_RPC(Rpc_void_cap, Genode::Native_capability,
void_cap);
+ GENODE_RPC(Rpc_cap_cap, Genode::Native_capability, cap_cap,
+ Genode::addr_t);
GENODE_RPC(Rpc_leak_utcb_address, Genode::addr_t, leak_utcb_address);
- GENODE_RPC_INTERFACE(Rpc_cap_void, Rpc_void_cap, Rpc_leak_utcb_address);
+ GENODE_RPC_INTERFACE(Rpc_cap_void, Rpc_void_cap, Rpc_cap_cap,
+ Rpc_leak_utcb_address);
};
struct Test::Client : Genode::Rpc_client
{
Client(Capability cap) : Rpc_client(cap) { }
- bool cap_void(Genode::Native_capability cap) {
- return call(cap); }
+ bool cap_void(Genode::Native_capability cap, Genode::addr_t &local_name) {
+ return call(cap, local_name); }
Genode::Native_capability void_cap() {
return call(); }
+ Genode::Native_capability cap_cap(Genode::addr_t cap) {
+ return call(cap); }
+
Genode::addr_t leak_utcb_address() {
return call(); }
};
@@ -56,9 +70,11 @@ struct Test::Client : Genode::Rpc_client
struct Test::Component : Genode::Rpc_object
{
/* Test to transfer a object capability during send */
- bool cap_void(Genode::Native_capability);
+ bool cap_void(Genode::Native_capability, Genode::addr_t &);
/* Test to transfer a object capability during reply */
Genode::Native_capability void_cap();
+ /* Test to transfer a specific object capability during reply */
+ Genode::Native_capability cap_cap(Genode::addr_t);
/* Leak utcb address of entrypoint to manipulate utcb receive window */
Genode::addr_t leak_utcb_address();
};
@@ -68,7 +84,11 @@ namespace Test { typedef Genode::Capability Capability; }
/**
* Session implementation
*/
-bool Test::Component::cap_void(Genode::Native_capability got_cap) {
+inline bool Test::Component::cap_void(Genode::Native_capability got_cap,
+ Genode::addr_t &local_name)
+{
+ local_name = got_cap.local_name();
+
if (!got_cap.valid())
return false;
@@ -79,7 +99,7 @@ bool Test::Component::cap_void(Genode::Native_capability got_cap) {
return true;
}
-Genode::Native_capability Test::Component::void_cap() {
+inline Genode::Native_capability Test::Component::void_cap() {
Genode::Native_capability send_cap = cap();
/* XXX this code does does no longer work since the removal of 'solely_map' */
@@ -91,5 +111,8 @@ Genode::Native_capability Test::Component::void_cap() {
return send_cap;
}
-Genode::addr_t Test::Component::leak_utcb_address() {
+inline Genode::addr_t Test::Component::leak_utcb_address() {
return reinterpret_cast(Genode::Thread::myself()->utcb()); }
+
+inline Genode::Native_capability Test::Component::cap_cap(Genode::addr_t cap) {
+ return Genode::Native_capability(cap); }
diff --git a/repos/base-nova/src/test/platform/target.mk b/repos/base-nova/src/test/platform/target.mk
index 327dd04d62..e4820e69db 100644
--- a/repos/base-nova/src/test/platform/target.mk
+++ b/repos/base-nova/src/test/platform/target.mk
@@ -1,3 +1,3 @@
TARGET = test-platform
-SRC_CC = main.cc
+SRC_CC = main.cc ipc.cc
LIBS = base config