sel4: support region fault manager outside core

rm_fault.run works

Issue #2044
This commit is contained in:
Alexander Boettcher 2016-07-08 16:38:48 +02:00 committed by Christian Helmuth
parent 738ca74166
commit 657dd5faad
4 changed files with 270 additions and 40 deletions

View File

@ -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

View File

@ -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;
}
};
}

View File

@ -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 <base/thread.h>
#include <base/object_pool.h>
#include <cap_session/cap_session.h>
#include <pager/capability.h>
#include <ipc_pager.h>
/* core-local includes */
#include <rpc_cap_factory.h>
#include <base/internal/capability_space_sel4.h>
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<Pager_object>::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<Pager_object>,
public Thread_deprecated<PAGER_EP_STACK_SIZE>
{
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_STACK_SIZE>("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_ */

View File

@ -11,13 +11,11 @@
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/sleep.h>
/* core includes */
#include <pager.h>
#include <core_capability_space.h>
#include <install_mapping.h>
#include <platform.h>
/* base-internal includes */
#include <base/internal/capability_space_sel4.h>
@ -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<Pager_object>;
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<Pager_object>(cap);
}
void Pager_entrypoint::entry()
{
using Pool = Object_pool<Pager_object>;
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());
});
}
}