hw: no assertions in pagers

ref #528
This commit is contained in:
Martin Stein 2013-08-30 16:02:31 +02:00 committed by Norman Feske
parent 2afa25be1d
commit f7fd7b0b11
3 changed files with 62 additions and 28 deletions

View File

@ -106,8 +106,11 @@ namespace Genode
/** /**
* Resolve current pagefault and wait for a new one * Resolve current pagefault and wait for a new one
*
* \retval 0 succeeded
* \retval !=0 failed
*/ */
void resolve_and_wait_for_fault(); int resolve_and_wait_for_fault();
/** /**
* Request instruction pointer of current page fault * Request instruction pointer of current page fault

View File

@ -29,23 +29,28 @@ void Pager_activation_base::entry()
_cap = pager; _cap = pager;
_cap_valid.unlock(); _cap_valid.unlock();
/* wait for the first pagefault */ /* receive and handle faults */
bool reply = false; bool mapping_pending = 0;
while (1) while (1)
{ {
if (reply) if (mapping_pending) {
pager.resolve_and_wait_for_fault(); /* apply mapping and await next fault */
else if (pager.resolve_and_wait_for_fault()) {
PERR("failed to resolve page fault");
pager.wait_for_fault();
}
} else {
pager.wait_for_fault(); pager.wait_for_fault();
}
/* lookup pager object for the current faulter */ /* lookup pager object for current faulter */
Object_pool<Pager_object>::Guard o(_ep ? _ep->lookup_and_lock(pager.badge()) : 0); Object_pool<Pager_object>::Guard o(_ep ? _ep->lookup_and_lock(pager.badge()) : 0);
if (!o) { if (!o) {
PERR("%s:%d: Invalid pager object", __FILE__, __LINE__); PERR("invalid pager object");
while (1) ; mapping_pending = 0;
} else {
/* try to find an appropriate mapping */
mapping_pending = !o->pager(pager);
} }
/* let pager handle the pagefault, apply mapping, await pagefault */
reply = !o->pager(pager);
} }
} }
@ -90,6 +95,10 @@ void Ipc_pager::wait_for_fault()
/* receive first message */ /* receive first message */
size_t s = Kernel::wait_for_request(); size_t s = Kernel::wait_for_request();
while (1) { while (1) {
/*
* FIXME: the message size is a weak indicator for the message type
*/
switch (s) { switch (s) {
case sizeof(Pagefault): { case sizeof(Pagefault): {

View File

@ -18,12 +18,24 @@
#include <rm_session_component.h> #include <rm_session_component.h>
#include <platform.h> #include <platform.h>
#include <platform_thread.h> #include <platform_thread.h>
#include <assert.h>
#include <tlb.h> #include <tlb.h>
using namespace Genode; using namespace Genode;
/**
* Try to regain administrative memory that isn't used anymore from 'tlb'
*/
static void regain_ram_from_tlb(Tlb * tlb)
{
size_t s;
void * base;
while (tlb->regain_memory(base, s)) {
platform()->ram_alloc()->free(base, s);
}
}
/*************** /***************
** Rm_client ** ** Rm_client **
***************/ ***************/
@ -33,18 +45,19 @@ void Rm_client::unmap(addr_t core_local_base, addr_t virt_base, size_t size)
{ {
/* get software TLB of the thread that we serve */ /* get software TLB of the thread that we serve */
Platform_thread * const pt = Kernel::get_thread(badge()); Platform_thread * const pt = Kernel::get_thread(badge());
assert(pt); if (!pt) {
PERR("failed to get RM client-thread");
return;
}
Tlb * const tlb = pt->tlb(); Tlb * const tlb = pt->tlb();
assert(tlb); if (!tlb) {
PERR("failed to get PD of RM client-thread");
return;
}
/* update all translation caches */ /* update all translation caches */
tlb->remove_region(virt_base, size); tlb->remove_region(virt_base, size);
Kernel::update_pd(pt->pd_id()); Kernel::update_pd(pt->pd_id());
regain_ram_from_tlb(tlb);
/* try to regain administrative memory that has been freed by unmap */
size_t s;
void * base;
while (tlb->regain_memory(base, s)) platform()->ram_alloc()->free(base, s);
} }
@ -52,11 +65,13 @@ void Rm_client::unmap(addr_t core_local_base, addr_t virt_base, size_t size)
** Ipc_pager ** ** Ipc_pager **
***************/ ***************/
void Ipc_pager::resolve_and_wait_for_fault() int Ipc_pager::resolve_and_wait_for_fault()
{ {
/* valid mapping? */ /* check mapping */
assert(_mapping.valid()); if (!_mapping.valid()) {
PERR("invalid mapping");
return -1;
}
/* prepare mapping */ /* prepare mapping */
Tlb * const tlb = _pagefault.tlb; Tlb * const tlb = _pagefault.tlb;
Page_flags::access_t const flags = Page_flags::access_t const flags =
@ -74,18 +89,25 @@ void Ipc_pager::resolve_and_wait_for_fault()
void * ram; void * ram;
bool ram_ok = platform()->ram_alloc()->alloc_aligned(1<<sl2, &ram, bool ram_ok = platform()->ram_alloc()->alloc_aligned(1<<sl2, &ram,
sl2).is_ok(); sl2).is_ok();
assert(ram_ok); if (!ram_ok) {
PERR("failed to allocate additional RAM for TLB");
return -1;
}
/* try to translate again with extra RAM */ /* try to translate again with extra RAM */
sl2 = tlb->insert_translation(_mapping.virt_address, sl2 = tlb->insert_translation(_mapping.virt_address,
_mapping.phys_address, _mapping.phys_address,
_mapping.size_log2, flags, ram); _mapping.size_log2, flags, ram);
assert(!sl2); if (sl2) {
PERR("TLB needs to much RAM");
regain_ram_from_tlb(tlb);
return -1;
}
} }
/* wake up faulter */ /* wake up faulter */
Kernel::resume_faulter(_pagefault.thread_id); Kernel::resume_faulter(_pagefault.thread_id);
/* wait for next page fault */ /* wait for next page fault */
wait_for_fault(); wait_for_fault();
return 0;
} }