diff --git a/repos/base-sel4/lib/mk/core.mk b/repos/base-sel4/lib/mk/core.mk
index 005ba3a35..011371739 100644
--- a/repos/base-sel4/lib/mk/core.mk
+++ b/repos/base-sel4/lib/mk/core.mk
@@ -35,8 +35,7 @@ SRC_CC += \
dump_alloc.cc \
stack_area.cc \
capability_space.cc \
- pager.cc \
- pager_ep.cc
+ pager.cc
LIBS += core_printf base-common syscall
@@ -64,5 +63,4 @@ vpath dataspace_component.cc $(GEN_CORE_DIR)
vpath core_mem_alloc.cc $(GEN_CORE_DIR)
vpath core_rpc_cap_alloc.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)
-vpath pager_ep.cc $(GEN_CORE_DIR)
vpath %.cc $(REP_DIR)/src/core
diff --git a/repos/base-sel4/src/core/include/ipc_pager.h b/repos/base-sel4/src/core/include/ipc_pager.h
index a66759f6c..3245b3be8 100644
--- a/repos/base-sel4/src/core/include/ipc_pager.h
+++ b/repos/base-sel4/src/core/include/ipc_pager.h
@@ -75,6 +75,7 @@ namespace Genode {
private:
addr_t _last; /* faulted thread ID */
+ addr_t _reply_sel; /* selector to save reply cap */
addr_t _pf_addr; /* page-fault address */
addr_t _pf_ip; /* instruction pointer of faulter */
bool _pf_write; /* true on write fault */
@@ -116,21 +117,7 @@ namespace Genode {
/**
* Set destination for next reply
*/
- void set_reply_dst(Native_capability pager_object) {
- _last = pager_object.local_name(); }
-
- /**
- * Answer call without sending a mapping
- *
- * This function is used to acknowledge local calls from one of
- * core's region-manager sessions.
- */
- void acknowledge_wakeup();
-
- /**
- * Returns true if the last request was send from a core thread
- */
- bool request_from_core() { return false; }
+ void reply_save_caller(addr_t sel) { _reply_sel = sel; }
/**
* Return badge for faulting thread
@@ -141,17 +128,6 @@ namespace Genode {
* Return true if page fault was a write fault
*/
bool write_fault() const { return _pf_write; }
-
- /**
- * Return true if last fault was an exception
- */
- bool exception() const
- {
- /*
- * Reflection of exceptions is not supported on this platform.
- */
- return false;
- }
};
}
diff --git a/repos/base-sel4/src/core/include/pager.h b/repos/base-sel4/src/core/include/pager.h
new file mode 100644
index 000000000..7c6785de0
--- /dev/null
+++ b/repos/base-sel4/src/core/include/pager.h
@@ -0,0 +1,187 @@
+/*
+ * \brief Paging-server framework
+ * \author Norman Feske
+ * \author Christian Helmuth
+ * \author Stefan Kalkowski
+ * \date 2006-04-28
+ */
+
+/*
+ * Copyright (C) 2006-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__PAGER_H_
+#define _CORE__INCLUDE__PAGER_H_
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+
+/* core-local includes */
+#include
+#include
+
+namespace Genode {
+
+ /**
+ * Special server object for paging
+ *
+ * A 'Pager_object' is very similar to a 'Rpc_object'. It is just a
+ * special implementation for page-fault handling, which does not allow to
+ * define a "badge" for pager capabilities.
+ */
+ class Pager_object;
+
+ /**
+ * Paging entry point
+ */
+ class Pager_entrypoint;
+
+ enum { PAGER_EP_STACK_SIZE = sizeof(addr_t) * 2048 };
+}
+
+
+class Genode::Pager_object : public Object_pool::Entry
+{
+ protected:
+
+ /**
+ * Local name for this pager object
+ */
+ unsigned long _badge;
+
+ Cpu_session_capability _cpu_session_cap;
+ Thread_capability _thread_cap;
+ Genode::Cap_sel _reply_cap;
+
+ /**
+ * User-level signal handler registered for this pager object via
+ * 'Cpu_session::exception_handler()'.
+ */
+ Signal_context_capability _exception_sigh;
+
+ public:
+
+ /**
+ * Contains information about exception state of corresponding thread.
+ */
+ Thread_state state;
+
+ /**
+ * Constructor
+ *
+ * \param location affinity of paged thread to physical CPU
+ */
+ Pager_object(Cpu_session_capability cpu_sesion, Thread_capability thread,
+ unsigned long badge, Affinity::Location location);
+
+ ~Pager_object();
+
+ unsigned long badge() const { return _badge; }
+
+ unsigned long reply_cap_sel() const { return _reply_cap.value(); }
+
+ /**
+ * Interface to be implemented by a derived class
+ *
+ * \param ps 'Ipc_pager' stream
+ *
+ * Returns !0 on error and pagefault will not be answered.
+ */
+ virtual int pager(Ipc_pager &ps) = 0;
+
+ /**
+ * Wake up the faulter
+ */
+ void wake_up();
+
+ /**
+ * Assign user-level exception handler for the pager object
+ */
+ void exception_handler(Signal_context_capability sigh)
+ {
+ _exception_sigh = sigh;
+ }
+
+ /**
+ * Notify exception handler about the occurrence of an exception
+ */
+ void submit_exception_signal()
+ {
+ if (!_exception_sigh.valid()) return;
+
+ Signal_transmitter transmitter(_exception_sigh);
+ transmitter.submit();
+ }
+
+ /**
+ * Return CPU session that was used to created the thread
+ */
+ Cpu_session_capability cpu_session_cap() const { return _cpu_session_cap; }
+
+ /**
+ * Return thread capability
+ *
+ * This function enables the destructor of the thread's
+ * address-space region map to kill the thread.
+ */
+ Thread_capability thread_cap() const { return _thread_cap; }
+
+ /*
+ * Note in the thread state that an unresolved page
+ * fault occurred.
+ */
+ void unresolved_page_fault_occurred();
+};
+
+
+class Genode::Pager_entrypoint : public Object_pool,
+ public Thread_deprecated
+{
+ private:
+
+ Ipc_pager _pager;
+ Rpc_cap_factory _cap_factory;
+
+ Untyped_capability _pager_object_cap(unsigned long badge);
+
+ public:
+
+ /**
+ * Constructor
+ *
+ * \param cap_factory factory for creating capabilities
+ * for the pager objects managed by this
+ * entry point
+ */
+ Pager_entrypoint(Rpc_cap_factory &cap_factory)
+ :
+ Thread_deprecated("pager_ep"),
+ _cap_factory(cap_factory)
+ { start(); }
+
+ /**
+ * Associate Pager_object with the entry point
+ */
+ Pager_capability manage(Pager_object *obj);
+
+ /**
+ * Dissolve Pager_object from entry point
+ */
+ void dissolve(Pager_object *obj);
+
+
+ /**********************
+ ** Thread interface **
+ **********************/
+
+ void entry();
+};
+
+#endif /* _CORE__INCLUDE__PAGER_H_ */
diff --git a/repos/base-sel4/src/core/pager.cc b/repos/base-sel4/src/core/pager.cc
index 925e6acf4..67f87d43c 100644
--- a/repos/base-sel4/src/core/pager.cc
+++ b/repos/base-sel4/src/core/pager.cc
@@ -11,13 +11,11 @@
* under the terms of the GNU General Public License version 2.
*/
-/* Genode includes */
-#include
-
/* core includes */
#include
#include
#include
+#include
/* base-internal includes */
#include
@@ -53,8 +51,18 @@ struct Fault_info
** IPC pager **
***************/
+
void Ipc_pager::wait_for_fault()
{
+ if (_last && _reply_sel) {
+ seL4_CNode const service = seL4_CapInitThreadCNode;
+ seL4_Word const index = _reply_sel;
+ uint8_t const depth = 32;
+ int ret = seL4_CNode_SaveCaller(service, index, depth);
+ if (ret != seL4_NoError)
+ Genode::error("saving reply cap failed with ", ret);
+ }
+ _reply_sel = 0;
_last = 0;
reply_and_wait_for_fault();
}
@@ -91,22 +99,35 @@ void Ipc_pager::reply_and_wait_for_fault()
}
-void Ipc_pager::acknowledge_wakeup()
-{
- PDBG("not implemented");
-}
-
-
-Ipc_pager::Ipc_pager() : _last(0) { }
+Ipc_pager::Ipc_pager() : _last(0), _reply_sel(0) { }
/******************
** Pager object **
******************/
+Pager_object::Pager_object(Cpu_session_capability cpu_sesion,
+ Thread_capability thread,
+ unsigned long badge, Affinity::Location location)
+:
+ _badge(badge), _cpu_session_cap(cpu_sesion), _thread_cap(thread),
+ _reply_cap(platform_specific()->core_sel_alloc().alloc())
+{ }
+
+
+Pager_object::~Pager_object()
+{
+ seL4_CNode_Delete(seL4_CapInitThreadCNode, _reply_cap.value(), 32);
+ platform_specific()->core_sel_alloc().free(_reply_cap);
+ /* invalidate reply cap for Pager_object::wait_for_fault() _reply_sel */
+ _reply_cap = Cap_sel(0);
+}
+
+
void Pager_object::wake_up()
{
- PDBG("not implemented");
+ seL4_MessageInfo_t const send_msg = seL4_MessageInfo_new(0, 0, 0, 0);
+ seL4_Send(_reply_cap.value(), send_msg);
}
@@ -133,3 +154,51 @@ Untyped_capability Pager_entrypoint::_pager_object_cap(unsigned long badge)
return Capability_space::create_rpc_obj_cap(ep_cap, nullptr, rpc_obj_key);
}
+
+void Pager_entrypoint::dissolve(Pager_object *obj)
+{
+ using Pool = Object_pool;
+
+ if (obj) Pool::remove(obj);
+}
+
+
+Pager_capability Pager_entrypoint::manage(Pager_object *obj)
+{
+ Native_capability cap = _pager_object_cap(obj->badge());
+
+ /* add server object to object pool */
+ obj->cap(cap);
+ insert(obj);
+
+ /* return capability that uses the object id as badge */
+ return reinterpret_cap_cast(cap);
+}
+
+
+void Pager_entrypoint::entry()
+{
+ using Pool = Object_pool;
+
+ bool reply_pending = false;
+
+ while (1) {
+
+ if (reply_pending)
+ _pager.reply_and_wait_for_fault();
+ else
+ _pager.wait_for_fault();
+
+ reply_pending = false;
+
+ Pool::apply(_pager.badge(), [&] (Pager_object *obj) {
+ if (!obj)
+ return;
+
+ /* send reply if page-fault handling succeeded */
+ reply_pending = !obj->pager(_pager);
+ if (!reply_pending)
+ _pager.reply_save_caller(obj->reply_cap_sel());
+ });
+ }
+}