mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-11 13:22:33 +00:00
parent
2afa25be1d
commit
f7fd7b0b11
@ -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
|
||||
|
@ -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<Pager_object>::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): {
|
||||
|
@ -18,12 +18,24 @@
|
||||
#include <rm_session_component.h>
|
||||
#include <platform.h>
|
||||
#include <platform_thread.h>
|
||||
#include <assert.h>
|
||||
#include <tlb.h>
|
||||
|
||||
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<<sl2, &ram,
|
||||
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 */
|
||||
sl2 = tlb->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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user