Hi, As a toy exercise I'm trying to write a very simple custom pager which simply allocates memory from RAM to handle page faults. When I try to handle the fault I get a region conflict exception. Can someone tell me why?? I think I am missing something fundamental here.
Thanks Daniel
----
#include <base/printf.h> #include <base/sleep.h> #include <base/rpc_server.h> #include <cap_session/connection.h> #include <dataspace/client.h> #include <rom_session/connection.h> #include <rm_session/connection.h> #include <ram_session/connection.h> #include <root/component.h> #include <util/avl_string.h> #include <util/misc_math.h> #include <assert.h>
#define PAGE_SIZE 4096
using namespace Genode;
namespace Test {
/** * Example pager class * * @return */ class Pager : public Thread<8192> { private:
Signal_receiver _receiver;
public:
Signal_receiver *signal_receiver() { return &_receiver; }
void entry(); };
/** * Example backing store class - this one uses physical memory * */ class Physical_backing_store : public Signal_context { private: Rm_connection _rm; size_t _size;
public: // ctor Physical_backing_store(size_t size): _rm(0,_size) { _size = size; assert(_size > 0); }
virtual ~Physical_backing_store() { }
/** * Page fault handler. * */ void handle_fault() { Rm_session::State state = _rm.state();
printf("Test::Physical_backing_store:: 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);
if (state.type == Rm_session::READY) return;
try {
Dataspace_capability _ds; try { _ds = env()->ram_session()->alloc(PAGE_SIZE); } catch(...) { PERR("Actual page allocation failed.\n"); }
_rm.attach_at(_ds, state.addr & ~(PAGE_SIZE - 1));
PDBG("attached data space OK!\n"); } catch (Genode::Rm_session::Region_conflict) { PERR("Region conflict - this should not happen\n"); } catch (Genode::Rm_session::Out_of_metadata) { PERR("Out of meta data!\n"); } catch(...) { PERR("Something else caused attach to fail in fault handler.\n"); }
return; }
Rm_connection *rm() { return &_rm; } Dataspace_capability ds() { return _rm.dataspace(); }
void connect_pager(Pager& _pager) { /* connect pager signal receiver to the fault handler */ _rm.fault_handler(_pager.signal_receiver()->manage(this)); }
};
/** * Entry point for pager thread. * */ void Pager::entry() { printf("Pager thread started OK.\n");
while (true) { try { Signal signal = _receiver.wait_for_signal();
for (int i = 0; i < signal.num(); i++) { static_cast<Physical_backing_store *>(signal.context())->handle_fault(); } } catch (...) { PDBG("unexpected error while waiting for signal"); } } }
}
int main() { Genode::printf("Test-pager example. ;-))\n");
Test::Pager _pager;
/* start pager thread */ _pager.start();
/* create dataspace etc. */ try {
enum { MANAGED_DS_SIZE = 64*1024*1024 }; Test::Physical_backing_store bs(MANAGED_DS_SIZE);
/* connect pager to fault handler */ bs.connect_pager(_pager);
/* attach to dataspace */ char * addr = (char*) env()->rm_session()->attach(bs.ds()); assert(addr);
/* trigger read fault */ printf("!!!Triggering fault...\n"); printf("%c%c%c\n",addr[0],addr[1],addr[2]);
printf("Fault handled OK.\n");
} catch(...) { PERR("Something failed ????.\n"); }
printf("test-pager completed.\n"); Genode::sleep_forever(); return 0; }