2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief Testing nested region-manager sessions
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2008-09-27
|
|
|
|
*
|
|
|
|
* The program uses two threads. A local fault-handler thread waits for fault
|
|
|
|
* signals regarding a sub-region-manager session that is mapped into the local
|
|
|
|
* address space as a dataspace. If a fault occurs, this thread allocates a new
|
|
|
|
* dataspace and attaches it to the faulting address to resolve the fault. The
|
|
|
|
* main thread performs memory accesses at the local address range that is
|
|
|
|
* backed by the sub-region-manager session. Thereby, it triggers
|
|
|
|
* region-manager faults.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2012-01-03 15:35:05 +01:00
|
|
|
* Copyright (C) 2008-2012 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <base/printf.h>
|
|
|
|
#include <base/env.h>
|
|
|
|
#include <base/thread.h>
|
|
|
|
#include <base/signal.h>
|
|
|
|
#include <cap_session/connection.h>
|
|
|
|
#include <rm_session/connection.h>
|
|
|
|
#include <dataspace/client.h>
|
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
MANAGED_SIZE = 0x00010000,
|
|
|
|
PAGE_SIZE = 4096,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Region-manager fault handler resolves faults by attaching new dataspaces
|
|
|
|
*/
|
|
|
|
class Local_fault_handler : public Thread<4096>
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
Rm_session *_rm_session;
|
|
|
|
Signal_receiver *_receiver;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Local_fault_handler(Rm_session *rm_session, Signal_receiver *receiver)
|
|
|
|
:
|
|
|
|
_rm_session(rm_session), _receiver(receiver)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
void handle_fault()
|
|
|
|
{
|
|
|
|
Rm_session::State state = _rm_session->state();
|
|
|
|
|
|
|
|
printf("rm session state is %s, pf_addr=0x%lx\n",
|
|
|
|
state.type == Rm_session::READ_FAULT ? "READ_FAULT" :
|
|
|
|
state.type == Rm_session::WRITE_FAULT ? "WRITE_FAULT" :
|
|
|
|
state.type == Rm_session::EXEC_FAULT ? "EXEC_FAULT" : "READY",
|
|
|
|
state.addr);
|
|
|
|
|
|
|
|
printf("allocate dataspace and attach it to sub rm session\n");
|
|
|
|
Dataspace_capability ds = env()->ram_session()->alloc(PAGE_SIZE);
|
|
|
|
_rm_session->attach_at(ds, state.addr & ~(PAGE_SIZE - 1));
|
|
|
|
|
|
|
|
printf("returning from handle_fault\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void entry()
|
|
|
|
{
|
|
|
|
while (true) {
|
|
|
|
printf("fault handler: waiting for fault signal\n");
|
|
|
|
Signal signal = _receiver->wait_for_signal();
|
|
|
|
printf("received %d fault signals\n", signal.num());
|
|
|
|
for (int i = 0; i < signal.num(); i++)
|
|
|
|
handle_fault();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
printf("--- nested region-manager test ---\n");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize sub-region-manager session and set up a local fault handler
|
|
|
|
* for it.
|
|
|
|
*/
|
|
|
|
static Rm_connection sub_rm(0, MANAGED_SIZE);
|
|
|
|
static Cap_connection cap;
|
|
|
|
static Signal_receiver receiver;
|
|
|
|
static Signal_context context;
|
|
|
|
sub_rm.fault_handler(receiver.manage(&context));
|
|
|
|
static Local_fault_handler fault_handler(&sub_rm, &receiver);
|
|
|
|
fault_handler.start();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Attach sub-region-manager session as dataspace to the local address
|
|
|
|
* space.
|
|
|
|
*/
|
|
|
|
void *addr = env()->rm_session()->attach(sub_rm.dataspace());
|
|
|
|
|
|
|
|
printf("attached sub dataspace at local address 0x%p\n", addr);
|
|
|
|
Dataspace_client client(sub_rm.dataspace());
|
|
|
|
printf("sub dataspace size is %u should be %u\n", client.size(), MANAGED_SIZE);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Walk through the address range belonging to the sub-region-manager session
|
|
|
|
*/
|
|
|
|
char *managed = (char *)addr;
|
|
|
|
for (int i = 0; i < MANAGED_SIZE; i += PAGE_SIZE/16) {
|
|
|
|
printf("write to %p\n", &managed[i]);
|
|
|
|
managed[i] = 13;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("--- finished nested region-manager test ---\n");
|
|
|
|
return 0;
|
|
|
|
}
|