/* * \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. */ /* * Copyright (C) 2008-2012 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. */ #include #include #include #include #include #include #include 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; }