From f7fd7b0b11c63f4990bb2bd39c45e0ed255222cf Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Fri, 30 Aug 2013 16:02:31 +0200 Subject: [PATCH] hw: no assertions in pagers ref #528 --- base-hw/include/base/ipc_pager.h | 5 ++- base-hw/src/base/pager.cc | 31 +++++++++------ base-hw/src/core/rm_session_support.cc | 54 ++++++++++++++++++-------- 3 files changed, 62 insertions(+), 28 deletions(-) diff --git a/base-hw/include/base/ipc_pager.h b/base-hw/include/base/ipc_pager.h index 9444ad528..b3a08cab5 100644 --- a/base-hw/include/base/ipc_pager.h +++ b/base-hw/include/base/ipc_pager.h @@ -106,8 +106,11 @@ namespace Genode /** * 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 diff --git a/base-hw/src/base/pager.cc b/base-hw/src/base/pager.cc index d7e161bb5..687a9f3c9 100644 --- a/base-hw/src/base/pager.cc +++ b/base-hw/src/base/pager.cc @@ -29,23 +29,28 @@ void Pager_activation_base::entry() _cap = pager; _cap_valid.unlock(); - /* wait for the first pagefault */ - bool reply = false; + /* receive and handle faults */ + bool mapping_pending = 0; while (1) { - if (reply) - pager.resolve_and_wait_for_fault(); - else + if (mapping_pending) { + /* apply mapping and await next fault */ + if (pager.resolve_and_wait_for_fault()) { + PERR("failed to resolve page fault"); + pager.wait_for_fault(); + } + } else { pager.wait_for_fault(); - - /* lookup pager object for the current faulter */ + } + /* lookup pager object for current faulter */ Object_pool::Guard o(_ep ? _ep->lookup_and_lock(pager.badge()) : 0); if (!o) { - PERR("%s:%d: Invalid pager object", __FILE__, __LINE__); - while (1) ; + PERR("invalid pager object"); + 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 */ size_t s = Kernel::wait_for_request(); while (1) { + + /* + * FIXME: the message size is a weak indicator for the message type + */ switch (s) { case sizeof(Pagefault): { diff --git a/base-hw/src/core/rm_session_support.cc b/base-hw/src/core/rm_session_support.cc index 3f02169af..3634d7b2f 100644 --- a/base-hw/src/core/rm_session_support.cc +++ b/base-hw/src/core/rm_session_support.cc @@ -18,12 +18,24 @@ #include #include #include -#include #include 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 ** ***************/ @@ -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 */ 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(); - assert(tlb); - + if (!tlb) { + PERR("failed to get PD of RM client-thread"); + return; + } /* update all translation caches */ tlb->remove_region(virt_base, size); Kernel::update_pd(pt->pd_id()); - - /* 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); + regain_ram_from_tlb(tlb); } @@ -52,11 +65,13 @@ void Rm_client::unmap(addr_t core_local_base, addr_t virt_base, size_t size) ** Ipc_pager ** ***************/ -void Ipc_pager::resolve_and_wait_for_fault() +int Ipc_pager::resolve_and_wait_for_fault() { - /* valid mapping? */ - assert(_mapping.valid()); - + /* check mapping */ + if (!_mapping.valid()) { + PERR("invalid mapping"); + return -1; + } /* prepare mapping */ Tlb * const tlb = _pagefault.tlb; Page_flags::access_t const flags = @@ -74,18 +89,25 @@ void Ipc_pager::resolve_and_wait_for_fault() void * ram; bool ram_ok = platform()->ram_alloc()->alloc_aligned(1<insert_translation(_mapping.virt_address, _mapping.phys_address, _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 */ Kernel::resume_faulter(_pagefault.thread_id); /* wait for next page fault */ wait_for_fault(); + return 0; }