2011-12-22 16:19:25 +01:00
|
|
|
/*
|
2015-07-29 10:58:17 +02:00
|
|
|
* \brief Pager support for OKL4
|
2011-12-22 16:19:25 +01:00
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2009-03-31
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2013-01-10 21:44:47 +01:00
|
|
|
* Copyright (C) 2009-2013 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
2015-07-29 10:58:17 +02:00
|
|
|
/* Genode includes */
|
|
|
|
#include <base/printf.h>
|
|
|
|
|
2016-03-08 17:44:54 +01:00
|
|
|
/* core includes */
|
2015-07-29 10:58:17 +02:00
|
|
|
#include <ipc_pager.h>
|
2015-06-19 14:58:18 +02:00
|
|
|
#include <pager.h>
|
2016-03-08 17:44:54 +01:00
|
|
|
#include <platform_thread.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2016-03-11 17:32:43 +01:00
|
|
|
/* base-internal includes */
|
|
|
|
#include <base/internal/native_thread.h>
|
2016-06-13 13:53:58 +02:00
|
|
|
#include <base/internal/native_utcb.h>
|
2016-03-11 17:32:43 +01:00
|
|
|
|
2015-07-29 10:58:17 +02:00
|
|
|
namespace Okl4 { extern "C" {
|
|
|
|
#include <l4/message.h>
|
|
|
|
#include <l4/ipc.h>
|
|
|
|
#include <l4/schedule.h>
|
|
|
|
#include <l4/kdebug.h>
|
|
|
|
} }
|
|
|
|
|
|
|
|
static const bool verbose_page_fault = false;
|
|
|
|
static const bool verbose_exception = false;
|
|
|
|
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
using namespace Genode;
|
2015-07-29 10:58:17 +02:00
|
|
|
using namespace Okl4;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2015-07-29 10:58:17 +02:00
|
|
|
/**
|
|
|
|
* Print page-fault information in a human-readable form
|
|
|
|
*/
|
|
|
|
static inline void print_page_fault(L4_Word_t type, L4_Word_t addr, L4_Word_t ip,
|
|
|
|
unsigned long badge)
|
|
|
|
{
|
|
|
|
printf("page (%s%s%s) fault at fault_addr=%lx, fault_ip=%lx, from=%lx\n",
|
|
|
|
type & L4_Readable ? "r" : "-",
|
|
|
|
type & L4_Writable ? "w" : "-",
|
|
|
|
type & L4_eXecutable ? "x" : "-",
|
|
|
|
addr, ip, badge);
|
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
|
2015-07-29 10:58:17 +02:00
|
|
|
/**
|
|
|
|
* Return the global thread ID of the calling thread
|
|
|
|
*
|
|
|
|
* On OKL4 we cannot use 'L4_Myself()' to determine our own thread's
|
|
|
|
* identity. By convention, each thread stores its global ID in a
|
|
|
|
* defined entry of its UTCB.
|
|
|
|
*/
|
|
|
|
static inline Okl4::L4_ThreadId_t thread_get_my_global_id()
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2015-07-29 10:58:17 +02:00
|
|
|
Okl4::L4_ThreadId_t myself;
|
|
|
|
myself.raw = Okl4::__L4_TCR_ThreadWord(UTCB_TCR_THREAD_WORD_MYSELF);
|
|
|
|
return myself;
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-29 10:58:17 +02:00
|
|
|
/*************
|
|
|
|
** Mapping **
|
|
|
|
*************/
|
|
|
|
|
|
|
|
Mapping::Mapping(addr_t dst_addr, addr_t src_addr,
|
|
|
|
Cache_attribute cacheability, bool io_mem,
|
|
|
|
unsigned l2size, bool rw)
|
|
|
|
:
|
|
|
|
_fpage(L4_FpageLog2(dst_addr, l2size)),
|
|
|
|
/*
|
|
|
|
* OKL4 does not support write-combining as mapping attribute.
|
|
|
|
*/
|
|
|
|
_phys_desc(L4_PhysDesc(src_addr, 0))
|
|
|
|
{
|
|
|
|
L4_Set_Rights(&_fpage, rw ? L4_ReadWriteOnly : L4_ReadeXecOnly);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Mapping::Mapping() { }
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2015-07-29 10:58:17 +02:00
|
|
|
/***************
|
|
|
|
** IPC pager **
|
|
|
|
***************/
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2015-07-29 10:58:17 +02:00
|
|
|
void Ipc_pager::wait_for_fault()
|
|
|
|
{
|
|
|
|
/* wait for fault */
|
|
|
|
_faulter_tag = L4_Wait(&_last);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read fault information
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* exception */
|
2016-05-11 18:21:47 +02:00
|
|
|
if (exception()) {
|
2015-07-29 10:58:17 +02:00
|
|
|
L4_StoreMR(1, &_fault_ip);
|
|
|
|
|
|
|
|
if (verbose_exception)
|
|
|
|
PERR("Exception (label 0x%x) occured in space %d at IP 0x%p",
|
|
|
|
(int)L4_Label(_faulter_tag), (int)L4_SenderSpace().raw,
|
|
|
|
(void *)_fault_ip);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* page fault */
|
|
|
|
else {
|
|
|
|
L4_StoreMR(1, &_fault_addr);
|
|
|
|
L4_StoreMR(2, &_fault_ip);
|
|
|
|
|
|
|
|
if (verbose_page_fault)
|
|
|
|
print_page_fault(L4_Label(_faulter_tag), _fault_addr, _fault_ip, _last.raw);
|
|
|
|
}
|
|
|
|
_last_space = L4_SenderSpace().raw;
|
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2015-07-29 10:58:17 +02:00
|
|
|
|
|
|
|
void Ipc_pager::reply_and_wait_for_fault()
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2015-07-29 10:58:17 +02:00
|
|
|
L4_SpaceId_t to_space;
|
|
|
|
to_space.raw = L4_ThreadNo(_last) >> Thread_id_bits::THREAD;
|
|
|
|
|
|
|
|
/* map page to faulting space */
|
|
|
|
int ret = L4_MapFpage(to_space, _reply_mapping.fpage(),
|
|
|
|
_reply_mapping.phys_desc());
|
|
|
|
|
|
|
|
if (ret != 1)
|
|
|
|
PERR("L4_MapFpage returned %d, error_code=%d",
|
|
|
|
ret, (int)L4_ErrorCode());
|
|
|
|
|
|
|
|
/* reply to page-fault message to resume the faulting thread */
|
|
|
|
acknowledge_wakeup();
|
|
|
|
|
|
|
|
wait_for_fault();
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-29 10:58:17 +02:00
|
|
|
void Ipc_pager::acknowledge_wakeup()
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2015-07-29 10:58:17 +02:00
|
|
|
/* answer wakeup call from one of core's region-manager sessions */
|
|
|
|
L4_LoadMR(0, 0);
|
|
|
|
L4_Send(_last);
|
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
|
2015-07-29 10:58:17 +02:00
|
|
|
/**********************
|
|
|
|
** Pager entrypoint **
|
|
|
|
**********************/
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2015-08-10 13:34:16 +02:00
|
|
|
Untyped_capability Pager_entrypoint::_pager_object_cap(unsigned long badge)
|
2015-07-29 10:58:17 +02:00
|
|
|
{
|
2016-03-11 17:32:43 +01:00
|
|
|
return Untyped_capability(native_thread().l4id, badge);
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|