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

@@ -83,7 +83,7 @@ namespace Genode {
/**
* Special paging server class
*/
class Ipc_pager : public Native_capability
class Ipc_pager
{
private:
@@ -108,11 +108,6 @@ namespace Genode {
public:
/**
* Constructor
*/
Ipc_pager();
/**
* Wait for a new fault received as short message IPC
*/
@@ -156,9 +151,9 @@ 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() { return true; }
/**
* Return badge for faulting thread

View File

@@ -1,141 +0,0 @@
/*
* \brief Pager support for Pistachio
* \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>
#include <base/sleep.h>
/* Core includes */
#include <ipc_pager.h>
namespace Pistachio
{
#include <l4/message.h>
#include <l4/ipc.h>
#include <l4/schedule.h>
#include <l4/kdebug.h>
}
using namespace Genode;
using namespace Pistachio;
/*************
** Mapping **
*************/
Mapping::Mapping(addr_t dst_addr, addr_t src_addr,
Cache_attribute, bool io_mem, unsigned l2size,
bool rw, bool grant)
{
L4_Fpage_t fpage = L4_FpageLog2(src_addr, l2size);
fpage += rw ? L4_FullyAccessible : L4_Readable;
if (grant)
_grant_item = L4_GrantItem(fpage, dst_addr);
else
_map_item = L4_MapItem(fpage, dst_addr);
}
Mapping::Mapping() { _map_item = L4_MapItem(L4_Nilpage, 0); }
/***************
** IPC pager **
***************/
void Ipc_pager::wait_for_fault()
{
L4_MsgTag_t result;
L4_ThreadId_t sender = L4_nilthread;
bool failed;
do {
L4_Accept(L4_UntypedWordsAcceptor);
result = L4_Wait(&sender);
failed = L4_IpcFailed(result);
if (failed)
PERR("Page fault IPC error. (continuable)");
if (L4_UntypedWords(result) != 2) {
PERR("Malformed page-fault ipc. (sender = 0x%08lx)",
sender.raw);
failed = true;
}
} while (failed);
L4_Msg_t msg;
// TODO Error checking. Did we really receive 2 words?
L4_Store(result, &msg);
_pf_addr = L4_Get(&msg, 0);
_pf_ip = L4_Get(&msg, 1);
_flags = L4_Label(result);
_last = sender;
}
void Ipc_pager::reply_and_wait_for_fault()
{
/*
* XXX call memory-control if mapping has enabled write-combining
*/
L4_Msg_t msg;
L4_Accept(L4_UntypedWordsAcceptor);
L4_Clear(&msg);
/* this should work even if _map_item is a grant item */
L4_Append(&msg, _map_item);
L4_Load(&msg);
L4_MsgTag_t result = L4_ReplyWait(_last, &_last);
if (L4_IpcFailed(result)) {
PERR("Page fault IPC error. (continuable)");
wait_for_fault();
return;
}
if (L4_UntypedWords(result) != 2) {
PERR("Malformed page-fault ipc. (sender = 0x%08lx)", _last.raw);
wait_for_fault();
return;
}
L4_Clear(&msg);
// TODO Error checking. Did we really receive 2 words?
L4_Store(result, &msg);
_pf_addr = L4_Get(&msg, 0);
_pf_ip = L4_Get(&msg, 1);
_flags = L4_Label(result);
}
void Ipc_pager::acknowledge_wakeup()
{
PERR("acknowledge_wakeup called, not yet implemented");
// /* 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(L4_Myself(), 0)
{ }

View File

@@ -1,10 +1,7 @@
/*
* \brief Pistachio pager framework
* \author Norman Feske
* \brief Pager support for Pistachio
* \author Christian Helmuth
* \date 2006-07-14
*
* FIXME Isn't this file generic?
* \date 2006-06-14
*/
/*
@@ -14,83 +11,128 @@
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/printf.h>
#include <base/sleep.h>
/* Core includes */
#include <ipc_pager.h>
#include <pager.h>
using namespace Genode;
namespace Pistachio {
#include <l4/thread.h>
namespace Pistachio
{
#include <l4/message.h>
#include <l4/ipc.h>
#include <l4/schedule.h>
#include <l4/kdebug.h>
}
/**********************
** Pager activation **
**********************/
using namespace Genode;
using namespace Pistachio;
void Pager_activation_base::entry()
/*************
** Mapping **
*************/
Mapping::Mapping(addr_t dst_addr, addr_t src_addr,
Cache_attribute, bool io_mem, unsigned l2size,
bool rw, bool grant)
{
Ipc_pager pager;
_cap = pager;
_cap_valid.unlock();
L4_Fpage_t fpage = L4_FpageLog2(src_addr, l2size);
Pager_object * obj;
bool reply = false;
fpage += rw ? L4_FullyAccessible : L4_Readable;
while (1) {
if (grant)
_grant_item = L4_GrantItem(fpage, dst_addr);
else
_map_item = L4_MapItem(fpage, dst_addr);
}
if (reply)
pager.reply_and_wait_for_fault();
else
pager.wait_for_fault();
/* lookup referenced object */
Object_pool<Pager_object>::Guard _obj(_ep ? _ep->lookup_and_lock(pager.badge()) : 0);
obj = _obj;
reply = false;
Mapping::Mapping() { _map_item = L4_MapItem(L4_Nilpage, 0); }
/* handle request */
if (obj) {
/* if something strange occurred - leave thread in pagefault */
reply = !obj->pager(pager);
continue;
} else {
/* 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) {
/***************
** IPC pager **
***************/
#warning Check for messages from outside of core
if (0) {
PWRN("page fault to 0x%08lx from unknown partner %lx.",
Pistachio::L4_Myself().raw,
pager.last().raw);
void Ipc_pager::wait_for_fault()
{
L4_MsgTag_t result;
L4_ThreadId_t sender = L4_nilthread;
bool failed;
} else {
do {
L4_Accept(L4_UntypedWordsAcceptor);
result = L4_Wait(&sender);
failed = L4_IpcFailed(result);
if (failed)
PERR("Page fault IPC error. (continuable)");
/*
* 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();
}
if (L4_UntypedWords(result) != 2) {
PERR("Malformed page-fault ipc. (sender = 0x%08lx)",
sender.raw);
failed = true;
}
} while (failed);
L4_Msg_t msg;
// TODO Error checking. Did we really receive 2 words?
L4_Store(result, &msg);
_pf_addr = L4_Get(&msg, 0);
_pf_ip = L4_Get(&msg, 1);
_flags = L4_Label(result);
_last = sender;
}
void Ipc_pager::reply_and_wait_for_fault()
{
/*
* XXX call memory-control if mapping has enabled write-combining
*/
L4_Msg_t msg;
L4_Accept(L4_UntypedWordsAcceptor);
L4_Clear(&msg);
/* this should work even if _map_item is a grant item */
L4_Append(&msg, _map_item);
L4_Load(&msg);
L4_MsgTag_t result = L4_ReplyWait(_last, &_last);
if (L4_IpcFailed(result)) {
PERR("Page fault IPC error. (continuable)");
wait_for_fault();
return;
}
if (L4_UntypedWords(result) != 2) {
PERR("Malformed page-fault ipc. (sender = 0x%08lx)", _last.raw);
wait_for_fault();
return;
}
L4_Clear(&msg);
// TODO Error checking. Did we really receive 2 words?
L4_Store(result, &msg);
_pf_addr = L4_Get(&msg, 0);
_pf_ip = L4_Get(&msg, 1);
_flags = L4_Label(result);
}
void Ipc_pager::acknowledge_wakeup()
{
PERR("acknowledge_wakeup called, not yet implemented");
// /* 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);
}
@@ -98,28 +140,7 @@ void Pager_activation_base::entry()
** 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 = Native_capability(_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

@@ -13,14 +13,14 @@ SRC_CC = cap_session_component.cc \
dump_alloc.cc \
io_mem_session_component.cc \
io_mem_session_support.cc \
ipc_pager.cc \
irq_session_component.cc \
kip.cc \
main.cc \
multiboot_info.cc \
pd_session_component.cc \
pager.cc \
pager_common.cc \
pager_ep.cc \
pager_object.cc \
platform.cc \
platform_pd.cc \
platform_services.cc \
@@ -57,7 +57,8 @@ 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_ep.cc $(GEN_CORE_DIR)
vpath pager_object.cc $(GEN_CORE_DIR)
vpath core_printf.cc $(BASE_DIR)/src/base/console
vpath kip.cc $(REP_DIR)/src/base/kip
vpath %.cc $(REP_DIR)/src/core