90 lines
2.2 KiB
C++
90 lines
2.2 KiB
C++
/*
|
|
* \brief RM- and pager implementations specific for base-hw and core
|
|
* \author Martin Stein
|
|
* \date 2012-02-12
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2012-2013 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU General Public License version 2.
|
|
*/
|
|
|
|
/* Genode includes */
|
|
#include <base/ipc_pager.h>
|
|
|
|
/* core includes */
|
|
#include <rm_session_component.h>
|
|
#include <platform.h>
|
|
#include <platform_thread.h>
|
|
#include <assert.h>
|
|
#include <tlb.h>
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
/***************
|
|
** Rm_client **
|
|
***************/
|
|
|
|
|
|
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);
|
|
Tlb * const tlb = pt->tlb();
|
|
assert(tlb);
|
|
|
|
/* 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);
|
|
}
|
|
|
|
|
|
/***************
|
|
** Ipc_pager **
|
|
***************/
|
|
|
|
void Ipc_pager::resolve_and_wait_for_fault()
|
|
{
|
|
/* valid mapping? */
|
|
assert(_mapping.valid());
|
|
|
|
/* prepare mapping */
|
|
Tlb * const tlb = _pagefault.tlb;
|
|
Page_flags::access_t const flags =
|
|
Page_flags::resolve_and_wait_for_fault(_mapping.writable,
|
|
_mapping.write_combined,
|
|
_mapping.io_mem);
|
|
|
|
/* insert mapping into TLB */
|
|
unsigned sl2;
|
|
sl2 = tlb->insert_translation(_mapping.virt_address, _mapping.phys_address,
|
|
_mapping.size_log2, flags);
|
|
if (sl2)
|
|
{
|
|
/* try to get some natural aligned space */
|
|
void * space;
|
|
assert(platform()->ram_alloc()->alloc_aligned(1<<sl2, &space, sl2).is_ok());
|
|
|
|
/* try to translate again with extra space */
|
|
sl2 = tlb->insert_translation(_mapping.virt_address,
|
|
_mapping.phys_address,
|
|
_mapping.size_log2, flags, space);
|
|
assert(!sl2);
|
|
}
|
|
/* wake up faulter */
|
|
Kernel::resume_faulter(_pagefault.thread_id);
|
|
|
|
/* wait for next page fault */
|
|
wait_for_fault();
|
|
}
|
|
|