132 lines
2.9 KiB
C++
132 lines
2.9 KiB
C++
/*
|
|
* \brief Pager implementations that are specific for the HW-core
|
|
* \author Martin Stein
|
|
* \date 2012-03-29
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2012-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/pager.h>
|
|
#include <base/printf.h>
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
/***************************
|
|
** Pager_activation_base **
|
|
***************************/
|
|
|
|
void Pager_activation_base::entry()
|
|
{
|
|
/* acknowledge that we're ready to work */
|
|
Ipc_pager pager;
|
|
_cap = pager;
|
|
_cap_valid.unlock();
|
|
|
|
/* wait for the first pagefault */
|
|
bool reply = false;
|
|
while (1)
|
|
{
|
|
if (reply)
|
|
pager.resolve_and_wait_for_fault();
|
|
else
|
|
pager.wait_for_fault();
|
|
|
|
/* lookup pager object for the current faulter */
|
|
Object_pool<Pager_object>::Guard o(_ep ? _ep->lookup_and_lock(pager.badge()) : 0);
|
|
if (!o) {
|
|
PERR("%s:%d: Invalid pager object", __FILE__, __LINE__);
|
|
while (1) ;
|
|
}
|
|
/* let pager handle the pagefault, apply mapping, await pagefault */
|
|
reply = !o->pager(pager);
|
|
}
|
|
}
|
|
|
|
|
|
/**********************
|
|
** Pager_entrypoint **
|
|
**********************/
|
|
|
|
Pager_entrypoint::Pager_entrypoint(Cap_session *,
|
|
Pager_activation_base * const a)
|
|
: _activation(a) { _activation->ep(this); }
|
|
|
|
|
|
void Pager_entrypoint::dissolve(Pager_object * const o) { remove_locked(o); }
|
|
|
|
|
|
Pager_capability Pager_entrypoint::manage(Pager_object * const o)
|
|
{
|
|
/* do we have an activation */
|
|
if (!_activation) return Pager_capability();
|
|
|
|
/* create cap with the object badge as local name */
|
|
Native_capability c;
|
|
c = Native_capability(_activation->cap().dst(), o->badge());
|
|
|
|
/* let activation provide the pager object */
|
|
o->cap(c);
|
|
insert(o);
|
|
|
|
/* return pager-object cap */
|
|
return reinterpret_cap_cast<Pager_object>(c);
|
|
}
|
|
|
|
|
|
/***************
|
|
** Ipc_pager **
|
|
***************/
|
|
|
|
|
|
void Ipc_pager::wait_for_fault()
|
|
{
|
|
/* receive first message */
|
|
size_t s = Kernel::wait_for_request();
|
|
while (1) {
|
|
switch (s) {
|
|
|
|
case sizeof(Pagefault): {
|
|
|
|
/* message is a pagefault */
|
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
|
Pagefault * const pf = (Pagefault *)utcb;
|
|
if (pf->valid())
|
|
{
|
|
/* give our caller the chance to handle the fault */
|
|
_pagefault = *pf;
|
|
return;
|
|
}
|
|
/* pagefault is invalid so get the next message */
|
|
else {
|
|
PERR("%s:%d: Invalid pagefault", __FILE__, __LINE__);
|
|
continue;
|
|
}
|
|
continue; }
|
|
|
|
case sizeof(Pagefault_resolved): {
|
|
|
|
/* message is a release request from a RM session */
|
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
|
Pagefault_resolved * const msg = (Pagefault_resolved *)utcb;
|
|
|
|
/* resume faulter, send ack to RM and get the next message */
|
|
Kernel::resume_thread(msg->pager_object->badge());
|
|
s = Kernel::reply(0, 1);
|
|
continue; }
|
|
|
|
default: {
|
|
|
|
PERR("%s:%d: Invalid message format", __FILE__, __LINE__);
|
|
continue; }
|
|
}
|
|
}
|
|
}
|
|
|