diff --git a/repos/base-hw/include/base/ipc_msgbuf.h b/repos/base-hw/include/base/ipc_msgbuf.h
index bb7b166456..e9b370dc11 100644
--- a/repos/base-hw/include/base/ipc_msgbuf.h
+++ b/repos/base-hw/include/base/ipc_msgbuf.h
@@ -1,11 +1,12 @@
/*
* \brief IPC message buffers
* \author Martin Stein
+ * \author Stefan Kalkowski
* \date 2012-01-03
*/
/*
- * Copyright (C) 2012-2013 Genode Labs GmbH
+ * Copyright (C) 2012-2015 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.
@@ -14,58 +15,118 @@
#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
#define _INCLUDE__BASE__IPC_MSGBUF_H_
+#include
+#include
+
namespace Genode
{
+ class Native_utcb;
+
/**
* IPC message buffer layout
*/
- class Msgbuf_base
- {
- protected:
-
- size_t _size; /* buffer size in bytes */
-
- public:
-
- char buf[]; /* begin of actual message buffer */
-
- /*************************************************
- ** 'buf' must be the last member of this class **
- *************************************************/
-
- /**
- * Return size of message buffer
- */
- inline size_t size() const { return _size; }
-
- /**
- * Return address of message buffer
- */
- inline void *addr() { return &buf[0]; }
- };
+ class Msgbuf_base;
/**
* Instance of IPC message buffer with specified buffer size
*
* 'Msgbuf_base' must be the last class this class inherits from.
*/
- template
- class Msgbuf : public Msgbuf_base
- {
- public:
-
- /**************************************************
- ** 'buf' must be the first member of this class **
- **************************************************/
-
- char buf[BUF_SIZE];
-
- /**
- * Constructor
- */
- Msgbuf() { _size = BUF_SIZE; }
- };
+ template class Msgbuf;
}
-#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
+class Genode::Msgbuf_base
+{
+ public:
+
+ enum { MAX_CAP_ARGS = 4 };
+
+ private:
+
+ friend class Native_utcb;
+
+ size_t _size; /* buffer size in bytes */
+ Native_capability _caps[MAX_CAP_ARGS]; /* capability buffer */
+ size_t _snd_cap_cnt = 0; /* capability counter */
+ size_t _rcv_cap_cnt = 0; /* capability counter */
+
+ public:
+
+ /*************************************************
+ ** 'buf' must be the last member of this class **
+ *************************************************/
+
+ char buf[]; /* begin of actual message buffer */
+
+ Msgbuf_base(size_t size) : _size(size) { }
+
+ void const * base() const { return &buf; }
+
+ /**
+ * Return size of message buffer
+ */
+ size_t size() const { return _size; }
+
+ /**
+ * Return address of message buffer
+ */
+ void *addr() { return &buf[0]; }
+
+ /**
+ * Reset capability buffer.
+ */
+ void reset()
+ {
+ _snd_cap_cnt = 0;
+ _rcv_cap_cnt = 0;
+ }
+
+ /**
+ * Return how many capabilities are accepted by this message buffer
+ */
+ size_t cap_rcv_window() { return _rcv_cap_cnt; }
+
+ /**
+ * Set how many capabilities are accepted by this message buffer
+ */
+ void cap_rcv_window(size_t cnt) { _rcv_cap_cnt = cnt; }
+
+ /**
+ * Add capability to buffer
+ */
+ void cap_add(Native_capability const &cap)
+ {
+ if (_snd_cap_cnt < MAX_CAP_ARGS)
+ _caps[_snd_cap_cnt++] = cap;
+ }
+
+ /**
+ * Return last capability from buffer.
+ */
+ Native_capability cap_get()
+ {
+ return (_rcv_cap_cnt < _snd_cap_cnt)
+ ? _caps[_rcv_cap_cnt++] : Native_capability();
+ }
+};
+
+
+template
+class Genode::Msgbuf : public Genode::Msgbuf_base
+{
+ public:
+
+ /**************************************************
+ ** 'buf' must be the first member of this class **
+ **************************************************/
+
+ char buf[BUF_SIZE];
+
+ /**
+ * Constructor
+ */
+ Msgbuf() : Msgbuf_base(BUF_SIZE) { }
+};
+
+#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
diff --git a/repos/base-hw/include/base/native_capability.h b/repos/base-hw/include/base/native_capability.h
new file mode 100644
index 0000000000..4d77c31fd6
--- /dev/null
+++ b/repos/base-hw/include/base/native_capability.h
@@ -0,0 +1,95 @@
+/*
+ * \brief Native capability of base-hw
+ * \author Stefan Kalkowski
+ * \date 2015-05-15
+ */
+
+/*
+ * Copyright (C) 2015 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 _BASE__NATIVE_CAPABILITY_H_
+#define _BASE__NATIVE_CAPABILITY_H_
+
+/* Genode includes */
+#include
+#include
+
+namespace Genode { class Native_capability; }
+
+
+class Genode::Native_capability
+{
+ public:
+
+ using Dst = Kernel::capid_t;
+
+ private:
+
+ Dst _dst;
+
+ void _inc() const;
+ void _dec() const;
+
+ public:
+
+ struct Raw
+ {
+ Dst dst;
+
+ /* obsolete in base-hw, but still used in generic code path */
+ addr_t local_name;
+ };
+
+ /**
+ * Create an invalid capability
+ */
+ Native_capability() : _dst(Kernel::cap_id_invalid()) { }
+
+ /**
+ * Create a capability out of a kernel's capability id
+ */
+ Native_capability(Kernel::capid_t dst) : _dst(dst) { _inc(); }
+
+ /**
+ * Create a capability from another one
+ */
+ Native_capability(const Native_capability &o) : _dst(o._dst) { _inc(); }
+
+ ~Native_capability() { _dec(); }
+
+ /**
+ * Returns true if it is a valid capability otherwise false
+ */
+ bool valid() const { return (_dst != Kernel::cap_id_invalid()); }
+
+
+ /*****************
+ ** Accessors **
+ *****************/
+
+ addr_t local_name() const { return _dst; }
+ Dst dst() const { return _dst; }
+
+
+ /**************************
+ ** Operator overloads **
+ **************************/
+
+ bool operator==(const Native_capability &o) const {
+ return _dst == _dst; }
+
+ Native_capability& operator=(const Native_capability &o)
+ {
+ if (this == &o) return *this;
+ _dec();
+ _dst = o._dst;
+ _inc();
+ return *this;
+ }
+};
+
+#endif /* _BASE__NATIVE_CAPABILITY_H_ */
diff --git a/repos/base-hw/include/base/native_env.h b/repos/base-hw/include/base/native_env.h
new file mode 100644
index 0000000000..3deeba7803
--- /dev/null
+++ b/repos/base-hw/include/base/native_env.h
@@ -0,0 +1,28 @@
+/*
+ * \brief Native extensions of the Genode environment
+ * \author Stefan Kalkowski
+ * \date 2015-05-20
+ */
+
+/*
+ * Copyright (C) 2015 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 _BASE__NATIVE_ENV_H_
+#define _BASE__NATIVE_ENV_H_
+
+/* Genode includes */
+#include
+
+namespace Genode
+{
+ /**
+ * Upgrade quota of the PD session within my Genode environment
+ */
+ void upgrade_pd_session_quota(Genode::size_t);
+};
+
+#endif /**_BASE__NATIVE_ENV_H_ */
diff --git a/repos/base-hw/include/base/native_types.h b/repos/base-hw/include/base/native_types.h
index 55de43fe88..2a8a188880 100644
--- a/repos/base-hw/include/base/native_types.h
+++ b/repos/base-hw/include/base/native_types.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2012-2013 Genode Labs GmbH
+ * Copyright (C) 2012-2015 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.
@@ -16,300 +16,170 @@
#define _BASE__NATIVE_TYPES_H_
/* Genode includes */
-#include
-#include
-#include
-#include
-
-/* base-hw includes */
#include
+#include
+#include
namespace Genode
{
class Platform_thread;
+ class Native_thread;
- typedef unsigned Native_thread_id;
-
- struct Native_thread
- {
- Platform_thread * platform_thread;
- Native_thread_id thread_id;
- };
+ using Native_thread_id = Kernel::capid_t;
typedef int Native_connection_state;
- /* FIXME needs to be MMU dependent */
- enum { MIN_MAPPING_SIZE_LOG2 = 12 };
-
- /**
- * Return kernel thread-name of the caller
- */
- Native_thread_id thread_get_my_native_id();
-
- /**
- * Return an invalid kernel thread-name
- */
- inline Native_thread_id thread_invalid_id() { return 0; }
-
- /**
- * Data bunch with variable size that is communicated between threads
- *
- * \param MAX_SIZE maximum size the object is allowed to take
- */
- template
- struct Message_tpl;
-
/**
* Information that a thread creator hands out to a new thread
*/
class Start_info;
/**
- * Info that a core-thread creator hands out to Platform_thread::start
+ * Coherent address region
*/
- class Core_start_info;
+ struct Native_region;
+
+ struct Native_config;
+
+ struct Native_pd_args { };
+
+ /**
+ * Get the the minimal supported page-size log 2
+ */
+ constexpr size_t get_page_size_log2() { return 12; }
+
+ /**
+ * Get the the minimal supported page-size
+ */
+ constexpr size_t get_page_size() { return 1 << get_page_size_log2(); }
/**
* Memory region that is exclusive to every thread and known by the kernel
*/
class Native_utcb;
-
- struct Cap_dst_policy
- {
- typedef Native_thread_id Dst;
-
- /**
- * Validate capability destination
- */
- static bool valid(Dst pt) { return pt != 0; }
-
- /**
- * Get invalid capability destination
- */
- static Dst invalid() { return 0; }
-
- /**
- * Copy capability 'src' to a given memory destination 'dst'
- */
- static void
- copy(void * dst, Native_capability_tpl * src);
- };
-
- typedef Native_capability_tpl Native_capability;
-
- /**
- * Coherent address region
- */
- struct Native_region
- {
- addr_t base;
- size_t size;
- };
-
- struct Native_config
- {
- /**
- * Thread-context area configuration.
- */
- static constexpr addr_t context_area_virtual_base() {
- return 0xe0000000UL; }
- static constexpr addr_t context_area_virtual_size() {
- return 0x10000000UL; }
-
- /**
- * Size of virtual address region holding the context of one thread
- */
- static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
- };
-
- struct Native_pd_args { };
}
-template
-class Genode::Message_tpl
+
+struct Genode::Native_thread
{
- private:
-
- size_t _data_size;
- uint8_t _data[];
-
- /**
- * Return size of payload-preceding meta data
- */
- size_t _header_size() const { return (addr_t)_data - (addr_t)this; }
-
- /**
- * Return maximum payload size
- */
- size_t _max_data_size() const { return MAX_SIZE - _header_size(); }
-
- /**
- * Return size of header and current payload
- */
- size_t _size() const { return _header_size() + _data_size; }
-
- public:
-
- /**
- * Get properties of receive buffer
- *
- * \return buf_base base of receive buffer
- * \return buf_size size of receive buffer
- */
- void buffer_info(void * & buf_base, size_t & buf_size) const
- {
- buf_base = (void *)this;
- buf_size = MAX_SIZE;
- }
-
- /**
- * Get properties of request message and receive buffer
- *
- * \return buf_base base of receive buffer and request message
- * \return buf_size size of receive buffer
- * \return msg_size size of request message
- */
- void request_info(void * & buf_base, size_t & buf_size,
- size_t & msg_size) const
- {
- buf_base = (void *)this;
- buf_size = MAX_SIZE;
- msg_size = _size();
- }
-
- /**
- * Get properties of reply message
- *
- * \return msg_base base of reply message
- * \return msg_size size of reply message
- */
- void reply_info(void * & msg_base, size_t & msg_size) const
- {
- msg_base = (void *)this;
- msg_size = _size();
- }
-
- /**
- * Install message that shall be send
- *
- * \param data base of payload
- * \param data_size size of payload
- * \param name local name that shall be the first payload word
- */
- void prepare_send(void * const data, size_t data_size,
- unsigned long const name)
- {
- /* limit data size */
- if (data_size > _max_data_size()) {
- Kernel::log() << "oversized message outgoing\n";
- data_size = _max_data_size();
- }
- /* copy data */
- *(unsigned long *)_data = name;
- void * const data_dst = (void *)((addr_t)_data + sizeof(name));
- void * const data_src = (void *)((addr_t)data + sizeof(name));
- memcpy(data_dst, data_src, data_size - sizeof(name));
- _data_size = data_size;
- }
-
- /**
- * Read out message that was received
- *
- * \param buf_base base of read buffer
- * \param buf_size size of read buffer
- */
- void finish_receive(void * const buf_base, size_t const buf_size)
- {
- /* limit data size */
- if (_data_size > buf_size) {
- Kernel::log() << "oversized message incoming\n";
- _data_size = buf_size;
- }
- /* copy data */
- memcpy(buf_base, _data, _data_size);
- }
+ Platform_thread * platform_thread;
+ Native_capability cap;
};
-class Genode::Start_info
+
+/**
+ * Coherent address region
+ */
+struct Genode::Native_region
{
- private:
-
- Native_thread_id _thread_id;
- Native_capability _utcb_ds;
-
- public:
-
- /**
- * Set-up valid startup message
- *
- * \param thread_id kernel name of the thread that is started
- */
- void init(Native_thread_id const thread_id,
- Native_capability const & utcb_ds)
- {
- _thread_id = thread_id;
- _utcb_ds = utcb_ds;
- }
-
-
- /***************
- ** Accessors **
- ***************/
-
- Native_thread_id thread_id() const { return _thread_id; }
- Native_capability utcb_ds() const { return _utcb_ds; }
+ addr_t base;
+ size_t size;
};
-class Genode::Core_start_info
+
+struct Genode::Native_config
{
- private:
+ /**
+ * Thread-context area configuration.
+ */
+ static constexpr addr_t context_area_virtual_base() {
+ return 0xe0000000UL; }
+ static constexpr addr_t context_area_virtual_size() {
+ return 0x10000000UL; }
- unsigned _cpu_id;
-
- public:
-
- /**
- * Set-up valid core startup-message for starting on 'cpu'
- */
- void init(unsigned const cpu) { _cpu_id = cpu; }
-
-
- /***************
- ** Accessors **
- ***************/
-
- unsigned cpu_id() const { return _cpu_id; }
+ /**
+ * Size of virtual address region holding the context of one thread
+ */
+ static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
};
+
class Genode::Native_utcb
{
+ public:
+
+ enum { MAX_CAP_ARGS = Msgbuf_base::MAX_CAP_ARGS};
+
+ enum Offsets { PARENT, UTCB_DATASPACE, THREAD_MYSELF };
+
private:
- uint8_t _data[1 << MIN_MAPPING_SIZE_LOG2];
+ Kernel::capid_t _caps[MAX_CAP_ARGS]; /* capability buffer */
+ size_t _cap_cnt = 0; /* capability counter */
+ size_t _size = 0; /* bytes to transfer */
+ uint8_t _buf[get_page_size() - sizeof(_caps) -
+ sizeof(_cap_cnt) - sizeof(_size)];
public:
- typedef Message_tpl Message;
-
-
- /***************
- ** Accessors **
- ***************/
-
- Message * message() const { return (Message *)_data; }
-
- Start_info * start_info() const { return (Start_info *)_data; }
-
- Core_start_info * core_start_info() const
+ Native_utcb& operator= (const Native_utcb &o)
{
- return (Core_start_info *)_data;
+ _cap_cnt = 0;
+ _size = o._size;
+ memcpy(_buf, o._buf, _size);
+ return *this;
}
- size_t size() const { return sizeof(_data)/sizeof(_data[0]); }
+ /**
+ * Set the destination capability id (server object identity)
+ */
+ void destination(Kernel::capid_t id) {
+ *reinterpret_cast(_buf) = id; }
- void * base() const { return (void *)_data; }
+ /**
+ * Return the count of capabilities in the UTCB
+ */
+ size_t cap_cnt() { return _cap_cnt; }
+
+ /**
+ * Set the count of capabilities in the UTCB
+ */
+ void cap_cnt(size_t cnt) { _cap_cnt = cnt; }
+
+ /**
+ * Return the start address of the payload data
+ */
+ void const * base() const { return &_buf; }
+
+ /**
+ * Copy data from the message buffer 'o' to this UTCB
+ */
+ void copy_from(Msgbuf_base &o, size_t size)
+ {
+ _size = size;
+
+ _cap_cnt = o._snd_cap_cnt;
+ for (unsigned i = 0; i < _cap_cnt; i++)
+ _caps[i] = o._caps[i].dst();
+
+ memcpy(_buf, o.buf, min(_size, o._size));
+ }
+
+ /**
+ * Copy data from this UTCB to the message buffer 'o'
+ */
+ void copy_to(Msgbuf_base &o)
+ {
+ o._snd_cap_cnt = _cap_cnt;
+ for (unsigned i = 0; i < _cap_cnt; i++) o._caps[i] = _caps[i];
+
+ memcpy(o.buf, _buf, min(_size, o._size));
+ }
+
+ /**
+ * Return the capability id at index 'i'
+ */
+ Kernel::capid_t cap_get(unsigned i) {
+ return (i < _cap_cnt) ? _caps[i] : Kernel::cap_id_invalid(); }
+
+ /**
+ * Set the capability id 'cap_id' at the next index
+ */
+ void cap_add(Kernel::capid_t cap_id) {
+ if (_cap_cnt < MAX_CAP_ARGS) _caps[_cap_cnt++] = cap_id; }
};
+
namespace Genode
{
static constexpr addr_t VIRT_ADDR_SPACE_START = 0x1000;
@@ -319,9 +189,8 @@ namespace Genode
{
return (Native_utcb *)
((VIRT_ADDR_SPACE_START + VIRT_ADDR_SPACE_SIZE - sizeof(Native_utcb))
- & ~((1 << MIN_MAPPING_SIZE_LOG2) - 1));
+ & ~(get_page_size() - 1));
}
}
#endif /* _BASE__NATIVE_TYPES_H_ */
-
diff --git a/repos/base-hw/include/cap_session/connection.h b/repos/base-hw/include/cap_session/connection.h
new file mode 100644
index 0000000000..49e6c0965a
--- /dev/null
+++ b/repos/base-hw/include/cap_session/connection.h
@@ -0,0 +1,33 @@
+/*
+ * \brief Connection to CAP service
+ * \author Stefan Kalkowski
+ * \author Norman Feske
+ * \date 2015-05-20
+ *
+ * This is a shadow copy of the generic header in base,
+ * due to higher memory donation requirements in base-hw
+ */
+
+/*
+ * Copyright (C) 2015 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__CAP_SESSION__CONNECTION_H_
+#define _INCLUDE__CAP_SESSION__CONNECTION_H_
+
+#include
+#include
+
+namespace Genode { struct Cap_connection; }
+
+
+struct Genode::Cap_connection : Connection, Cap_session_client
+{
+ Cap_connection() : Connection(session("ram_quota=8K")),
+ Cap_session_client(cap()) { }
+};
+
+#endif /* _INCLUDE__CAP_SESSION__CONNECTION_H_ */
diff --git a/repos/base-hw/include/kernel/interface.h b/repos/base-hw/include/kernel/interface.h
index 79c6b6ab29..71c9ebbc2a 100644
--- a/repos/base-hw/include/kernel/interface.h
+++ b/repos/base-hw/include/kernel/interface.h
@@ -17,18 +17,13 @@
/* base-hw includes */
#include
-namespace Genode
-{
- class Native_utcb;
- class Platform_pd;
-}
-
namespace Kernel
{
- typedef Genode::addr_t addr_t;
- typedef Genode::size_t size_t;
- typedef Genode::Platform_pd Platform_pd;
- typedef Genode::Native_utcb Native_utcb;
+ using addr_t = Genode::addr_t;
+ using size_t = Genode::size_t;
+ using capid_t = Genode::uint16_t;
+
+ constexpr capid_t cap_id_invalid() { return 0; }
/**
* Kernel names of the kernel calls
@@ -47,6 +42,7 @@ namespace Kernel
constexpr Call_arg call_id_print_char() { return 11; }
constexpr Call_arg call_id_update_data_region() { return 12; }
constexpr Call_arg call_id_update_instr_region() { return 13; }
+ constexpr Call_arg call_id_delete_cap() { return 14; }
/*****************************************************************
@@ -97,11 +93,11 @@ namespace Kernel
/**
* Cancel blocking of a thread of the current domain if possible
*
- * \param thread_id kernel name of the targeted thread
+ * \param thread_id capability id of the targeted thread
*
* \return wether thread was in a cancelable blocking beforehand
*/
- inline bool resume_local_thread(unsigned const thread_id)
+ inline bool resume_local_thread(capid_t const thread_id)
{
return call(call_id_resume_local_thread(), thread_id);
}
@@ -110,12 +106,12 @@ namespace Kernel
/**
* Let the current thread give up its remaining timeslice
*
- * \param thread_id kernel name of the benefited thread
+ * \param thread_id capability id of the benefited thread
*
* If thread_id is valid the call will resume the targeted thread
* additionally.
*/
- inline void yield_thread(unsigned const thread_id)
+ inline void yield_thread(capid_t const thread_id)
{
call(call_id_yield_thread(), thread_id);
}
@@ -145,38 +141,43 @@ namespace Kernel
/**
* Send request message and await receipt of corresponding reply message
*
- * \param thread_id kernel name of targeted thread
+ * \param thread_id capability id of targeted thread
*
* \retval 0 succeeded
* \retval -1 failed
+ * \retval -2 failed due to out-of-memory for capability reception
*
* If the call returns successful, the received message is located at the
* base of the callers userland thread-context.
*/
- inline int send_request_msg(unsigned const thread_id)
+ inline int send_request_msg(capid_t const thread_id, unsigned rcv_caps)
{
- return call(call_id_send_request_msg(), thread_id);
+ return call(call_id_send_request_msg(), thread_id, rcv_caps);
}
/**
* Await receipt of request message
*
+ * \param rcv_caps number of capabilities willing to accept
+ *
* \retval 0 succeeded
- * \retval -1 failed
+ * \retval -1 canceled
+ * \retval -2 failed due to out-of-memory for capability reception
*
* If the call returns successful, the received message is located at the
* base of the callers userland thread-context.
*/
- inline int await_request_msg()
+ inline int await_request_msg(unsigned rcv_caps)
{
- return call(call_id_await_request_msg());
+ return call(call_id_await_request_msg(), rcv_caps);
}
/**
* Reply to lastly received request message
*
+ * \param rcv_caps number of capabilities to accept when awaiting again
* \param await_request_msg wether the call shall await a request message
*
* \retval 0 await_request_msg == 0 or request-message receipt succeeded
@@ -185,9 +186,9 @@ namespace Kernel
* If the call returns successful and await_request_msg == 1, the received
* message is located at the base of the callers userland thread-context.
*/
- inline int send_reply_msg(bool const await_request_msg)
+ inline int send_reply_msg(unsigned rcv_caps, bool const await_request_msg)
{
- return call(call_id_send_reply_msg(), await_request_msg);
+ return call(call_id_send_reply_msg(), rcv_caps, await_request_msg);
}
@@ -206,7 +207,7 @@ namespace Kernel
/**
* Await any context of a receiver and optionally ack a context before
*
- * \param receiver_id kernel name of the targeted signal receiver
+ * \param receiver_id capability id of the targeted signal receiver
*
* \retval 0 suceeded
* \retval -1 failed
@@ -221,7 +222,7 @@ namespace Kernel
* deliver again unless its last delivery has been acknowledged via
* ack_signal.
*/
- inline int await_signal(unsigned const receiver_id)
+ inline int await_signal(capid_t const receiver_id)
{
return call(call_id_await_signal(), receiver_id);
}
@@ -230,12 +231,12 @@ namespace Kernel
/**
* Return wether any context of a receiver is pending
*
- * \param receiver kernel name of the targeted signal receiver
+ * \param receiver capability id of the targeted signal receiver
*
* \retval 0 none of the contexts is pending or the receiver doesn't exist
* \retval 1 a context of the signal receiver is pending
*/
- inline bool signal_pending(unsigned const receiver)
+ inline bool signal_pending(capid_t const receiver)
{
return call(call_id_signal_pending(), receiver);
}
@@ -244,13 +245,13 @@ namespace Kernel
/**
* Trigger a specific signal context
*
- * \param context kernel name of the targeted signal context
+ * \param context capability id of the targeted signal context
* \param num how often the context shall be triggered by this call
*
* \retval 0 suceeded
* \retval -1 failed
*/
- inline int submit_signal(unsigned const context, unsigned const num)
+ inline int submit_signal(capid_t const context, unsigned const num)
{
return call(call_id_submit_signal(), context, num);
}
@@ -259,9 +260,9 @@ namespace Kernel
/**
* Acknowledge the processing of the last delivery of a signal context
*
- * \param context kernel name of the targeted signal context
+ * \param context capability id of the targeted signal context
*/
- inline void ack_signal(unsigned const context)
+ inline void ack_signal(capid_t const context)
{
call(call_id_ack_signal(), context);
}
@@ -270,15 +271,25 @@ namespace Kernel
/**
* Halt processing of a signal context synchronously
*
- * \param context kernel name of the targeted signal context
+ * \param context capability id of the targeted signal context
*
* \retval 0 suceeded
* \retval -1 failed
*/
- inline int kill_signal_context(unsigned const context)
+ inline int kill_signal_context(capid_t const context)
{
return call(call_id_kill_signal_context(), context);
}
+
+ /**
+ * Delete a capability id
+ *
+ * \param cap capability id to delete
+ */
+ inline void delete_cap(capid_t const cap)
+ {
+ call(call_id_delete_cap(), cap);
+ }
}
#endif /* _KERNEL__INTERFACE_H_ */
diff --git a/repos/base-hw/include/pd_session/connection.h b/repos/base-hw/include/pd_session/connection.h
new file mode 100644
index 0000000000..baa96b9c87
--- /dev/null
+++ b/repos/base-hw/include/pd_session/connection.h
@@ -0,0 +1,42 @@
+/*
+ * \brief Connection to PD service
+ * \author Stefan Kalkowski
+ * \author Norman Feske
+ * \date 2015-05-20
+ *
+ * This is a shadow copy of the generic header in base,
+ * due to higher memory donation requirements in base-hw
+ */
+
+/*
+ * Copyright (C) 2015 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__PD_SESSION__CONNECTION_H_
+#define _INCLUDE__PD_SESSION__CONNECTION_H_
+
+#include
+#include
+
+namespace Genode { struct Pd_connection; }
+
+
+struct Genode::Pd_connection : Connection, Pd_session_client
+{
+ enum { RAM_QUOTA = 20*1024 };
+
+ /**
+ * Constructor
+ *
+ * \param label session label
+ */
+ Pd_connection(char const *label = "", Native_pd_args const *pd_args = 0)
+ : Connection(session("ram_quota=%u, label=\"%s\"",
+ RAM_QUOTA, label)),
+ Pd_session_client(cap()) { }
+};
+
+#endif /* _INCLUDE__PD_SESSION__CONNECTION_H_ */
diff --git a/repos/base-hw/include/signal_session/connection.h b/repos/base-hw/include/signal_session/connection.h
new file mode 100644
index 0000000000..1b6abb51d2
--- /dev/null
+++ b/repos/base-hw/include/signal_session/connection.h
@@ -0,0 +1,35 @@
+/*
+ * \brief Connection to signal service
+ * \author Stefan Kalkowski
+ * \author Norman Feske
+ * \date 2015-05-20
+ *
+ * This is a shadow copy of the generic header in base,
+ * due to higher memory donation requirements in base-hw
+ */
+
+/*
+ * Copyright (C) 2015 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__SIGNAL_SESSION__CONNECTION_H_
+#define _INCLUDE__SIGNAL_SESSION__CONNECTION_H_
+
+#include
+#include
+
+namespace Genode { struct Signal_connection; }
+
+
+struct Genode::Signal_connection : Connection,
+ Signal_session_client
+{
+ Signal_connection()
+ : Connection(session("ram_quota=32K")),
+ Signal_session_client(cap()) { }
+};
+
+#endif /* _INCLUDE__CAP_SESSION__CONNECTION_H_ */
diff --git a/repos/base-hw/lib/mk/base-common.inc b/repos/base-hw/lib/mk/base-common.inc
index e267eabfe2..250da6d98a 100644
--- a/repos/base-hw/lib/mk/base-common.inc
+++ b/repos/base-hw/lib/mk/base-common.inc
@@ -10,7 +10,6 @@ LIBS += cxx
# add C++ sources
SRC_CC += ipc/ipc.cc
-SRC_CC += ipc/ipc_marshal_cap.cc
SRC_CC += avl_tree/avl_tree.cc
SRC_CC += allocator/slab.cc
SRC_CC += allocator/allocator_avl.cc
diff --git a/repos/base-hw/lib/mk/base.mk b/repos/base-hw/lib/mk/base.mk
index 7fc5622492..1e30bbcb10 100644
--- a/repos/base-hw/lib/mk/base.mk
+++ b/repos/base-hw/lib/mk/base.mk
@@ -15,8 +15,12 @@ SRC_CC += env/context_area.cc
SRC_CC += env/reinitialize.cc
SRC_CC += thread/start.cc
SRC_CC += irq/platform.cc
+SRC_CC += env.cc
+SRC_CC += capability.cc
# add include paths
+INC_DIR += $(REP_DIR)/src/base/lock
+INC_DIR += $(BASE_DIR)/src/base/lock
INC_DIR += $(BASE_DIR)/src/base/env
# declare source locations
diff --git a/repos/base-hw/lib/mk/core.inc b/repos/base-hw/lib/mk/core.inc
index 6922b561d1..22b6835e1c 100644
--- a/repos/base-hw/lib/mk/core.inc
+++ b/repos/base-hw/lib/mk/core.inc
@@ -19,7 +19,6 @@ INC_DIR += $(BASE_DIR)/src/platform
# add C++ sources
SRC_CC += console.cc
-SRC_CC += cap_session_component.cc
SRC_CC += cpu_session_component.cc
SRC_CC += cpu_session_support.cc
SRC_CC += core_rm_session.cc
@@ -42,6 +41,7 @@ SRC_CC += rom_session_component.cc
SRC_CC += signal_session_component.cc
SRC_CC += trace_session_component.cc
SRC_CC += thread_start.cc
+SRC_CC += env.cc
SRC_CC += rm_session_support.cc
SRC_CC += pager.cc
SRC_CC += _main.cc
@@ -54,7 +54,9 @@ SRC_CC += kernel/ipc_node.cc
SRC_CC += kernel/irq.cc
SRC_CC += kernel/pd.cc
SRC_CC += kernel/cpu.cc
+SRC_CC += kernel/object.cc
SRC_CC += init_main_thread.cc
+SRC_CC += capability.cc
# add assembly sources
SRC_S += boot_modules.s
diff --git a/repos/base-hw/lib/mk/platform_arndale/core.mk b/repos/base-hw/lib/mk/platform_arndale/core.mk
index 3a8945c323..b6a637fb5f 100644
--- a/repos/base-hw/lib/mk/platform_arndale/core.mk
+++ b/repos/base-hw/lib/mk/platform_arndale/core.mk
@@ -13,7 +13,6 @@ SRC_CC += spec/arndale/pic.cc
SRC_CC += spec/arndale/platform_services.cc
SRC_CC += spec/arm_v7/kernel/vm_thread.cc
SRC_CC += spec/arm_v7/virtualization/kernel/vm.cc
-SRC_CC += spec/arm_v7/virtualization/kernel/vm_thread.cc
SRC_CC += spec/arm_v7/virtualization/kernel/cpu_context.cc
SRC_CC += spec/arm_v7/vm_session_component.cc
SRC_CC += spec/arm_v7/virtualization/vm_session_component.cc
diff --git a/repos/base-hw/lib/mk/platform_imx53/core-trustzone_on.mk b/repos/base-hw/lib/mk/platform_imx53/core-trustzone_on.mk
index 1e4cb90a15..6cde9827c2 100644
--- a/repos/base-hw/lib/mk/platform_imx53/core-trustzone_on.mk
+++ b/repos/base-hw/lib/mk/platform_imx53/core-trustzone_on.mk
@@ -15,7 +15,6 @@ SRC_CC += spec/imx53/trustzone/platform_services.cc
SRC_CC += spec/imx53/trustzone/pic.cc
SRC_CC += spec/arm_v7/kernel/vm_thread.cc
SRC_CC += spec/arm_v7/trustzone/kernel/vm.cc
-SRC_CC += spec/arm_v7/trustzone/kernel/vm_thread.cc
SRC_CC += spec/arm_v7/vm_session_component.cc
SRC_CC += spec/arm_v7/trustzone/vm_session_component.cc
diff --git a/repos/base-hw/src/base/capability.cc b/repos/base-hw/src/base/capability.cc
new file mode 100644
index 0000000000..497133d9da
--- /dev/null
+++ b/repos/base-hw/src/base/capability.cc
@@ -0,0 +1,38 @@
+/*
+ * \brief Implementation of platform-specific capabilities
+ * \author Stefan Kalkowski
+ * \date 2015-05-20
+ */
+
+/*
+ * Copyright (C) 2015 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
+#include
+
+static volatile int spinlock = SPINLOCK_UNLOCKED;
+static Genode::uint8_t ref_counter[1 << (sizeof(Kernel::capid_t)*8)];
+
+void Genode::Native_capability::_inc() const
+{
+ if (!valid()) return;
+
+ spinlock_lock(&spinlock);
+ ref_counter[_dst]++;
+ spinlock_unlock(&spinlock);
+}
+
+
+void Genode::Native_capability::_dec() const
+{
+ if (!valid()) return;
+
+ spinlock_lock(&spinlock);
+ if (!--ref_counter[_dst]) { Kernel::delete_cap(_dst); }
+ spinlock_unlock(&spinlock);
+}
diff --git a/repos/base-hw/src/base/env.cc b/repos/base-hw/src/base/env.cc
new file mode 100644
index 0000000000..31d976a1e1
--- /dev/null
+++ b/repos/base-hw/src/base/env.cc
@@ -0,0 +1,26 @@
+/*
+ * \brief Implementation of non-core PD session upgrade
+ * \author Stefan Kalkowski
+ * \date 2015-05-20
+ */
+
+/*
+ * Copyright (C) 2015 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
+#include
+#include
+
+void Genode::upgrade_pd_session_quota(Genode::size_t quota)
+{
+ char buf[128];
+ snprintf(buf, sizeof(buf), "ram_quota=%zu", quota);
+ Pd_session_capability cap =
+ *static_cast(env()->pd_session());
+ env()->parent()->upgrade(cap, buf);
+}
diff --git a/repos/base-hw/src/base/ipc/ipc.cc b/repos/base-hw/src/base/ipc/ipc.cc
index 1de92fdcb1..ee98c5d0d5 100644
--- a/repos/base-hw/src/base/ipc/ipc.cc
+++ b/repos/base-hw/src/base/ipc/ipc.cc
@@ -12,19 +12,26 @@
*/
/* Genode includes */
+#include
#include
+#include
#include
+#include
+#include
+#include
/* base-hw includes */
#include
#include
+namespace Hw { extern Genode::Untyped_capability _main_thread_cap; }
+
using namespace Genode;
enum
{
/* size of the callee-local name of a targeted RPC object */
- RPC_OBJECT_ID_SIZE = sizeof(umword_t),
+ RPC_OBJECT_ID_SIZE = sizeof(Native_thread_id),
/*
* The RPC framework marshalls a return value into reply messages to
@@ -35,6 +42,18 @@ enum
};
+/*****************************
+ ** IPC marshalling support **
+ *****************************/
+
+void Ipc_ostream::_marshal_capability(Native_capability const &cap) {
+ _snd_msg->cap_add(cap); }
+
+
+void Ipc_istream::_unmarshal_capability(Native_capability &cap) {
+ cap = _rcv_msg->cap_get(); }
+
+
/*****************
** Ipc_ostream **
*****************/
@@ -44,7 +63,8 @@ Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
_snd_msg(snd_msg), _dst(dst)
{
- _write_offset = RPC_OBJECT_ID_SIZE;
+ _write_offset = align_natural(RPC_OBJECT_ID_SIZE);
+ _snd_msg->reset();
}
@@ -62,9 +82,10 @@ void Ipc_istream::_wait()
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
:
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
- Native_capability(Genode::thread_get_my_native_id(), 0),
+ Native_capability(Thread_base::myself() ? Thread_base::myself()->tid().cap
+ : Hw::_main_thread_cap),
_rcv_msg(rcv_msg), _rcv_cs(-1)
-{ _read_offset = RPC_OBJECT_ID_SIZE; }
+{ _read_offset = align_natural(RPC_OBJECT_ID_SIZE); }
Ipc_istream::~Ipc_istream() { }
@@ -76,24 +97,35 @@ Ipc_istream::~Ipc_istream() { }
void Ipc_client::_call()
{
- /* send request and receive corresponding reply */
- unsigned const local_name = Ipc_ostream::_dst.local_name();
- Native_utcb * const utcb = Thread_base::myself()->utcb();
- utcb->message()->prepare_send(_snd_msg->buf, _write_offset, local_name);
- if (Kernel::send_request_msg(Ipc_ostream::_dst.dst())) {
- PERR("failed to receive reply");
- throw Blocking_canceled();
- }
- utcb->message()->finish_receive(_rcv_msg->buf, _rcv_msg->size());
+ retry(
+ [&] () {
- /* reset unmarshaller */
- _write_offset = _read_offset = RPC_OBJECT_ID_SIZE;
+ /* send request and receive corresponding reply */
+ Thread_base::myself()->utcb()->copy_from(*_snd_msg, _write_offset);
+
+ switch (Kernel::send_request_msg(Ipc_ostream::dst().dst(),
+ _rcv_msg->cap_rcv_window())) {
+ case -1: throw Blocking_canceled();
+ case -2: throw Allocator::Out_of_memory();
+ default:
+ _rcv_msg->reset();
+ _snd_msg->reset();
+ Thread_base::myself()->utcb()->copy_to(*_rcv_msg);
+
+ /* reset unmarshaller */
+ _write_offset = _read_offset =
+ align_natural(RPC_OBJECT_ID_SIZE);
+ }
+
+ },
+ [&] () { upgrade_pd_session_quota(3*4096); });
}
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
- Msgbuf_base *rcv_msg, unsigned short)
-: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) { }
+ Msgbuf_base *rcv_msg, unsigned short rcv_caps)
+: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) {
+ rcv_msg->cap_rcv_window(rcv_caps); }
/****************
@@ -104,8 +136,7 @@ Ipc_server::Ipc_server(Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg) :
Ipc_istream(rcv_msg),
Ipc_ostream(Native_capability(), snd_msg),
- _reply_needed(false)
-{ }
+ _reply_needed(false) { }
void Ipc_server::_prepare_next_reply_wait()
@@ -114,34 +145,41 @@ void Ipc_server::_prepare_next_reply_wait()
_reply_needed = true;
/* leave space for RPC method return value */
- _write_offset = RPC_OBJECT_ID_SIZE + RPC_RETURN_VALUE_SIZE;
+ _write_offset = align_natural(RPC_OBJECT_ID_SIZE +
+ RPC_RETURN_VALUE_SIZE);
/* reset unmarshaller */
- _read_offset = RPC_OBJECT_ID_SIZE;
+ _read_offset = align_natural(RPC_OBJECT_ID_SIZE);
}
void Ipc_server::_wait()
{
- /* receive request */
- if (Kernel::await_request_msg()) {
- PERR("failed to receive request");
- throw Blocking_canceled();
- }
- Native_utcb * const utcb = Thread_base::myself()->utcb();
- utcb->message()->finish_receive(_rcv_msg->buf, _rcv_msg->size());
+ retry(
+ [&] () {
- /* update server state */
- _prepare_next_reply_wait();
+ /* receive request */
+ switch (Kernel::await_request_msg(Msgbuf_base::MAX_CAP_ARGS)) {
+ case -1: throw Blocking_canceled();
+ case -2: throw Allocator::Out_of_memory();
+ default:
+ _rcv_msg->reset();
+ Thread_base::myself()->utcb()->copy_to(*_rcv_msg);
+
+ /* update server state */
+ _prepare_next_reply_wait();
+ }
+
+ },
+ [&] () { upgrade_pd_session_quota(3*4096); });
}
void Ipc_server::_reply()
{
- unsigned const local_name = Ipc_ostream::_dst.local_name();
- Native_utcb * const utcb = Thread_base::myself()->utcb();
- utcb->message()->prepare_send(_snd_msg->buf, _write_offset, local_name);
- Kernel::send_reply_msg(false);
+ Thread_base::myself()->utcb()->copy_from(*_snd_msg, _write_offset);
+ _snd_msg->reset();
+ Kernel::send_reply_msg(0, false);
}
@@ -152,16 +190,23 @@ void Ipc_server::_reply_wait()
_wait();
return;
}
- /* send reply and receive next request */
- unsigned const local_name = Ipc_ostream::_dst.local_name();
- Native_utcb * const utcb = Thread_base::myself()->utcb();
- utcb->message()->prepare_send(_snd_msg->buf, _write_offset, local_name);
- if (Kernel::send_reply_msg(true)) {
- PERR("failed to receive request");
- throw Blocking_canceled();
- }
- utcb->message()->finish_receive(_rcv_msg->buf, _rcv_msg->size());
- /* update server state */
- _prepare_next_reply_wait();
+ retry(
+ [&] () {
+ /* send reply and receive next request */
+ Thread_base::myself()->utcb()->copy_from(*_snd_msg, _write_offset);
+ switch (Kernel::send_reply_msg(Msgbuf_base::MAX_CAP_ARGS, true)) {
+ case -1: throw Blocking_canceled();
+ case -2: throw Allocator::Out_of_memory();
+ default:
+ _rcv_msg->reset();
+ _snd_msg->reset();
+ Thread_base::myself()->utcb()->copy_to(*_rcv_msg);
+
+ /* update server state */
+ _prepare_next_reply_wait();
+ }
+
+ },
+ [&] () { upgrade_pd_session_quota(3*4096); });
}
diff --git a/repos/base-hw/src/base/lock/lock_helper.h b/repos/base-hw/src/base/lock/lock_helper.h
index 39c13068ff..b76dcb79bd 100644
--- a/repos/base-hw/src/base/lock/lock_helper.h
+++ b/repos/base-hw/src/base/lock/lock_helper.h
@@ -18,13 +18,15 @@
#include
#include
-extern Genode::Native_thread_id _main_thread_id;
-
+namespace Hw {
+ extern Genode::Untyped_capability _main_thread_cap;
+}
/**
* Yield execution time-slice of current thread
*/
-static inline void thread_yield() { Kernel::yield_thread(0); }
+static inline void thread_yield() {
+ Kernel::yield_thread(Kernel::cap_id_invalid()); }
/**
@@ -33,7 +35,7 @@ static inline void thread_yield() { Kernel::yield_thread(0); }
static inline Genode::Native_thread_id
native_thread_id(Genode::Thread_base * const t)
{
- return t ? t->tid().thread_id : _main_thread_id;
+ return t ? t->tid().cap.dst() : Hw::_main_thread_cap.dst();
}
diff --git a/repos/base-hw/src/base/server/server.cc b/repos/base-hw/src/base/server/server.cc
new file mode 100644
index 0000000000..7d17361faf
--- /dev/null
+++ b/repos/base-hw/src/base/server/server.cc
@@ -0,0 +1,99 @@
+/*
+ * \brief base-hw specific part of RPC framework
+ * \author Stefan Kalkowski
+ * \date 2015-03-05
+ */
+
+/*
+ * Copyright (C) 2015 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
+#include
+#include
+#include
+#include
+
+using namespace Genode;
+
+
+/***********************
+ ** Server entrypoint **
+ ***********************/
+
+Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
+{
+ Untyped_capability new_obj_cap =
+ retry(
+ [&] () { return _cap_session->alloc(_cap); },
+ [&] () {
+ Cap_session_client *client =
+ dynamic_cast(_cap_session);
+ if (client)
+ env()->parent()->upgrade(*client, "ram_quota=16K");
+ });
+
+ /* add server object to object pool */
+ obj->cap(new_obj_cap);
+ insert(obj);
+
+ /* return capability that uses the object id as badge */
+ return new_obj_cap;
+}
+
+
+void Rpc_entrypoint::entry()
+{
+ Ipc_server srv(&_snd_buf, &_rcv_buf);
+ _ipc_server = &srv;
+ _cap = srv;
+ _cap_valid.unlock();
+
+ /*
+ * Now, the capability of the server activation is initialized
+ * an can be passed around. However, the processing of capability
+ * invocations should not happen until activation-using server
+ * is completely initialized. Thus, we wait until the activation
+ * gets explicitly unblocked by calling 'Rpc_entrypoint::activate()'.
+ */
+ _delay_start.lock();
+
+ while (!_exit_handler.exit) {
+
+ int opcode = 0;
+
+ srv >> IPC_REPLY_WAIT >> opcode;
+
+ /* set default return value */
+ srv.ret(Ipc_client::ERR_INVALID_OBJECT);
+
+ /* atomically lookup and lock referenced object */
+ Object_pool::Guard curr_obj(lookup_and_lock(srv.badge()));
+ if (!curr_obj)
+ continue;
+
+ {
+ Lock::Guard lock_guard(_curr_obj_lock);
+ _curr_obj = curr_obj;
+ }
+
+ /* dispatch request */
+ try { srv.ret(_curr_obj->dispatch(opcode, srv, srv)); }
+ catch (Blocking_canceled) { }
+
+ {
+ Lock::Guard lock_guard(_curr_obj_lock);
+ _curr_obj = 0;
+ }
+ }
+
+ /* answer exit call, thereby wake up '~Rpc_entrypoint' */
+ srv << IPC_REPLY;
+
+ /* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
+ _delay_exit.lock();
+}
diff --git a/repos/base-hw/src/base/signal/signal.cc b/repos/base-hw/src/base/signal/signal.cc
index c296103cab..cc76ddaa9f 100644
--- a/repos/base-hw/src/base/signal/signal.cc
+++ b/repos/base-hw/src/base/signal/signal.cc
@@ -104,7 +104,7 @@ Signal_receiver::Signal_receiver()
return;
}
PINF("upgrading quota donation for SIGNAL session");
- env()->parent()->upgrade(s->cap(), "ram_quota=4K");
+ env()->parent()->upgrade(s->cap(), "ram_quota=8K");
session_upgraded = 1;
}
}
@@ -159,7 +159,7 @@ Signal_context_capability Signal_receiver::manage(Signal_context * const c)
return Signal_context_capability();
}
PINF("upgrading quota donation for signal session");
- env()->parent()->upgrade(s->cap(), "ram_quota=4K");
+ env()->parent()->upgrade(s->cap(), "ram_quota=8K");
session_upgraded = 1;
}
}
@@ -193,8 +193,9 @@ Signal Signal_receiver::wait_for_signal()
PERR("failed to receive signal");
return Signal(Signal::Data());
}
+
/* get signal data */
- Signal s(*(Signal::Data *)Thread_base::myself()->utcb());
+ Signal s(*(Signal::Data *)Thread_base::myself()->utcb()->base());
return s;
}
diff --git a/repos/base-hw/src/base/thread/bootstrap.cc b/repos/base-hw/src/base/thread/bootstrap.cc
index 842e64d710..5f8f475994 100644
--- a/repos/base-hw/src/base/thread/bootstrap.cc
+++ b/repos/base-hw/src/base/thread/bootstrap.cc
@@ -22,18 +22,10 @@
using namespace Genode;
-Ram_dataspace_capability _main_thread_utcb_ds;
-Native_thread_id _main_thread_id;
-
-
-/**************************
- ** Native types support **
- **************************/
-
-Native_thread_id Genode::thread_get_my_native_id()
-{
- Thread_base * const t = Thread_base::myself();
- return t ? t->tid().thread_id : _main_thread_id;
+namespace Hw {
+ Ram_dataspace_capability _main_thread_utcb_ds;
+ Untyped_capability _main_thread_cap;
+ Untyped_capability _parent_cap;
}
@@ -44,15 +36,17 @@ Native_thread_id Genode::thread_get_my_native_id()
void prepare_init_main_thread()
{
using namespace Genode;
+ using namespace Hw;
/*
* Make data from the startup info persistantly available by copying it
* before the UTCB gets polluted by the following function calls.
*/
- Native_utcb * const utcb = Thread_base::myself()->utcb();
- _main_thread_id = utcb->start_info()->thread_id();
- _main_thread_utcb_ds =
- reinterpret_cap_cast(utcb->start_info()->utcb_ds());
+ Native_utcb * utcb = Thread_base::myself()->utcb();
+ _parent_cap = utcb->cap_get(Native_utcb::PARENT);
+ Untyped_capability ds_cap(utcb->cap_get(Native_utcb::UTCB_DATASPACE));
+ _main_thread_utcb_ds = reinterpret_cap_cast(ds_cap);
+ _main_thread_cap = utcb->cap_get(Native_utcb::THREAD_MYSELF);
}
@@ -78,8 +72,5 @@ void Thread_base::_thread_start()
Genode::sleep_forever();
}
-void Thread_base::_thread_bootstrap()
-{
- Native_utcb * const utcb = Thread_base::myself()->utcb();
- _tid.thread_id = utcb->start_info()->thread_id();
-}
+void Thread_base::_thread_bootstrap() {
+ _tid.cap = myself()->utcb()->cap_get(Native_utcb::THREAD_MYSELF); }
diff --git a/repos/base-hw/src/base/thread/start.cc b/repos/base-hw/src/base/thread/start.cc
index 7d806da870..8ac1d69347 100644
--- a/repos/base-hw/src/base/thread/start.cc
+++ b/repos/base-hw/src/base/thread/start.cc
@@ -22,9 +22,10 @@ using namespace Genode;
namespace Genode { Rm_session * env_context_area_rm_session(); }
-extern Ram_dataspace_capability _main_thread_utcb_ds;
-extern Native_thread_id _main_thread_id;
-
+namespace Hw {
+ extern Ram_dataspace_capability _main_thread_utcb_ds;
+ extern Untyped_capability _main_thread_cap;
+}
/*****************
** Thread_base **
@@ -50,14 +51,14 @@ void Thread_base::_init_platform_thread(size_t weight, Type type)
if (type == REINITIALIZED_MAIN) { rm->detach(utcb_new); }
/* remap initial main-thread UTCB according to context-area spec */
- try { rm->attach_at(_main_thread_utcb_ds, utcb_new, utcb_size); }
+ try { rm->attach_at(Hw::_main_thread_utcb_ds, utcb_new, utcb_size); }
catch(...) {
PERR("failed to re-map UTCB");
while (1) ;
}
/* adjust initial object state in case of a main thread */
- tid().thread_id = _main_thread_id;
- _thread_cap = env()->parent()->main_thread_cap();
+ tid().cap = Hw::_main_thread_cap;
+ _thread_cap = env()->parent()->main_thread_cap();
}
diff --git a/repos/base-hw/src/core/capability.cc b/repos/base-hw/src/core/capability.cc
new file mode 100644
index 0000000000..6165eee90b
--- /dev/null
+++ b/repos/base-hw/src/core/capability.cc
@@ -0,0 +1,17 @@
+/*
+ * \brief Implementation of platform-specific capabilities for core
+ * \author Stefan Kalkowski
+ * \date 2015-05-20
+ */
+
+/*
+ * Copyright (C) 2015 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
+
+void Genode::Native_capability::_inc() const { }
+
+void Genode::Native_capability::_dec() const { }
diff --git a/repos/base-hw/src/core/env.cc b/repos/base-hw/src/core/env.cc
new file mode 100644
index 0000000000..c867735335
--- /dev/null
+++ b/repos/base-hw/src/core/env.cc
@@ -0,0 +1,18 @@
+/*
+ * \brief Implementation of core's PD session upgrade
+ * \author Stefan Kalkowski
+ * \date 2015-05-20
+ */
+
+/*
+ * Copyright (C) 2015 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
+#include
+
+void Genode::upgrade_pd_session_quota(Genode::size_t quota) { assert(false); }
diff --git a/repos/base-hw/src/core/include/cap_session_component.h b/repos/base-hw/src/core/include/cap_session_component.h
new file mode 100644
index 0000000000..a712696bdb
--- /dev/null
+++ b/repos/base-hw/src/core/include/cap_session_component.h
@@ -0,0 +1,122 @@
+/*
+ * \brief Capability allocation service
+ * \author Stefan Kalkowski
+ * \date 2015-03-05
+ */
+
+/*
+ * Copyright (C) 2015 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__CAP_SESSION_COMPONENT_H_
+#define _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+namespace Genode { class Cap_session_component; }
+
+
+class Genode::Cap_session_component : public Rpc_object
+{
+ private:
+
+ /**
+ * Kernel object placeholder hold in a list
+ */
+ struct Kobject : List::Element
+ {
+ using Identity = Kernel::Core_object_identity;
+
+ Native_capability cap;
+
+ uint8_t data[sizeof(Identity)]
+ __attribute__((aligned(sizeof(addr_t))));
+ };
+
+ using Slab = Tslab;
+
+ Allocator_guard _guard;
+ uint8_t _initial_sb[get_page_size()]; /* initial slab block */
+ Slab _slab;
+ List _list;
+ Lock _lock;
+
+ /**
+ * Returns the right meta-data allocator,
+ * for core it returns a non-guarded one, otherwise a guard
+ */
+ Allocator * _md_alloc(Allocator *md_alloc)
+ {
+ Allocator * core_mem_alloc =
+ static_cast(platform()->core_mem_alloc());
+ return (md_alloc == core_mem_alloc) ? core_mem_alloc : &_guard;
+ }
+
+ public:
+
+ Cap_session_component(Allocator *md_alloc, const char *args)
+ : _guard(md_alloc,
+ Arg_string::find_arg(args, "ram_quota").long_value(0)),
+ _slab(_md_alloc(md_alloc), (Slab_block*)&_initial_sb) { }
+
+ ~Cap_session_component()
+ {
+ Lock::Guard guard(_lock);
+
+ while (Kobject * obj = _list.first()) {
+ Kernel::delete_obj(obj->data);
+ _list.remove(obj);
+ destroy(&_slab, obj);
+ }
+ }
+
+ void upgrade_ram_quota(size_t ram_quota) { _guard.upgrade(ram_quota); }
+
+ Native_capability alloc(Native_capability ep)
+ {
+ Lock::Guard guard(_lock);
+
+ /* allocate kernel object */
+ Kobject * obj;
+ if (!_slab.alloc(sizeof(Kobject), (void**)&obj))
+ throw Out_of_metadata();
+ construct_at(obj);
+
+ /* create kernel object via syscall */
+ obj->cap = Kernel::new_obj(obj->data, ep.dst());
+ if (!obj->cap.valid()) {
+ PWRN("Invalid entrypoint %u for allocating a capability!",
+ ep.dst());
+ destroy(&_slab, obj);
+ return Native_capability();
+ }
+
+ /* store it in the list and return result */
+ _list.insert(obj);
+ return obj->cap;
+ }
+
+ void free(Native_capability cap)
+ {
+ Lock::Guard guard(_lock);
+
+ for (Kobject * obj = _list.first(); obj; obj = obj->next())
+ if (obj->cap.dst() == cap.dst()) {
+ Kernel::delete_obj(obj->data);
+ _list.remove(obj);
+ destroy(&_slab, obj);
+ return;
+ }
+ }
+};
+
+#endif /* _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_ */
diff --git a/repos/base-hw/src/core/include/kernel/configuration.h b/repos/base-hw/src/core/include/kernel/configuration.h
index 817a4752ae..a0204c3e85 100644
--- a/repos/base-hw/src/core/include/kernel/configuration.h
+++ b/repos/base-hw/src/core/include/kernel/configuration.h
@@ -16,10 +16,7 @@
namespace Kernel
{
- enum {
- DEFAULT_STACK_SIZE = 16 * 1024,
- MAX_KERNEL_OBJECTS = 8192,
- };
+ enum { DEFAULT_STACK_SIZE = 16 * 1024 };
/* amount of priority bands amongst quota owners in CPU scheduling */
constexpr unsigned cpu_priorities = 4;
diff --git a/repos/base-hw/src/core/include/kernel/core_interface.h b/repos/base-hw/src/core/include/kernel/core_interface.h
index d9d3115007..558f424b57 100644
--- a/repos/base-hw/src/core/include/kernel/core_interface.h
+++ b/repos/base-hw/src/core/include/kernel/core_interface.h
@@ -17,6 +17,8 @@
/* base-hw includes */
#include
+namespace Genode { class Native_utcb; }
+
namespace Kernel
{
class Pd;
@@ -25,57 +27,35 @@ namespace Kernel
class Signal_context;
class Vm;
class User_irq;
+ using Native_utcb = Genode::Native_utcb;
/**
* Kernel names of the kernel calls
*/
- constexpr Call_arg call_id_new_thread() { return 14; }
- constexpr Call_arg call_id_delete_thread() { return 15; }
- constexpr Call_arg call_id_start_thread() { return 16; }
- constexpr Call_arg call_id_resume_thread() { return 17; }
- constexpr Call_arg call_id_access_thread_regs() { return 18; }
- constexpr Call_arg call_id_route_thread_event() { return 19; }
- constexpr Call_arg call_id_update_pd() { return 20; }
- constexpr Call_arg call_id_new_pd() { return 21; }
- constexpr Call_arg call_id_delete_pd() { return 22; }
- constexpr Call_arg call_id_new_signal_receiver() { return 23; }
- constexpr Call_arg call_id_new_signal_context() { return 24; }
- constexpr Call_arg call_id_delete_signal_context() { return 25; }
- constexpr Call_arg call_id_delete_signal_receiver() { return 26; }
- constexpr Call_arg call_id_new_vm() { return 27; }
- constexpr Call_arg call_id_run_vm() { return 28; }
- constexpr Call_arg call_id_pause_vm() { return 29; }
- constexpr Call_arg call_id_pause_thread() { return 30; }
- constexpr Call_arg call_id_delete_vm() { return 31; }
- constexpr Call_arg call_id_new_irq() { return 32; }
- constexpr Call_arg call_id_delete_irq() { return 33; }
- constexpr Call_arg call_id_thread_quota() { return 34; }
- constexpr Call_arg call_id_ack_irq() { return 35; }
-
- /**
- * Create a domain
- *
- * \param dst appropriate memory donation for the kernel object
- * \param pd core local Platform_pd object
- *
- * \retval 0 when successful, otherwise !=0
- */
- inline int long new_pd(void * const dst, Platform_pd * const pd)
- {
- return call(call_id_new_pd(), (Call_arg)dst, (Call_arg)pd);
- }
-
-
- /**
- * Destruct a domain
- *
- * \param pd pointer to pd kernel object
- */
- inline void delete_pd(Pd * const pd)
- {
- call(call_id_delete_pd(), (Call_arg)pd);
- }
-
+ constexpr Call_arg call_id_new_thread() { return 15; }
+ constexpr Call_arg call_id_delete_thread() { return 16; }
+ constexpr Call_arg call_id_start_thread() { return 17; }
+ constexpr Call_arg call_id_pause_thread() { return 18; }
+ constexpr Call_arg call_id_resume_thread() { return 19; }
+ constexpr Call_arg call_id_access_thread_regs() { return 20; }
+ constexpr Call_arg call_id_route_thread_event() { return 21; }
+ constexpr Call_arg call_id_thread_quota() { return 22; }
+ constexpr Call_arg call_id_update_pd() { return 23; }
+ constexpr Call_arg call_id_new_pd() { return 24; }
+ constexpr Call_arg call_id_delete_pd() { return 25; }
+ constexpr Call_arg call_id_new_signal_receiver() { return 26; }
+ constexpr Call_arg call_id_new_signal_context() { return 27; }
+ constexpr Call_arg call_id_delete_signal_context() { return 28; }
+ constexpr Call_arg call_id_delete_signal_receiver() { return 29; }
+ constexpr Call_arg call_id_new_vm() { return 30; }
+ constexpr Call_arg call_id_run_vm() { return 31; }
+ constexpr Call_arg call_id_pause_vm() { return 32; }
+ constexpr Call_arg call_id_delete_vm() { return 33; }
+ constexpr Call_arg call_id_new_irq() { return 34; }
+ constexpr Call_arg call_id_delete_irq() { return 35; }
+ constexpr Call_arg call_id_ack_irq() { return 36; }
+ constexpr Call_arg call_id_new_obj() { return 37; }
+ constexpr Call_arg call_id_delete_obj() { return 38; }
/**
* Update locally effective domain configuration to in-memory state
@@ -92,25 +72,6 @@ namespace Kernel
}
- /**
- * Create a thread
- *
- * \param p memory donation for the new kernel thread object
- * \param priority scheduling priority of the new thread
- * \param quota CPU quota of the new thread
- * \param label debugging label of the new thread
- *
- * \retval >0 kernel name of the new thread
- * \retval 0 failed
- */
- inline unsigned new_thread(void * const p, unsigned const priority,
- size_t const quota, char const * const label)
- {
- return call(call_id_new_thread(), (Call_arg)p, (Call_arg)priority,
- (Call_arg)quota, (Call_arg)label);
- }
-
-
/**
* Configure the CPU quota of a thread
*
@@ -134,17 +95,6 @@ namespace Kernel
}
- /**
- * Destruct a thread
- *
- * \param thread pointer to thread kernel object
- */
- inline void delete_thread(Thread * const thread)
- {
- call(call_id_delete_thread(), (Call_arg)thread);
- }
-
-
/**
* Start execution of a thread
*
@@ -181,15 +131,15 @@ namespace Kernel
* Set or unset the handler of an event that can be triggered by a thread
*
* \param thread pointer to thread kernel object
- * \param event_id kernel name of the targeted thread event
- * \param signal_context_id kernel name of the handlers signal context
+ * \param event_id capability id of the targeted thread event
+ * \param signal_context_id capability id of the handlers signal context
*
* \retval 0 succeeded
* \retval -1 failed
*/
inline int route_thread_event(Thread * const thread,
- unsigned const event_id,
- unsigned const signal_context_id)
+ capid_t const event_id,
+ capid_t const signal_context_id)
{
return call(call_id_route_thread_event(), (Call_arg)thread,
event_id, signal_context_id);
@@ -238,109 +188,14 @@ namespace Kernel
}
- /**
- * Create a signal receiver
- *
- * \param p memory donation for the kernel signal-receiver object
- *
- * \retval >0 kernel name of the new signal receiver
- * \retval 0 failed
- */
- inline unsigned new_signal_receiver(addr_t const p)
- {
- return call(call_id_new_signal_receiver(), p);
- }
-
-
- /**
- * Create a signal context and assign it to a signal receiver
- *
- * \param p memory donation for the kernel signal-context object
- * \param receiver pointer to signal receiver kernel object
- * \param imprint user label of the signal context
- *
- * \retval >0 kernel name of the new signal context
- * \retval 0 failed
- */
- inline unsigned new_signal_context(addr_t const p,
- Signal_receiver * const receiver,
- unsigned const imprint)
- {
- return call(call_id_new_signal_context(), p,
- (Call_arg)receiver, imprint);
- }
-
-
- /**
- * Destruct a signal context
- *
- * \param context pointer to signal context kernel object
- */
- inline void delete_signal_context(Signal_context * const context)
- {
- call(call_id_delete_signal_context(), (Call_arg)context);
- }
-
-
- /**
- * Destruct a signal receiver
- *
- * \param receiver pointer to signal receiver kernel object
- *
- * \retval 0 suceeded
- * \retval -1 failed
- */
- inline void delete_signal_receiver(Signal_receiver * const receiver)
- {
- call(call_id_delete_signal_receiver(), (Call_arg)receiver);
- }
-
-
- /**
- * Create a virtual machine that is stopped initially
- *
- * \param dst memory donation for the VM object
- * \param state location of the CPU state of the VM
- * \param signal_context_id kernel name of the signal context for VM events
- * \param table guest-physical to host-physical translation
- * table pointer
- *
- * \retval 0 when successful, otherwise !=0
- *
- * Regaining of the supplied memory is not supported by now.
- */
- inline int new_vm(void * const dst, void * const state,
- unsigned const signal_context_id,
- void * const table)
- {
- return call(call_id_new_vm(), (Call_arg)dst, (Call_arg)state,
- (Call_arg)table, signal_context_id);
- }
-
-
/**
* Execute a virtual-machine (again)
*
* \param vm pointer to vm kernel object
- *
- * \retval 0 when successful, otherwise !=0
*/
- inline int run_vm(Vm * const vm)
+ inline void run_vm(Vm * const vm)
{
- return call(call_id_run_vm(), (Call_arg) vm);
- }
-
-
- /**
- * Destruct a virtual-machine
- *
- * \param vm pointer to vm kernel object
- *
- * \retval 0 when successful, otherwise !=0
- */
- inline int delete_vm(Vm * const vm)
- {
- return call(call_id_delete_vm(), (Call_arg) vm);
+ call(call_id_run_vm(), (Call_arg) vm);
}
@@ -348,12 +203,10 @@ namespace Kernel
* Stop execution of a virtual-machine
*
* \param vm pointer to vm kernel object
- *
- * \retval 0 when successful, otherwise !=0
*/
- inline int pause_vm(Vm * const vm)
+ inline void pause_vm(Vm * const vm)
{
- return call(call_id_pause_vm(), (Call_arg) vm);
+ call(call_id_pause_vm(), (Call_arg) vm);
}
/**
@@ -361,10 +214,10 @@ namespace Kernel
*
* \param p memory donation for the irq object
* \param irq_nr interrupt number
- * \param signal_context_id kernel name of the signal context
+ * \param signal_context_id capability id of the signal context
*/
inline int new_irq(addr_t const p, unsigned irq_nr,
- unsigned signal_context_id)
+ capid_t signal_context_id)
{
return call(call_id_new_irq(), (Call_arg) p, irq_nr, signal_context_id);
}
@@ -388,6 +241,27 @@ namespace Kernel
{
call(call_id_delete_irq(), (Call_arg) irq);
}
+
+ /**
+ * Create a new object identity for a thread
+ *
+ * \param dst memory donation for the new object
+ * \param cap capability id of the targeted thread
+ */
+ inline capid_t new_obj(void * const dst, capid_t const cap)
+ {
+ return call(call_id_new_obj(), (Call_arg)dst, (Call_arg)cap);
+ }
+
+ /**
+ * Destroy an object identity
+ *
+ * \param dst pointer to the object identity object
+ */
+ inline void delete_obj(void * const dst)
+ {
+ call(call_id_delete_obj(), (Call_arg)dst);
+ }
}
#endif /* _KERNEL__CORE_INTERFACE_H_ */
diff --git a/repos/base-hw/src/core/include/kernel/ipc_node.h b/repos/base-hw/src/core/include/kernel/ipc_node.h
index b86601d0a2..b6df19d638 100644
--- a/repos/base-hw/src/core/include/kernel/ipc_node.h
+++ b/repos/base-hw/src/core/include/kernel/ipc_node.h
@@ -1,6 +1,7 @@
/*
* \brief Backend for end points of synchronous interprocess communication
* \author Martin Stein
+ * \author Stefan Kalkowski
* \date 2012-11-30
*/
@@ -14,19 +15,28 @@
#ifndef _KERNEL__IPC_NODE_H_
#define _KERNEL__IPC_NODE_H_
+/* Genode includes */
+#include
+
/* core includes */
#include
#include
+namespace Genode { class Msgbuf_base; };
+
namespace Kernel
{
+ class Pd;
+
/**
* Backend for end points of synchronous interprocess communication
*/
class Ipc_node;
+
+ using Ipc_node_queue = Kernel::Fifo;
}
-class Kernel::Ipc_node
+class Kernel::Ipc_node : public Ipc_node_queue::Element
{
protected:
@@ -39,48 +49,40 @@ class Kernel::Ipc_node
PREPARE_AND_AWAIT_REPLY = 5,
};
+ void _init(Genode::Native_utcb * utcb, Ipc_node * callee);
+
private:
- class Message_buf;
+ friend class Core_thread;
- typedef Kernel::Fifo Message_fifo;
+ State _state = INACTIVE;
+ capid_t _capid = cap_id_invalid();
+ Ipc_node * _caller = nullptr;
+ Ipc_node * _callee = nullptr;
+ bool _help = false;
+ size_t _rcv_caps = 0; /* max capability num to receive */
+ Genode::Native_utcb * _utcb = nullptr;
+ Ipc_node_queue _request_queue;
- /**
- * Describes the buffer for incoming or outgoing messages
- */
- class Message_buf : public Message_fifo::Element
- {
- public:
+ /* pre-allocation array for obkject identity references */
+ void * _obj_id_ref_ptr[Genode::Msgbuf_base::MAX_CAP_ARGS];
- void * base;
- size_t size;
- Ipc_node * src;
- };
-
- Message_fifo _request_queue;
- Message_buf _inbuf;
- Message_buf _outbuf;
- Ipc_node * _outbuf_dst;
- bool _outbuf_dst_help;
- State _state;
+ inline void copy_msg(Ipc_node * const sender);
/**
* Buffer next request from request queue in 'r' to handle it
*/
- void _receive_request(Message_buf * const r);
+ void _receive_request(Ipc_node * const caller);
/**
* Receive a given reply if one is expected
- *
- * \param base base of the reply payload
- * \param size size of the reply payload
*/
- void _receive_reply(void * const base, size_t const size);
+ void _receive_reply(Ipc_node * callee);
/**
* Insert 'r' into request queue, buffer it if we were waiting for it
*/
- void _announce_request(Message_buf * const r);
+ void _announce_request(Ipc_node * const node);
/**
* Cancel all requests in request queue
@@ -100,7 +102,7 @@ class Kernel::Ipc_node
/**
* A request 'r' in inbuf or request queue was cancelled by sender
*/
- void _announced_request_cancelled(Message_buf * const r);
+ void _announced_request_cancelled(Ipc_node * const node);
/**
* The request in the outbuf was cancelled by receiver
@@ -134,31 +136,28 @@ class Kernel::Ipc_node
protected:
+ Pd * _pd; /* pointer to PD this IPC node is part of */
+
+
/***************
** Accessors **
***************/
- Ipc_node * outbuf_dst() { return _outbuf_dst; }
-
- State state() { return _state; }
+ Ipc_node * callee() { return _callee; }
+ State state() { return _state; }
public:
- Ipc_node();
~Ipc_node();
/**
* Send a request and wait for the according reply
*
- * \param dst targeted IPC node
- * \param buf_base base of receive buffer and request message
- * \param buf_size size of receive buffer
- * \param msg_size size of request message
+ * \param callee targeted IPC node
* \param help wether the request implies a helping relationship
*/
- void send_request(Ipc_node * const dst, void * const buf_base,
- size_t const buf_size, size_t const msg_size,
- bool help);
+ void send_request(Ipc_node * const callee, capid_t capid, bool help,
+ unsigned rcv_caps);
/**
* Return root destination of the helping-relation tree we are in
@@ -172,37 +171,38 @@ class Kernel::Ipc_node
{
/* if we have a helper in the receive buffer, call 'f' for it */
if (_state == PREPARE_REPLY || _state == PREPARE_AND_AWAIT_REPLY) {
- if (_inbuf.src->_outbuf_dst_help) { f(_inbuf.src); } }
+ if (_caller->_help) { f(_caller); } }
/* call 'f' for each helper in our request queue */
- _request_queue.for_each([f] (Message_buf * const b) {
- if (b->src->_outbuf_dst_help) { f(b->src); } });
+ _request_queue.for_each([f] (Ipc_node * const node) {
+ if (node->_help) { f(node); } });
}
/**
* Wait until a request has arrived and load it for handling
*
- * \param buf_base base of receive buffer
- * \param buf_size size of receive buffer
- *
* \return wether a request could be received already
*/
- bool await_request(void * const buf_base,
- size_t const buf_size);
+ bool await_request(unsigned rcv_caps);
/**
* Reply to last request if there's any
- *
- * \param msg_base base of reply message
- * \param msg_size size of reply message
*/
- void send_reply(void * const msg_base,
- size_t const msg_size);
+ void send_reply();
/**
* If IPC node waits, cancel '_outbuf' to stop waiting
*/
void cancel_waiting();
+
+
+ /***************
+ ** Accessors **
+ ***************/
+
+ Pd * const pd() const { return _pd; }
+ char const * pd_label() const;
+ Genode::Native_utcb * utcb() { return _utcb; }
};
#endif /* _KERNEL__IPC_NODE_H_ */
diff --git a/repos/base-hw/src/core/include/kernel/irq.h b/repos/base-hw/src/core/include/kernel/irq.h
index 1d753d23b7..60ac5c79cb 100644
--- a/repos/base-hw/src/core/include/kernel/irq.h
+++ b/repos/base-hw/src/core/include/kernel/irq.h
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
/* core includes */
#include
@@ -45,31 +46,35 @@ namespace Genode
}
-class Kernel::Irq : public Object_pool::Item
+class Kernel::Irq : public Genode::Avl_node
{
public:
- using Pool = Object_pool;
+ struct Pool : Genode::Avl_tree
+ {
+ Irq * object(unsigned const id) const
+ {
+ Irq * const irq = first();
+ if (!irq) return nullptr;
+ return irq->find(id);
+ }
+ };
protected:
- Pool &_pool;
-
- /**
- * Get kernel name of the interrupt
- */
- unsigned _id() const { return Pool::Item::id(); };
+ unsigned _irq_nr; /* kernel name of the interrupt */
+ Pool &_pool;
public:
/**
* Constructor
*
- * \param irq_id kernel name of the interrupt
- * \param pool pool this interrupt shall belong to
+ * \param irq interrupt number
+ * \param pool pool this interrupt shall belong to
*/
- Irq(unsigned const irq_id, Pool &pool)
- : Pool::Item(irq_id), _pool(pool) { _pool.insert(this); }
+ Irq(unsigned const irq, Pool &pool)
+ : _irq_nr(irq), _pool(pool) { _pool.insert(this); }
virtual ~Irq() { _pool.remove(this); }
@@ -87,10 +92,30 @@ class Kernel::Irq : public Object_pool::Item
* Allow interrupt to occur
*/
void enable() const;
+
+ unsigned irq_number() { return _irq_nr; }
+
+
+ /************************
+ * 'Avl_node' interface *
+ ************************/
+
+ bool higher(Irq * i) const { return i->_irq_nr > _irq_nr; }
+
+ /**
+ * Find irq with 'nr' within this AVL subtree
+ */
+ Irq * find(unsigned const nr)
+ {
+ if (nr == _irq_nr) return this;
+ Irq * const subtree = Genode::Avl_node::child(nr > _irq_nr);
+ return (subtree) ? subtree->find(nr): nullptr;
+ }
+
};
-class Kernel::User_irq : public Kernel::Irq
+class Kernel::User_irq : public Kernel::Irq, public Kernel::Object
{
private:
diff --git a/repos/base-hw/src/core/include/kernel/kernel.h b/repos/base-hw/src/core/include/kernel/kernel.h
index c8bc163081..fefb27b075 100644
--- a/repos/base-hw/src/core/include/kernel/kernel.h
+++ b/repos/base-hw/src/core/include/kernel/kernel.h
@@ -16,13 +16,21 @@
#define _KERNEL__KERNEL_H_
#include
-#include
+
+/**
+ * Main routine of every kernel pass
+ */
+extern "C" void kernel();
+
namespace Kernel {
+
+ class Pd;
+ class Mode_transition_control;
+
Pd * core_pd();
Mode_transition_control * mtc();
Pic * pic();
- Native_utcb * core_main_thread_utcb_phys_addr();
}
#endif /* _KERNEL__KERNEL_H_ */
diff --git a/repos/base-hw/src/core/include/kernel/object.h b/repos/base-hw/src/core/include/kernel/object.h
index 9a18a7048a..0a4f606880 100644
--- a/repos/base-hw/src/core/include/kernel/object.h
+++ b/repos/base-hw/src/core/include/kernel/object.h
@@ -1,6 +1,5 @@
/*
- * \brief Objects that are findable through unique IDs
- * \author Martin Stein
+ * \brief Kernel object identities and references
* \author Stefan Kalkowski
* \date 2012-11-30
*/
@@ -18,133 +17,172 @@
/* Genode includes */
#include
#include
+#include
/* core includes */
-#include
-#include
+#include
+#include
namespace Kernel
{
- /**
- * Map unique sortable IDs to objects
- *
- * \param T object type that inherits from Object_pool::Item
- */
- template
- class Object_pool;
+ class Pd; /* forward declaration */
/**
- * Manage allocation of a static set of IDs
+ * Base class of all Kernel objects
*/
- using Id_allocator = Genode::Bit_allocator;
- Id_allocator & id_alloc();
-
- /**
- * Make all objects of a deriving class findable through unique IDs
- *
- * \param T object type
- * \param POOL accessor function of object pool
- */
- template * (* POOL)()>
class Object;
+
+ /**
+ * An object identity helps to distinguish different capability owners
+ * that reference a Kernel object
+ */
+ class Object_identity;
+
+ /**
+ * An object identity reference is the in-kernel representation
+ * of a PD local capability. It references an object identity and is
+ * associated with a protection domain.
+ */
+ class Object_identity_reference;
+
+ /**
+ * A tree of object identity references to retrieve the capabilities
+ * of one PD fastly.
+ */
+ class Object_identity_reference_tree;
+
+ using Object_identity_reference_list
+ = Genode::List;
+
+ /**
+ * This class represents kernel object's identities including the
+ * corresponding object identity reference for core
+ */
+ template class Core_object_identity;
+
+ /**
+ * This class represents a kernel object, it's identity, and the
+ * corresponding object identity reference for core
+ */
+ template class Core_object;
}
-template
-class Kernel::Object_pool
+
+struct Kernel::Object
{
- public:
-
- /**
- * Enable a deriving class T to be inserted into an Object_pool
- */
- class Item;
-
- /**
- * Insert 'object' into pool
- */
- void insert(T * const object) { _tree.insert(object); }
-
- /**
- * Remove 'object' from pool
- */
- void remove(T * const object) { _tree.remove(object); }
-
- /**
- * Return object with ID 'id', or 0 if such an object doesn't exist
- */
- T * object(unsigned const id) const
- {
- Item * const root = _tree.first();
- if (!root) { return 0; }
- return static_cast(root->find(id));
- }
-
- private:
-
- Genode::Avl_tree- _tree;
+ virtual ~Object() { }
};
-template
-class Kernel::Object_pool::Item : public Genode::Avl_node
-
-{
- protected:
- unsigned _id;
+class Kernel::Object_identity
+: public Kernel::Object_identity_reference_list
+{
+ private:
+
+ Object & _object;
public:
- /**
- * Constructor
- */
- Item(unsigned const id) : _id(id) { }
+ Object_identity(Object & object);
+ ~Object_identity();
- /**
- * Find entry with 'object_id' within this AVL subtree
- */
- Item * find(unsigned const object_id)
- {
- if (object_id == id()) { return this; }
- Item * const subtree =
- Genode::Avl_node
- ::child(object_id > id());
- if (!subtree) { return 0; }
- return subtree->find(object_id);
- }
+ template
+ KOBJECT * object() { return dynamic_cast(&_object); }
+};
- /**
- * ID of this object
- */
- unsigned id() const { return _id; }
+
+class Kernel::Object_identity_reference
+: public Genode::Avl_node,
+ public Genode::List::Element
+{
+ private:
+
+ capid_t _capid;
+ Object_identity *_identity;
+ Pd &_pd;
+
+ public:
+
+ Object_identity_reference(Object_identity *oi, Pd &pd);
+ ~Object_identity_reference();
+
+ /***************
+ ** Accessors **
+ ***************/
+
+ template
+ KOBJECT * object() {
+ return _identity ? _identity->object() : nullptr; }
+
+ Object_identity_reference * factory(void * dst, Pd &pd);
+
+ Pd & pd() { return _pd; }
+ capid_t capid() { return _capid; }
+
+ void invalidate();
/************************
- * 'Avl_node' interface *
+ ** Avl_node interface **
************************/
- bool higher(Item * i) const { return i->id() > id(); }
+ bool higher(Object_identity_reference * oir) const {
+ return oir->_capid > _capid; }
+
+
+ /**********************
+ ** Lookup functions **
+ **********************/
+
+ Object_identity_reference * find(Pd * pd);
+ Object_identity_reference * find(capid_t capid);
};
-template * (* POOL)()>
-class Kernel::Object : public Object_pool::Item
+class Kernel::Object_identity_reference_tree
+: public Genode::Avl_tree
{
public:
- using Pool = Object_pool;
+ Object_identity_reference * find(capid_t id);
- /**
- * Map of unique IDs to objects of T
- */
- static Pool * pool() { return POOL(); }
-
- protected:
-
- Object() : Pool::Item(id_alloc().alloc()) {
- POOL()->insert(static_cast(this)); }
-
- ~Object()
+ template
+ KOBJECT * find(capid_t id)
{
- POOL()->remove(static_cast(this));
- id_alloc().free(Pool::Item::id());
+ Object_identity_reference * oir = find(id);
+ return (oir) ? oir->object() : nullptr;
+ }
+};
+
+
+template
+class Kernel::Core_object_identity : public Object_identity,
+ public Object_identity_reference
+{
+ public:
+
+ Core_object_identity(T & object)
+ : Object_identity(object),
+ Object_identity_reference(this, *core_pd()) { }
+
+ virtual void destroy() { this->~Object_identity(); }
+
+ capid_t core_capid() { return capid(); }
+};
+
+
+template
+class Kernel::Core_object : public T, public Kernel::Core_object_identity
+{
+ public:
+
+ template
+ Core_object(ARGS &&... args)
+ : T(args...), Core_object_identity(*static_cast(this)) { }
+
+ void destroy() {
+ Core_object_identity::destroy();
+ this->~T();
}
};
diff --git a/repos/base-hw/src/core/include/kernel/pd.h b/repos/base-hw/src/core/include/kernel/pd.h
index 67c55acfa4..34cbd0a23d 100644
--- a/repos/base-hw/src/core/include/kernel/pd.h
+++ b/repos/base-hw/src/core/include/kernel/pd.h
@@ -17,8 +17,13 @@
/* core includes */
#include
-#include
#include
+#include
+
+namespace Genode {
+ class Page_slab;
+ class Platform_pd;
+}
namespace Kernel
{
@@ -43,10 +48,6 @@ namespace Kernel
* Kernel backend of protection domains
*/
class Pd;
-
- typedef Object_pool Pd_pool;
-
- Pd_pool * pd_pool();
}
class Kernel::Mode_transition_control
@@ -129,16 +130,22 @@ class Kernel::Mode_transition_control
} __attribute__((aligned(Mode_transition_control::ALIGN)));
-class Kernel::Pd : public Object, public Cpu::Pd
+class Kernel::Pd : public Cpu::Pd,
+ public Kernel::Object
{
public:
- typedef Genode::Translation_table Table;
+ static constexpr unsigned max_cap_ids = 1 << (sizeof(capid_t) * 8);
+
+ using Table = Genode::Translation_table;
+ using Capid_allocator = Genode::Bit_allocator;
private:
- Table * const _table;
- Platform_pd * const _platform_pd;
+ Table * const _table;
+ Genode::Platform_pd * const _platform_pd;
+ Capid_allocator _capid_alloc;
+ Object_identity_reference_tree _cap_tree;
public:
@@ -148,7 +155,7 @@ class Kernel::Pd : public Object, public Cpu::Pd
* \param table translation table of the PD
* \param platform_pd core object of the PD
*/
- Pd(Table * const table, Platform_pd * const platform_pd);
+ Pd(Table * const table, Genode::Platform_pd * const platform_pd);
~Pd();
@@ -158,12 +165,25 @@ class Kernel::Pd : public Object, public Cpu::Pd
void admit(Cpu::Context * const c);
+ static capid_t syscall_create(void * const dst,
+ Genode::Translation_table * tt,
+ Genode::Platform_pd * const pd)
+ {
+ return call(call_id_new_pd(), (Call_arg)dst,
+ (Call_arg)tt, (Call_arg)pd);
+ }
+
+ static void syscall_destroy(Pd * const pd) {
+ call(call_id_delete_pd(), (Call_arg)pd); }
+
/***************
** Accessors **
***************/
- Platform_pd * platform_pd() const { return _platform_pd; }
- Table * translation_table() const { return _table; }
+ Genode::Platform_pd * platform_pd() const { return _platform_pd; }
+ Table * translation_table() const { return _table; }
+ Capid_allocator & capid_alloc() { return _capid_alloc; }
+ Object_identity_reference_tree & cap_tree() { return _cap_tree; }
};
#endif /* _KERNEL__PD_H_ */
diff --git a/repos/base-hw/src/core/include/kernel/signal_receiver.h b/repos/base-hw/src/core/include/kernel/signal_receiver.h
index 94140c32cf..562c152957 100644
--- a/repos/base-hw/src/core/include/kernel/signal_receiver.h
+++ b/repos/base-hw/src/core/include/kernel/signal_receiver.h
@@ -17,7 +17,7 @@
/* Genode includes */
#include
-/* core include */
+#include
#include
namespace Kernel
@@ -46,12 +46,6 @@ namespace Kernel
* Combines signal contexts to an entity that handlers can listen to
*/
class Signal_receiver;
-
- typedef Object_pool Signal_context_pool;
- typedef Object_pool Signal_receiver_pool;
-
- Signal_context_pool * signal_context_pool();
- Signal_receiver_pool * signal_receiver_pool();
}
class Kernel::Signal_ack_handler
@@ -167,8 +161,7 @@ class Kernel::Signal_context_killer
void cancel_waiting();
};
-class Kernel::Signal_context
-: public Object
+class Kernel::Signal_context : public Kernel::Object
{
friend class Signal_receiver;
friend class Signal_context_killer;
@@ -265,10 +258,34 @@ class Kernel::Signal_context
* \retval -1 failed
*/
int kill(Signal_context_killer * const k);
+
+ /**
+ * Create a signal context and assign it to a signal receiver
+ *
+ * \param p memory donation for the kernel signal-context object
+ * \param receiver pointer to signal receiver kernel object
+ * \param imprint user label of the signal context
+ *
+ * \retval capability id of the new kernel object
+ */
+ static capid_t syscall_create(void * p,
+ Signal_receiver * const receiver,
+ unsigned const imprint)
+ {
+ return call(call_id_new_signal_context(), (Call_arg)p,
+ (Call_arg)receiver, (Call_arg)imprint);
+ }
+
+ /**
+ * Destruct a signal context
+ *
+ * \param context pointer to signal context kernel object
+ */
+ static void syscall_destroy(Signal_context * const context) {
+ call(call_id_delete_signal_context(), (Call_arg)context); }
};
-class Kernel::Signal_receiver
-: public Object
+class Kernel::Signal_receiver : public Kernel::Object
{
friend class Signal_context;
friend class Signal_handler;
@@ -326,6 +343,24 @@ class Kernel::Signal_receiver
* Return wether any of the contexts of this receiver is deliverable
*/
bool deliverable();
+
+ /**
+ * Syscall to create a signal receiver
+ *
+ * \param p memory donation for the kernel signal-receiver object
+ *
+ * \retval capability id of the new kernel object
+ */
+ static capid_t syscall_create(void * p) {
+ return call(call_id_new_signal_receiver(), (Call_arg)p); }
+
+ /**
+ * Syscall to destruct a signal receiver
+ *
+ * \param receiver pointer to signal receiver kernel object
+ */
+ static void syscall_destroy(Signal_receiver * const receiver) {
+ call(call_id_delete_signal_receiver(), (Call_arg)receiver); }
};
#endif /* _KERNEL__SIGNAL_RECEIVER_ */
diff --git a/repos/base-hw/src/core/include/kernel/test.h b/repos/base-hw/src/core/include/kernel/test.h
new file mode 100644
index 0000000000..ea65dca240
--- /dev/null
+++ b/repos/base-hw/src/core/include/kernel/test.h
@@ -0,0 +1,26 @@
+/*
+ * \brief Automated testing of kernel internals
+ * \author Stefan Kalkowski
+ * \author Martin Stein
+ * \date 2015-05-21
+ */
+
+/*
+ * Copyright (C) 2015 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 _KERNEL__TEST_H_
+#define _KERNEL__TEST_H_
+
+namespace Kernel {
+
+ /**
+ * Hook that enables automated testing of kernel internals
+ */
+ void test();
+}
+
+#endif /* _KERNEL__TEST_H_ */
diff --git a/repos/base-hw/src/core/include/kernel/thread.h b/repos/base-hw/src/core/include/kernel/thread.h
index 0a4cb75299..209cc7b9aa 100644
--- a/repos/base-hw/src/core/include/kernel/thread.h
+++ b/repos/base-hw/src/core/include/kernel/thread.h
@@ -19,32 +19,29 @@
#include
#include
#include
+#include
+#include
namespace Kernel
{
class Thread;
- class Pd;
-
- typedef Genode::Native_utcb Native_utcb;
/**
* Kernel backend for userland execution-contexts
*/
class Thread;
- typedef Object_pool Thread_pool;
-
- Thread_pool * thread_pool();
+ class Core_thread;
}
class Kernel::Thread
-:
- public Cpu::User_context,
- public Object,
- public Cpu_domain_update, public Ipc_node, public Signal_context_killer,
- public Signal_handler, public Thread_base, public Cpu_job
+: public Kernel::Object,
+ public Cpu::User_context,
+ public Cpu_domain_update, public Ipc_node, public Signal_context_killer,
+ public Signal_handler, public Thread_base, public Cpu_job
{
friend class Thread_event;
+ friend class Core_thread;
private:
@@ -61,11 +58,9 @@ class Kernel::Thread
STOPPED = 7,
};
- State _state;
- Pd * _pd;
- Native_utcb * _utcb_phys;
- Signal_receiver * _signal_receiver;
- char const * const _label;
+ State _state;
+ Signal_receiver * _signal_receiver;
+ char const * const _label;
/**
* Notice that another thread yielded the CPU to this thread
@@ -81,8 +76,8 @@ class Kernel::Thread
* \retval 0 succeeded
* \retval -1 failed
*/
- int _route_event(unsigned const event_id,
- unsigned const signal_context_id);
+ int _route_event(unsigned const event_id,
+ Signal_context * const signal_context_id);
/**
* Map kernel name of thread event to the corresponding member
@@ -183,11 +178,6 @@ class Kernel::Thread
*/
addr_t Thread::* _reg(addr_t const id) const;
- /**
- * Print table of all threads and their current activity
- */
- void _print_activity_table();
-
/**
* Print the activity of the thread
*
@@ -210,11 +200,8 @@ class Kernel::Thread
** Kernel-call back-ends, see kernel-interface headers **
*********************************************************/
- void _call_new_pd();
- void _call_delete_pd();
void _call_new_thread();
void _call_thread_quota();
- void _call_delete_thread();
void _call_start_thread();
void _call_pause_current_thread();
void _call_pause_thread();
@@ -228,15 +215,11 @@ class Kernel::Thread
void _call_update_data_region();
void _call_update_instr_region();
void _call_print_char();
- void _call_new_signal_receiver();
- void _call_new_signal_context();
void _call_await_signal();
void _call_signal_pending();
void _call_submit_signal();
void _call_ack_signal();
void _call_kill_signal_context();
- void _call_delete_signal_context();
- void _call_delete_signal_receiver();
void _call_new_vm();
void _call_delete_vm();
void _call_run_vm();
@@ -244,8 +227,27 @@ class Kernel::Thread
void _call_access_thread_regs();
void _call_route_thread_event();
void _call_new_irq();
- void _call_delete_irq();
void _call_ack_irq();
+ void _call_new_obj();
+ void _call_delete_obj();
+ void _call_delete_cap();
+
+ template
+ void _call_new(ARGS &&... args)
+ {
+ using Object = Core_object;
+ void * dst = (void *)user_arg_1();
+ Object * o = Genode::construct_at