mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
sel4: support region fault manager outside core
rm_fault.run works Issue #2044
This commit is contained in:
parent
738ca74166
commit
657dd5faad
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
187
repos/base-sel4/src/core/include/pager.h
Normal file
187
repos/base-sel4/src/core/include/pager.h
Normal 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_ */
|
@ -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());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user