2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief Pager support for Fiasco.OC
|
|
|
|
* \author Stefan Kalkowski
|
|
|
|
* \date 2011-01-11
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2013-01-10 21:44:47 +01:00
|
|
|
* Copyright (C) 2011-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-06-19 14:58:18 +02:00
|
|
|
/* Genode includes */
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <base/printf.h>
|
|
|
|
#include <base/thread.h>
|
|
|
|
|
2015-06-19 14:58:18 +02:00
|
|
|
/* Core includes */
|
|
|
|
#include <ipc_pager.h>
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
namespace Fiasco {
|
|
|
|
#include <l4/sys/ipc.h>
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
using namespace Fiasco;
|
|
|
|
|
|
|
|
void Ipc_pager::_parse(unsigned long label) {
|
|
|
|
_badge = label & ~0x3;
|
|
|
|
_parse_msg_type();
|
|
|
|
if (_type == PAGEFAULT || _type == EXCEPTION)
|
|
|
|
_parse_pagefault();
|
|
|
|
if (_type == PAUSE || _type == EXCEPTION)
|
|
|
|
memcpy(&_regs, l4_utcb_exc(), sizeof(l4_exc_regs_t));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Ipc_pager::_parse_pagefault()
|
|
|
|
{
|
|
|
|
if (_tag.is_exception()) {
|
|
|
|
_pf_addr = l4_utcb_exc_pfa(l4_utcb_exc());
|
|
|
|
_pf_ip = l4_utcb_exc_pc(l4_utcb_exc());
|
|
|
|
} else {
|
|
|
|
_pf_addr = l4_utcb_mr()->mr[0];
|
|
|
|
_pf_ip = l4_utcb_mr()->mr[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Ipc_pager::_parse_msg_type()
|
|
|
|
{
|
|
|
|
if (_tag.is_exception() && !l4_utcb_exc_is_pf(l4_utcb_exc())) {
|
|
|
|
_parse_exception();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_tag.is_page_fault())
|
|
|
|
_type = PAGEFAULT;
|
|
|
|
else {
|
|
|
|
_type = WAKE_UP;
|
|
|
|
_pf_ip = l4_utcb_mr()->mr[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-03 19:45:53 +01:00
|
|
|
/* Build with frame pointer to make GDB backtraces work. See issue #1061. */
|
|
|
|
__attribute__((optimize("-fno-omit-frame-pointer")))
|
|
|
|
__attribute__((noinline))
|
2011-12-22 16:19:25 +01:00
|
|
|
void Ipc_pager::wait_for_fault()
|
|
|
|
{
|
|
|
|
l4_umword_t label;
|
|
|
|
|
|
|
|
do {
|
|
|
|
_tag = l4_ipc_wait(l4_utcb(), &label, L4_IPC_NEVER);
|
|
|
|
int err = l4_ipc_error(_tag, l4_utcb());
|
|
|
|
if (!err) {
|
|
|
|
_parse(label);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
PERR("Ipc error %d in pagefault from %lx", err, label & ~0x3);
|
|
|
|
} while (true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Ipc_pager::reply_and_wait_for_fault()
|
|
|
|
{
|
|
|
|
l4_umword_t label;
|
|
|
|
l4_msgtag_t snd_tag = l4_msgtag(0, 0, 1, 0);
|
|
|
|
|
|
|
|
l4_umword_t grant = _reply_mapping.grant() ? L4_MAP_ITEM_GRANT : 0;
|
|
|
|
l4_utcb_mr()->mr[0] = _reply_mapping.dst_addr() | L4_ITEM_MAP | grant;
|
2012-06-18 15:20:31 +02:00
|
|
|
|
2014-06-19 16:37:31 +02:00
|
|
|
switch (_reply_mapping.cacheability()) {
|
|
|
|
case WRITE_COMBINED:
|
2012-06-18 15:20:31 +02:00
|
|
|
l4_utcb_mr()->mr[0] |= L4_FPAGE_BUFFERABLE << 4;
|
2014-06-19 16:37:31 +02:00
|
|
|
break;
|
|
|
|
case CACHED:
|
|
|
|
l4_utcb_mr()->mr[0] |= L4_FPAGE_CACHEABLE << 4;
|
|
|
|
break;
|
|
|
|
case UNCACHED:
|
|
|
|
if (!_reply_mapping.iomem())
|
|
|
|
l4_utcb_mr()->mr[0] |= L4_FPAGE_BUFFERABLE << 4;
|
|
|
|
else
|
|
|
|
l4_utcb_mr()->mr[0] |= L4_FPAGE_UNCACHEABLE << 4;
|
|
|
|
break;
|
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
l4_utcb_mr()->mr[1] = _reply_mapping.fpage().raw;
|
|
|
|
|
2016-01-23 14:42:55 +01:00
|
|
|
_tag = l4_ipc_send_and_wait(_last.kcap, l4_utcb(), snd_tag,
|
2011-12-22 16:19:25 +01:00
|
|
|
&label, L4_IPC_SEND_TIMEOUT_0);
|
|
|
|
int err = l4_ipc_error(_tag, l4_utcb());
|
|
|
|
if (err) {
|
|
|
|
PERR("Ipc error %d in pagefault from %lx", err, label & ~0x3);
|
|
|
|
wait_for_fault();
|
|
|
|
} else
|
|
|
|
_parse(label);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Ipc_pager::acknowledge_wakeup()
|
|
|
|
{
|
2016-01-23 14:42:55 +01:00
|
|
|
l4_cap_idx_t dst = Fiasco::Capability::valid(_last.kcap) ? _last.kcap : L4_SYSF_REPLY;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/* answer wakeup call from one of core's region-manager sessions */
|
|
|
|
l4_ipc_send(dst, l4_utcb(), l4_msgtag(0, 0, 0, 0), L4_IPC_SEND_TIMEOUT_0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-26 11:49:00 +02:00
|
|
|
void Ipc_pager::acknowledge_exception()
|
|
|
|
{
|
|
|
|
memcpy(l4_utcb_exc(), &_regs, sizeof(l4_exc_regs_t));
|
2016-01-23 14:42:55 +01:00
|
|
|
l4_cap_idx_t dst = Fiasco::Capability::valid(_last.kcap) ? _last.kcap : L4_SYSF_REPLY;
|
2013-09-26 11:49:00 +02:00
|
|
|
l4_ipc_send(dst, l4_utcb(), l4_msgtag(0, L4_UTCB_EXCEPTION_REGS_SIZE, 0, 0), L4_IPC_SEND_TIMEOUT_0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
Ipc_pager::Ipc_pager()
|
Fiasco.OC: several capability ref-counter fixes.
This commit fixes several issues that were triggered e.g. by the
'noux_tool_chain' run-script (fix #208 in part). The following problems
are tackled:
* Don't reference count capability selectors within a task that are actually
controlled by core (all beneath 0x200000), because it's undecideable which
"version" of a capability selector we currently use, e.g. a thread gets
destroyed and a new one gets created immediately some other thread might
have a Native_capability pointing to the already destroyed thread's gate
capability-slot, that is now a new valid one (the one of the new thread)
* In core we cannot invalidate and remove a capability from the so called
Cap_map before each reference to it is destroyed, so don't do this in
Cap_session_component::free, but only reference-decrement within there,
the actual removal can only be done in Cap_map::remove. Because core also
has to invalidate a capability to be removed in all protection-domains
we have to implement a core specific Cap_map::remove method
* When a capability gets inserted into the Cap_map, and we detect an old
invalid entry with the dame id in the tree, don't just overmap that
invalid entry (as there exist remaining references to it), but just remove
it from the tree and allocate an new entry.
* Use the Cap_session_component interface to free a Pager_object when it
gets dissolved, as its also used for allocation
2012-08-29 15:52:18 +02:00
|
|
|
: Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE]),
|
|
|
|
_badge(0) { }
|
2011-12-22 16:19:25 +01:00
|
|
|
|