parent
2afa25be1d
commit
f7fd7b0b11
|
@ -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
|
||||||
|
|
|
@ -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): {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user