core: unify and simplify paging code (Fix #1641)

For most platforms except of NOVA a distinction between pager entrypoint
and pager activation is not needed, and only exists due to historical
reasons. Moreover, the pager thread's execution path is almost identical
between most platforms excluding NOVA, HW, and Fisco.OC. Therefore,
this commit unifies the pager loop for the other platforms, and removes
the pager activation class.
This commit is contained in:
Stefan Kalkowski
2015-07-29 10:58:17 +02:00
committed by Christian Helmuth
parent a574f73005
commit eafe5e81e3
31 changed files with 644 additions and 1238 deletions

View File

@@ -85,7 +85,7 @@ namespace Genode {
/**
* Special paging server class
*/
class Ipc_pager : public Native_capability
class Ipc_pager
{
private:
@@ -96,11 +96,6 @@ namespace Genode {
public:
/**
* Constructor
*/
Ipc_pager();
/**
* Wait for a new page fault received as short message IPC
*/
@@ -144,9 +139,13 @@ namespace Genode {
void acknowledge_wakeup();
/**
* Return thread ID of last faulter
* Returns true if the last request was send from a core thread
*/
Native_thread_id last() const { return _last; }
bool request_from_core()
{
enum { CORE_TASK_ID = 4 };
return _last.id.task == CORE_TASK_ID;
}
/**
* Return badge for faulting thread

View File

@@ -1,72 +0,0 @@
/*
* \brief Pager support for Fiasco
* \author Christian Helmuth
* \date 2006-06-14
*/
/*
* Copyright (C) 2006-2013 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 <base/printf.h>
/* Core includes */
#include <ipc_pager.h>
namespace Fiasco {
#include <l4/sys/ipc.h>
#include <l4/sys/syscalls.h>
}
using namespace Genode;
using namespace Fiasco;
void Ipc_pager::wait_for_fault()
{
l4_msgdope_t result;
do {
l4_ipc_wait(&_last,
L4_IPC_SHORT_MSG, &_pf_addr, &_pf_ip,
L4_IPC_NEVER, &result);
if (L4_IPC_IS_ERROR(result))
PERR("Ipc error %lx", L4_IPC_ERROR(result));
} while (L4_IPC_IS_ERROR(result));
}
void Ipc_pager::reply_and_wait_for_fault()
{
l4_msgdope_t result;
l4_ipc_reply_and_wait(_last,
L4_IPC_SHORT_FPAGE, _reply_mapping.dst_addr(),
_reply_mapping.fpage().fpage, &_last,
L4_IPC_SHORT_MSG, &_pf_addr, &_pf_ip,
L4_IPC_SEND_TIMEOUT_0, &result);
if (L4_IPC_IS_ERROR(result)) {
PERR("Ipc error %lx", L4_IPC_ERROR(result));
/* ignore all errors and wait for next proper message */
wait_for_fault();
}
}
void Ipc_pager::acknowledge_wakeup()
{
/* answer wakeup call from one of core's region-manager sessions */
l4_msgdope_t result;
l4_ipc_send(_last, L4_IPC_SHORT_MSG, 0, 0, L4_IPC_SEND_TIMEOUT_0, &result);
}
Ipc_pager::Ipc_pager() : Native_capability(Fiasco::l4_myself(), 0) { }

View File

@@ -1,10 +1,7 @@
/*
* \brief Fiasco pager framework
* \author Norman Feske
* \brief Pager support for Fiasco
* \author Christian Helmuth
* \date 2006-07-14
*
* FIXME Isn't this file generic?
* \date 2006-06-14
*/
/*
@@ -14,7 +11,11 @@
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/printf.h>
/* Core includes */
#include <ipc_pager.h>
#include <pager.h>
namespace Fiasco {
@@ -23,101 +24,61 @@ namespace Fiasco {
}
using namespace Genode;
using namespace Fiasco;
/**********************
** Pager activation **
**********************/
/***************
** Ipc_pager **
***************/
void Pager_activation_base::entry()
void Ipc_pager::wait_for_fault()
{
Ipc_pager pager;
_cap = pager;
_cap_valid.unlock();
l4_msgdope_t result;
Pager_object * obj;
bool reply = false;
do {
l4_ipc_wait(&_last,
L4_IPC_SHORT_MSG, &_pf_addr, &_pf_ip,
L4_IPC_NEVER, &result);
while (1) {
if (L4_IPC_IS_ERROR(result))
PERR("Ipc error %lx", L4_IPC_ERROR(result));
if (reply)
pager.reply_and_wait_for_fault();
else
pager.wait_for_fault();
} while (L4_IPC_IS_ERROR(result));
}
/* lookup referenced object */
Object_pool<Pager_object>::Guard _obj(_ep ? _ep->lookup_and_lock(pager.badge()) : 0);
obj = _obj;
reply = false;
/* handle request */
if (obj) {
reply = !obj->pager(pager);
/* something strange occurred - leave thread in pagefault */
continue;
} else {
void Ipc_pager::reply_and_wait_for_fault()
{
l4_msgdope_t result;
/* prevent threads outside of core to mess with our wake-up interface */
enum { CORE_TASK_ID = 4 };
if (pager.last().id.task != CORE_TASK_ID) {
l4_ipc_reply_and_wait(_last,
L4_IPC_SHORT_FPAGE, _reply_mapping.dst_addr(),
_reply_mapping.fpage().fpage, &_last,
L4_IPC_SHORT_MSG, &_pf_addr, &_pf_ip,
L4_IPC_SEND_TIMEOUT_0, &result);
PWRN("page fault from unknown partner %x.%02x",
(int)pager.last().id.task, (int)pager.last().id.lthread);
if (L4_IPC_IS_ERROR(result)) {
PERR("Ipc error %lx", L4_IPC_ERROR(result));
} else {
/* ignore all errors and wait for next proper message */
wait_for_fault();
}
}
/*
* We got a request from one of cores region-manager sessions
* to answer the pending page fault of a resolved region-manager
* client. Hence, we have to send the page-fault reply to the
* specified thread and answer the call of the region-manager
* session.
*
* When called from a region-manager session, we receive the
* core-local address of the targeted pager object via the
* first message word, which corresponds to the 'fault_ip'
* argument of normal page-fault messages.
*/
obj = reinterpret_cast<Pager_object *>(pager.fault_ip());
/* send reply to the calling region-manager session */
pager.acknowledge_wakeup();
/* answer page fault of resolved pager object */
pager.set_reply_dst(obj->cap());
pager.acknowledge_wakeup();
}
}
};
void Ipc_pager::acknowledge_wakeup()
{
/* answer wakeup call from one of core's region-manager sessions */
l4_msgdope_t result;
l4_ipc_send(_last, L4_IPC_SHORT_MSG, 0, 0, L4_IPC_SEND_TIMEOUT_0, &result);
}
/**********************
** Pager entrypoint **
** Pager Entrypoint **
**********************/
Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base *a)
: _activation(a)
{ _activation->ep(this); }
void Pager_entrypoint::dissolve(Pager_object *obj)
Untyped_capability Pager_entrypoint::_manage(Pager_object *obj)
{
remove_locked(obj);
}
Pager_capability Pager_entrypoint::manage(Pager_object *obj)
{
/* return invalid capability if no activation is present */
if (!_activation) return Pager_capability();
Native_capability cap(_activation->cap().dst(), 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);
return Untyped_capability(_tid.l4id, obj->badge());
}

View File

@@ -12,12 +12,12 @@ SRC_CC += cap_session_component.cc \
io_mem_session_component.cc \
io_mem_session_support.cc \
io_port_session_component.cc \
ipc_pager.cc \
irq_session_component.cc \
main.cc \
multiboot_info.cc \
pager.cc \
pager_common.cc \
pager_ep.cc \
pager_object.cc \
pd_session_component.cc \
platform.cc \
platform_pd.cc \
@@ -58,6 +58,7 @@ vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath dataspace_component.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)
vpath context_area.cc $(GEN_CORE_DIR)
vpath pager_common.cc $(GEN_CORE_DIR)
vpath pager_object.cc $(GEN_CORE_DIR)
vpath pager_ep.cc $(GEN_CORE_DIR)
vpath core_printf.cc $(BASE_DIR)/src/base/console
vpath %.cc $(REP_DIR)/src/core