2011-12-22 15:19:25 +00:00
|
|
|
/*
|
|
|
|
* \brief Pager framework
|
|
|
|
* \author Norman Feske
|
|
|
|
* \author Sebastian Sumpf
|
2012-08-01 14:16:51 +00:00
|
|
|
* \author Alexander Boettcher
|
2011-12-22 15:19:25 +00:00
|
|
|
* \date 2010-01-25
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2015-01-05 21:09:51 +00:00
|
|
|
* Copyright (C) 2010-2015 Genode Labs GmbH
|
2011-12-22 15:19:25 +00:00
|
|
|
*
|
|
|
|
* 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 */
|
2014-09-05 15:00:31 +00:00
|
|
|
#include <util/construct_at.h>
|
|
|
|
#include <rm_session/rm_session.h>
|
|
|
|
|
2016-03-11 16:32:43 +00:00
|
|
|
/* base-internal includes */
|
|
|
|
#include <base/internal/native_thread.h>
|
|
|
|
|
2016-01-19 19:24:22 +00:00
|
|
|
/* core-local includes */
|
2015-06-19 12:58:18 +00:00
|
|
|
#include <pager.h>
|
2016-11-04 12:01:09 +00:00
|
|
|
#include <platform.h>
|
2016-05-19 18:33:36 +00:00
|
|
|
#include <platform_thread.h>
|
2016-01-19 19:24:22 +00:00
|
|
|
#include <imprint_badge.h>
|
2016-11-30 18:36:32 +00:00
|
|
|
#include <cpu_thread_component.h>
|
|
|
|
#include <core_env.h>
|
2015-06-19 12:58:18 +00:00
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
/* NOVA includes */
|
|
|
|
#include <nova/syscalls.h>
|
2014-09-05 15:00:31 +00:00
|
|
|
#include <nova_util.h> /* map_local */
|
2016-06-15 13:04:54 +00:00
|
|
|
#include <nova/capability_space.h>
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2015-06-09 17:33:53 +00:00
|
|
|
static bool verbose_oom = false;
|
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
using namespace Genode;
|
|
|
|
using namespace Nova;
|
|
|
|
|
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
static Nova::Hip * kernel_hip()
|
2012-08-23 09:02:31 +00:00
|
|
|
{
|
2014-09-05 15:00:31 +00:00
|
|
|
/**
|
|
|
|
* Initial value of esp register, saved by the crt0 startup code.
|
|
|
|
* This value contains the address of the hypervisor information page.
|
|
|
|
*/
|
|
|
|
extern addr_t __initial_sp;
|
|
|
|
return reinterpret_cast<Hip *>(__initial_sp);
|
|
|
|
}
|
2012-08-23 09:02:31 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* pager activation threads storage and handling - one thread per CPU */
|
2016-11-04 12:01:09 +00:00
|
|
|
enum { PAGER_CPUS = Platform::MAX_SUPPORTED_CPUS, PAGER_STACK_SIZE = 2*4096 };
|
2012-08-23 09:02:31 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
static char pager_activation_mem[sizeof (Pager_activation<PAGER_STACK_SIZE>) * PAGER_CPUS];
|
|
|
|
static Pager_activation_base * pager_threads[PAGER_CPUS];
|
2012-08-23 09:02:31 +00:00
|
|
|
|
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
static unsigned which_cpu(Pager_activation_base * pager)
|
|
|
|
{
|
|
|
|
Pager_activation_base * start = reinterpret_cast<Pager_activation_base *>(&pager_activation_mem);
|
|
|
|
Pager_activation_base * end = start + PAGER_CPUS;
|
2012-08-23 09:02:31 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
if (start <= pager && pager < end) {
|
|
|
|
/* pager of one of the non boot CPUs */
|
|
|
|
unsigned cpu_id = pager - start;
|
|
|
|
return cpu_id;
|
|
|
|
}
|
2012-08-23 09:02:31 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* pager of boot CPU */
|
2016-11-04 12:01:09 +00:00
|
|
|
return 0;
|
2012-08-23 09:02:31 +00:00
|
|
|
}
|
|
|
|
|
2013-01-11 22:10:21 +00:00
|
|
|
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
/**
|
|
|
|
* Utility for the formatted output of page-fault information
|
|
|
|
*/
|
|
|
|
struct Page_fault_info
|
|
|
|
{
|
|
|
|
char const * const pd;
|
|
|
|
char const * const thread;
|
|
|
|
unsigned const cpu;
|
2016-11-10 10:46:30 +00:00
|
|
|
addr_t const ip, addr, sp;
|
|
|
|
uint8_t const pf_type;
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
|
|
|
|
Page_fault_info(char const *pd, char const *thread, unsigned cpu,
|
2016-11-10 10:46:30 +00:00
|
|
|
addr_t ip, addr_t addr, addr_t sp, unsigned type)
|
|
|
|
: pd(pd), thread(thread), cpu(cpu), ip(ip), addr(addr),
|
|
|
|
sp(sp), pf_type(type) { }
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
|
|
|
|
void print(Genode::Output &out) const
|
|
|
|
{
|
|
|
|
Genode::print(out, "pd='", pd, "' "
|
|
|
|
"thread='", thread, "' "
|
|
|
|
"cpu=", cpu, " "
|
|
|
|
"ip=", Hex(ip), " "
|
2016-11-10 10:46:30 +00:00
|
|
|
"address=", Hex(addr), " "
|
|
|
|
"stack pointer=", Hex(sp), " "
|
|
|
|
"qualifiers=", Hex(pf_type), " ",
|
|
|
|
pf_type & Ipc_pager::ERR_I ? "I" : "i",
|
|
|
|
pf_type & Ipc_pager::ERR_R ? "R" : "r",
|
|
|
|
pf_type & Ipc_pager::ERR_U ? "U" : "u",
|
|
|
|
pf_type & Ipc_pager::ERR_W ? "W" : "w",
|
|
|
|
pf_type & Ipc_pager::ERR_P ? "P" : "p");
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
void Pager_object::_page_fault_handler(addr_t pager_obj)
|
2011-12-22 15:19:25 +00:00
|
|
|
{
|
2016-05-04 10:27:17 +00:00
|
|
|
Thread * myself = Thread::myself();
|
2014-09-05 15:00:31 +00:00
|
|
|
Pager_object * obj = reinterpret_cast<Pager_object *>(pager_obj);
|
|
|
|
Utcb * utcb = reinterpret_cast<Utcb *>(myself->utcb());
|
2016-11-10 10:46:30 +00:00
|
|
|
|
|
|
|
Ipc_pager ipc_pager(reinterpret_cast<Nova::Utcb *>(utcb), obj->pd_sel(),
|
|
|
|
platform_specific()->core_pd_sel());
|
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
Pager_activation_base * pager_thread = static_cast<Pager_activation_base *>(myself);
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2016-11-30 18:36:32 +00:00
|
|
|
/* potential request to ask for EC cap or signal SM cap */
|
|
|
|
if (utcb->msg_words() == 1)
|
|
|
|
_invoke_handler(pager_obj);
|
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* lookup fault address and decide what to do */
|
2016-11-10 10:46:30 +00:00
|
|
|
int error = obj->pager(ipc_pager);
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* don't open receive window for pager threads */
|
|
|
|
if (utcb->crd_rcv.value())
|
|
|
|
nova_die();
|
2013-02-19 10:14:21 +00:00
|
|
|
|
2016-11-10 10:46:30 +00:00
|
|
|
if (!error && ipc_pager.syscall_result() != Nova::NOVA_OK) {
|
|
|
|
/* something went wrong - by default don't answer the page fault */
|
|
|
|
error = 4;
|
|
|
|
|
|
|
|
/* dst pd has not enough kernel quota ? - try to recover */
|
|
|
|
if (ipc_pager.syscall_result() == Nova::NOVA_PD_OOM) {
|
|
|
|
uint8_t res = obj->handle_oom();
|
|
|
|
if (res == Nova::NOVA_PD_OOM)
|
|
|
|
/* block until revoke is due */
|
|
|
|
ipc_pager.reply_and_wait_for_fault(obj->sel_sm_block_oom());
|
|
|
|
else if (res == Nova::NOVA_OK)
|
|
|
|
/* succeeded to recover - continue normally */
|
|
|
|
error = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* good case - found a valid region which is mappable */
|
2016-11-10 10:46:30 +00:00
|
|
|
if (!error)
|
2014-09-05 15:00:31 +00:00
|
|
|
ipc_pager.reply_and_wait_for_fault();
|
2013-01-31 10:59:38 +00:00
|
|
|
|
2016-11-10 10:46:30 +00:00
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
obj->_state_lock.lock();
|
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
obj->_state.thread.ip = ipc_pager.fault_ip();
|
|
|
|
obj->_state.thread.sp = 0;
|
|
|
|
obj->_state.thread.trapno = PT_SEL_PAGE_FAULT;
|
2013-01-31 10:59:38 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
obj->_state.block();
|
2013-02-27 10:32:49 +00:00
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
obj->_state_lock.unlock();
|
|
|
|
|
2016-05-19 18:33:36 +00:00
|
|
|
const char * client_thread = obj->client_thread();
|
|
|
|
const char * client_pd = obj->client_pd();
|
|
|
|
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
Page_fault_info const fault_info(client_pd, client_thread,
|
|
|
|
which_cpu(pager_thread),
|
2016-11-10 10:46:30 +00:00
|
|
|
ipc_pager.fault_ip(),
|
|
|
|
ipc_pager.fault_addr(),
|
|
|
|
ipc_pager.sp(),
|
|
|
|
ipc_pager.fault_type());
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* region manager fault - to be handled */
|
2016-11-10 10:46:30 +00:00
|
|
|
log("page fault, ", fault_info, " reason=", error);
|
2014-09-05 15:00:31 +00:00
|
|
|
|
2016-11-10 10:46:30 +00:00
|
|
|
/* block the faulting thread until region manager is done */
|
|
|
|
ipc_pager.reply_and_wait_for_fault(obj->sel_sm_block_pause());
|
2011-12-22 15:19:25 +00:00
|
|
|
}
|
|
|
|
|
2013-01-11 22:10:21 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
void Pager_object::exception(uint8_t exit_id)
|
2012-08-23 09:02:31 +00:00
|
|
|
{
|
2016-05-04 10:27:17 +00:00
|
|
|
Thread *myself = Thread::myself();
|
2014-09-05 15:00:31 +00:00
|
|
|
Utcb * utcb = reinterpret_cast<Utcb *>(myself->utcb());
|
|
|
|
Pager_activation_base * pager_thread = static_cast<Pager_activation_base *>(myself);
|
|
|
|
|
|
|
|
if (exit_id > PT_SEL_PARENT || !pager_thread)
|
|
|
|
nova_die();
|
|
|
|
|
2013-01-16 15:07:04 +00:00
|
|
|
addr_t fault_ip = utcb->ip;
|
2013-11-04 10:05:10 +00:00
|
|
|
uint8_t res = 0xFF;
|
2015-01-06 13:20:16 +00:00
|
|
|
addr_t mtd = 0;
|
2012-08-23 09:02:31 +00:00
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
_state_lock.lock();
|
2014-09-05 15:00:31 +00:00
|
|
|
|
|
|
|
/* remember exception type for cpu_session()->state() calls */
|
|
|
|
_state.thread.trapno = exit_id;
|
|
|
|
|
|
|
|
if (_exception_sigh.valid()) {
|
|
|
|
_state.submit_signal();
|
2016-05-17 14:13:56 +00:00
|
|
|
res = _unsynchronized_client_recall(true);
|
2014-09-05 15:00:31 +00:00
|
|
|
}
|
2013-09-26 12:31:56 +00:00
|
|
|
|
|
|
|
if (res != NOVA_OK) {
|
2014-09-05 15:00:31 +00:00
|
|
|
/* nobody handles this exception - so thread will be stopped finally */
|
|
|
|
_state.mark_dead();
|
2013-02-19 10:14:21 +00:00
|
|
|
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
warning("unresolvable exception ", exit_id, ", "
|
|
|
|
"pd '", client_pd(), "', "
|
|
|
|
"thread '", client_thread(), "', "
|
|
|
|
"cpu ", which_cpu(pager_thread), ", "
|
|
|
|
"ip=", Hex(fault_ip), " ",
|
|
|
|
res == 0xFF ? "no signal handler"
|
|
|
|
: (res == NOVA_OK ? "" : "recall failed"));
|
2013-01-16 15:07:04 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
Nova::revoke(Obj_crd(exc_pt_sel_client(), NUM_INITIAL_PT_LOG2));
|
2015-01-06 13:20:16 +00:00
|
|
|
|
|
|
|
enum { TRAP_BREAKPOINT = 3 };
|
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
if (exit_id == TRAP_BREAKPOINT) {
|
2015-01-06 13:20:16 +00:00
|
|
|
utcb->ip = fault_ip - 1;
|
|
|
|
mtd = Mtd::EIP;
|
|
|
|
}
|
2012-08-23 09:02:31 +00:00
|
|
|
}
|
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
_state_lock.unlock();
|
|
|
|
|
2012-08-23 09:02:31 +00:00
|
|
|
utcb->set_msg_word(0);
|
2015-01-06 13:20:16 +00:00
|
|
|
utcb->mtd = mtd;
|
2012-08-23 09:02:31 +00:00
|
|
|
|
|
|
|
reply(myself->stack_top());
|
|
|
|
}
|
|
|
|
|
2013-01-11 22:10:21 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
void Pager_object::_recall_handler(addr_t pager_obj)
|
2012-08-24 08:25:24 +00:00
|
|
|
{
|
2016-05-04 10:27:17 +00:00
|
|
|
Thread * myself = Thread::myself();
|
2014-09-05 15:00:31 +00:00
|
|
|
Pager_object * obj = reinterpret_cast<Pager_object *>(pager_obj);
|
|
|
|
Utcb * utcb = reinterpret_cast<Utcb *>(myself->utcb());
|
2012-08-24 08:25:24 +00:00
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
obj->_state_lock.lock();
|
2012-08-24 08:25:24 +00:00
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
if (obj->_state.modified) {
|
|
|
|
obj->_copy_state_to_utcb(utcb);
|
|
|
|
obj->_state.modified = false;
|
|
|
|
} else
|
|
|
|
utcb->mtd = 0;
|
2012-08-24 08:25:24 +00:00
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
/* switch on/off single step */
|
|
|
|
bool singlestep_state = obj->_state.thread.eflags & 0x100UL;
|
|
|
|
if (obj->_state.singlestep() && !singlestep_state) {
|
|
|
|
utcb->flags |= 0x100UL;
|
|
|
|
utcb->mtd |= Mtd::EFL;
|
|
|
|
} else if (!obj->_state.singlestep() && singlestep_state) {
|
|
|
|
utcb->flags &= ~0x100UL;
|
|
|
|
utcb->mtd |= Mtd::EFL;
|
|
|
|
}
|
2012-08-24 08:25:24 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* deliver signal if it was requested */
|
|
|
|
if (obj->_state.to_submit())
|
|
|
|
obj->submit_exception_signal();
|
2012-08-24 08:25:24 +00:00
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
/* block until cpu_session()->resume() respectively wake_up() call */
|
2012-08-24 08:25:24 +00:00
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
unsigned long sm = obj->_state.blocked() ? obj->sel_sm_block_pause() : 0;
|
|
|
|
|
|
|
|
obj->_state_lock.unlock();
|
2013-09-26 13:16:01 +00:00
|
|
|
|
2012-08-24 08:25:24 +00:00
|
|
|
utcb->set_msg_word(0);
|
2016-05-17 14:13:56 +00:00
|
|
|
reply(myself->stack_top(), sm);
|
2012-08-24 08:25:24 +00:00
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2013-01-11 22:10:21 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
void Pager_object::_startup_handler(addr_t pager_obj)
|
2011-12-22 15:19:25 +00:00
|
|
|
{
|
2016-05-04 10:27:17 +00:00
|
|
|
Thread *myself = Thread::myself();
|
2014-09-05 15:00:31 +00:00
|
|
|
Pager_object * obj = reinterpret_cast<Pager_object *>(pager_obj);
|
|
|
|
Utcb * utcb = reinterpret_cast<Utcb *>(myself->utcb());
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2012-08-24 08:25:24 +00:00
|
|
|
utcb->ip = obj->_initial_eip;
|
|
|
|
utcb->sp = obj->_initial_esp;
|
2012-08-23 09:02:31 +00:00
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
utcb->mtd = Mtd::EIP | Mtd::ESP;
|
2016-05-17 14:13:56 +00:00
|
|
|
|
|
|
|
if (obj->_state.singlestep()) {
|
|
|
|
utcb->flags = 0x100UL;
|
|
|
|
utcb->mtd |= Mtd::EFL;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj->_state.unblock();
|
|
|
|
|
2012-06-26 11:43:30 +00:00
|
|
|
utcb->set_msg_word(0);
|
2012-08-23 09:02:31 +00:00
|
|
|
|
|
|
|
reply(myself->stack_top());
|
2011-12-22 15:19:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
void Pager_object::_invoke_handler(addr_t pager_obj)
|
2011-12-22 15:19:25 +00:00
|
|
|
{
|
2016-05-04 10:27:17 +00:00
|
|
|
Thread *myself = Thread::myself();
|
2014-09-05 15:00:31 +00:00
|
|
|
Pager_object * obj = reinterpret_cast<Pager_object *>(pager_obj);
|
|
|
|
Utcb * utcb = reinterpret_cast<Utcb *>(myself->utcb());
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* receive window must be closed - otherwise implementation bug */
|
|
|
|
if (utcb->crd_rcv.value())
|
|
|
|
nova_die();
|
2013-11-14 09:35:44 +00:00
|
|
|
|
2016-11-30 18:36:32 +00:00
|
|
|
/* if protocol is violated ignore request */
|
|
|
|
if (utcb->msg_words() != 1) {
|
|
|
|
utcb->mtd = 0;
|
|
|
|
utcb->set_msg_word(0);
|
|
|
|
reply(myself->stack_top());
|
|
|
|
}
|
|
|
|
|
|
|
|
addr_t const event = utcb->msg[0];
|
2013-09-25 09:53:49 +00:00
|
|
|
|
2016-11-24 20:57:33 +00:00
|
|
|
/* check for translated pager portals - required for vCPU in remote PDs */
|
|
|
|
if (utcb->msg_items() == 1 && utcb->msg_words() == 1 && event == 0xaffe) {
|
|
|
|
|
|
|
|
Nova::Utcb::Item const * const item = utcb->get_item(0);
|
|
|
|
Nova::Crd const cap(item->crd);
|
|
|
|
|
|
|
|
/* valid item which got translated ? */
|
|
|
|
if (!cap.is_null() && !item->is_del()) {
|
2016-11-30 18:36:32 +00:00
|
|
|
Rpc_entrypoint *e = core_env()->entrypoint();
|
|
|
|
e->apply(cap.base(),
|
|
|
|
[&] (Cpu_thread_component *source) {
|
|
|
|
if (!source)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Platform_thread &p = source->platform_thread();
|
|
|
|
addr_t const sel_exc_base = p.remote_vcpu();
|
|
|
|
if (sel_exc_base == Native_thread::INVALID_INDEX)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* delegate VM-exit portals */
|
|
|
|
map_vcpu_portals(*p.pager(), sel_exc_base, sel_exc_base,
|
|
|
|
utcb, obj->pd_sel());
|
|
|
|
|
|
|
|
/* delegate portal to contact pager */
|
|
|
|
map_pagefault_portal(*obj, p.pager()->exc_pt_sel_client(),
|
|
|
|
sel_exc_base, obj->pd_sel(), utcb);
|
|
|
|
});
|
2014-09-05 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
utcb->mtd = 0;
|
|
|
|
utcb->set_msg_word(0);
|
|
|
|
reply(myself->stack_top());
|
|
|
|
}
|
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
utcb->mtd = 0;
|
2012-06-26 11:43:30 +00:00
|
|
|
utcb->set_msg_word(0);
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2013-09-26 12:31:56 +00:00
|
|
|
/* native ec cap requested */
|
2013-09-25 09:53:49 +00:00
|
|
|
if (event == ~0UL) {
|
|
|
|
/**
|
|
|
|
* Return native EC cap with specific rights mask set.
|
|
|
|
* If the cap is mapped the kernel will demote the
|
|
|
|
* rights of the EC as specified by the rights mask.
|
|
|
|
*
|
|
|
|
* The cap is supposed to be returned to clients,
|
|
|
|
* which they have to use as argument to identify
|
|
|
|
* the thread to which they want attach portals.
|
|
|
|
*
|
|
|
|
* The demotion by the kernel during the map operation
|
|
|
|
* takes care that the EC cap itself contains
|
|
|
|
* no usable rights for the clients.
|
|
|
|
*/
|
|
|
|
bool res = utcb->append_item(Obj_crd(obj->_state.sel_client_ec, 0,
|
|
|
|
Obj_crd::RIGHT_EC_RECALL), 0);
|
|
|
|
(void)res;
|
|
|
|
}
|
|
|
|
|
2013-09-26 12:31:56 +00:00
|
|
|
/* semaphore for signaling thread is requested, reuse PT_SEL_STARTUP. */
|
|
|
|
if (event == ~0UL - 1) {
|
|
|
|
/* create semaphore only once */
|
|
|
|
if (!obj->_state.has_signal_sm()) {
|
|
|
|
|
|
|
|
revoke(Obj_crd(obj->exc_pt_sel_client() + PT_SEL_STARTUP, 0));
|
|
|
|
|
|
|
|
bool res = Nova::create_sm(obj->exc_pt_sel_client() + PT_SEL_STARTUP,
|
2016-11-10 10:46:30 +00:00
|
|
|
platform_specific()->core_pd_sel(), 0);
|
2013-09-26 12:31:56 +00:00
|
|
|
if (res != Nova::NOVA_OK)
|
|
|
|
reply(myself->stack_top());
|
|
|
|
|
|
|
|
obj->_state.mark_signal_sm();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool res = utcb->append_item(Obj_crd(obj->exc_pt_sel_client() +
|
|
|
|
PT_SEL_STARTUP, 0), 0);
|
|
|
|
(void)res;
|
|
|
|
}
|
|
|
|
|
2012-08-23 09:02:31 +00:00
|
|
|
reply(myself->stack_top());
|
2011-12-22 15:19:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-26 13:16:01 +00:00
|
|
|
void Pager_object::wake_up()
|
|
|
|
{
|
2016-05-17 14:13:56 +00:00
|
|
|
Lock::Guard _state_lock_guard(_state_lock);
|
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
if (!_state.blocked())
|
|
|
|
return;
|
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
_state.thread.exception = false;
|
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
_state.unblock();
|
2013-09-26 13:16:01 +00:00
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
uint8_t res = sm_ctrl(sel_sm_block_pause(), SEMAPHORE_UP);
|
2014-09-05 15:00:31 +00:00
|
|
|
if (res != NOVA_OK)
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
warning("canceling blocked client failed (thread sm)");
|
2013-09-26 13:16:01 +00:00
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2012-08-22 10:10:04 +00:00
|
|
|
|
2013-01-11 22:10:21 +00:00
|
|
|
void Pager_object::client_cancel_blocking()
|
|
|
|
{
|
2013-09-23 07:07:33 +00:00
|
|
|
uint8_t res = sm_ctrl(exc_pt_sel_client() + SM_SEL_EC, SEMAPHORE_UP);
|
2012-08-24 08:25:24 +00:00
|
|
|
if (res != NOVA_OK)
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
warning("canceling blocked client failed (thread sm)");
|
2013-09-26 12:31:56 +00:00
|
|
|
|
|
|
|
if (!_state.has_signal_sm())
|
|
|
|
return;
|
|
|
|
|
|
|
|
res = sm_ctrl(exc_pt_sel_client() + PT_SEL_STARTUP, SEMAPHORE_UP);
|
|
|
|
if (res != NOVA_OK)
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
warning("canceling blocked client failed (signal sm)");
|
2012-08-24 08:25:24 +00:00
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2012-08-22 10:10:04 +00:00
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
uint8_t Pager_object::client_recall(bool get_state_and_block)
|
|
|
|
{
|
|
|
|
Lock::Guard _state_lock_guard(_state_lock);
|
|
|
|
return _unsynchronized_client_recall(get_state_and_block);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t Pager_object::_unsynchronized_client_recall(bool get_state_and_block)
|
2013-01-11 22:10:21 +00:00
|
|
|
{
|
2016-05-17 14:13:56 +00:00
|
|
|
enum { STATE_REQUESTED = 1 };
|
|
|
|
|
|
|
|
uint8_t res = ec_ctrl(EC_RECALL, _state.sel_client_ec,
|
|
|
|
get_state_and_block ? STATE_REQUESTED : ~0UL);
|
|
|
|
|
|
|
|
if (res != NOVA_OK)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
if (get_state_and_block) {
|
|
|
|
Utcb *utcb = reinterpret_cast<Utcb *>(Thread::myself()->utcb());
|
|
|
|
_copy_state_from_utcb(utcb);
|
|
|
|
_state.block();
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
2012-08-22 10:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-04 08:49:01 +00:00
|
|
|
void Pager_object::cleanup_call()
|
|
|
|
{
|
2014-09-05 15:00:31 +00:00
|
|
|
_state.mark_dissolved();
|
|
|
|
|
2016-04-20 19:12:57 +00:00
|
|
|
/* revoke ec and sc cap of client before the sm cap */
|
|
|
|
if (_state.sel_client_ec != Native_thread::INVALID_INDEX)
|
|
|
|
revoke(Obj_crd(_state.sel_client_ec, 2));
|
|
|
|
|
2013-09-23 07:07:33 +00:00
|
|
|
/* revoke all portals handling the client. */
|
|
|
|
revoke(Obj_crd(exc_pt_sel_client(), NUM_INITIAL_PT_LOG2));
|
2012-12-04 08:49:01 +00:00
|
|
|
|
2016-05-04 10:27:17 +00:00
|
|
|
Utcb *utcb = reinterpret_cast<Utcb *>(Thread::myself()->utcb());
|
2012-12-04 08:49:01 +00:00
|
|
|
utcb->set_msg_word(0);
|
2014-09-05 15:00:31 +00:00
|
|
|
utcb->mtd = 0;
|
|
|
|
if (uint8_t res = call(sel_pt_cleanup()))
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
error(utcb, " - cleanup call to pager failed res=", res);
|
2012-12-04 08:49:01 +00:00
|
|
|
}
|
|
|
|
|
2013-09-26 12:31:56 +00:00
|
|
|
|
2016-09-05 09:24:51 +00:00
|
|
|
void Pager_object::print(Output &out) const
|
|
|
|
{
|
|
|
|
Platform_thread * faulter = reinterpret_cast<Platform_thread *>(_badge);
|
|
|
|
Genode::print(out, "pager_object: pd='",
|
|
|
|
faulter ? faulter->pd_name() : "unknown", "' thread='",
|
|
|
|
faulter ? faulter->name() : "unknown", "'");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-22 14:26:43 +00:00
|
|
|
static uint8_t create_portal(addr_t pt, addr_t pd, addr_t ec, Mtd mtd,
|
2015-06-09 17:33:53 +00:00
|
|
|
addr_t eip, Pager_object * oom_handler)
|
2013-02-22 14:26:43 +00:00
|
|
|
{
|
2016-11-30 18:36:32 +00:00
|
|
|
uint8_t res = syscall_retry(*oom_handler,
|
|
|
|
[&]() { return create_pt(pt, pd, ec, mtd, eip); });
|
2013-02-22 14:26:43 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
if (res != NOVA_OK)
|
|
|
|
return res;
|
|
|
|
|
2016-11-30 18:36:32 +00:00
|
|
|
addr_t const badge_localname = reinterpret_cast<addr_t>(oom_handler);
|
|
|
|
|
2015-06-09 17:33:53 +00:00
|
|
|
res = pt_ctrl(pt, badge_localname);
|
2013-02-22 14:26:43 +00:00
|
|
|
if (res == NOVA_OK)
|
|
|
|
revoke(Obj_crd(pt, 0, Obj_crd::RIGHT_PT_CTRL));
|
2014-09-05 15:00:31 +00:00
|
|
|
else
|
|
|
|
revoke(Obj_crd(pt, 0));
|
2013-02-22 14:26:43 +00:00
|
|
|
|
2013-09-26 12:31:56 +00:00
|
|
|
return res;
|
2013-02-22 14:26:43 +00:00
|
|
|
}
|
2012-12-04 08:49:01 +00:00
|
|
|
|
2013-09-26 12:31:56 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/************************
|
|
|
|
** Exception handlers **
|
|
|
|
************************/
|
|
|
|
|
|
|
|
template <uint8_t EV>
|
|
|
|
void Exception_handlers::register_handler(Pager_object *obj, Mtd mtd,
|
|
|
|
void (* __attribute__((regparm(1))) func)(addr_t))
|
|
|
|
{
|
2016-11-04 12:01:09 +00:00
|
|
|
unsigned const genode_cpu_id = obj->location().xpos();
|
|
|
|
unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(genode_cpu_id);
|
2016-09-23 15:47:36 +00:00
|
|
|
|
2016-11-04 12:01:09 +00:00
|
|
|
if (!kernel_hip()->is_cpu_enabled(kernel_cpu_id) ||
|
|
|
|
!pager_threads[genode_cpu_id]) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
warning("invalid CPU parameter used in pager object");
|
2016-04-15 13:19:22 +00:00
|
|
|
throw Region_map::Invalid_thread();
|
2015-10-06 11:49:49 +00:00
|
|
|
}
|
2014-09-05 15:00:31 +00:00
|
|
|
|
2016-11-04 12:01:09 +00:00
|
|
|
addr_t const ec_sel = pager_threads[genode_cpu_id]->native_thread().ec_sel;
|
2014-09-05 15:00:31 +00:00
|
|
|
|
|
|
|
/* compiler generates instance of exception entry if not specified */
|
|
|
|
addr_t entry = func ? (addr_t)func : (addr_t)(&_handler<EV>);
|
|
|
|
uint8_t res = create_portal(obj->exc_pt_sel_client() + EV,
|
2016-11-10 10:46:30 +00:00
|
|
|
platform_specific()->core_pd_sel(), ec_sel, mtd, entry, obj);
|
2014-09-05 15:00:31 +00:00
|
|
|
if (res != Nova::NOVA_OK)
|
2016-04-15 13:19:22 +00:00
|
|
|
throw Region_map::Invalid_thread();
|
2014-09-05 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <uint8_t EV>
|
|
|
|
void Exception_handlers::_handler(addr_t obj)
|
|
|
|
{
|
|
|
|
Pager_object * pager_obj = reinterpret_cast<Pager_object *>(obj);
|
|
|
|
pager_obj->exception(EV);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Exception_handlers::Exception_handlers(Pager_object *obj)
|
|
|
|
{
|
|
|
|
register_handler<0>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<1>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<2>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<3>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<4>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<5>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<6>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<7>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<8>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<9>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<10>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<11>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<12>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<13>(obj, Mtd(Mtd::EIP));
|
|
|
|
|
|
|
|
register_handler<15>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<16>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<17>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<18>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<19>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<20>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<21>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<22>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<23>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<24>(obj, Mtd(Mtd::EIP));
|
|
|
|
register_handler<25>(obj, Mtd(Mtd::EIP));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************
|
|
|
|
** Pager object **
|
|
|
|
******************/
|
|
|
|
|
|
|
|
|
2016-04-20 19:12:57 +00:00
|
|
|
Pager_object::Pager_object(Cpu_session_capability cpu_session_cap,
|
|
|
|
Thread_capability thread_cap, unsigned long badge,
|
2016-09-05 09:24:51 +00:00
|
|
|
Affinity::Location location, Session_label const &,
|
|
|
|
Cpu_session::Name const &)
|
2013-11-14 09:35:44 +00:00
|
|
|
:
|
2014-09-05 15:00:31 +00:00
|
|
|
_badge(badge),
|
|
|
|
_selectors(cap_map()->insert(2)),
|
|
|
|
_client_exc_pt_sel(cap_map()->insert(NUM_INITIAL_PT_LOG2)),
|
2016-04-20 19:12:57 +00:00
|
|
|
_cpu_session_cap(cpu_session_cap), _thread_cap(thread_cap),
|
2016-09-23 15:47:36 +00:00
|
|
|
_location(location),
|
2016-11-24 20:57:33 +00:00
|
|
|
_exceptions(this),
|
2016-11-30 18:36:32 +00:00
|
|
|
_pd_target(Native_thread::INVALID_INDEX)
|
2011-12-22 15:19:25 +00:00
|
|
|
{
|
2012-08-23 09:02:31 +00:00
|
|
|
uint8_t res;
|
|
|
|
|
2016-11-10 10:46:30 +00:00
|
|
|
addr_t const pd_sel = platform_specific()->core_pd_sel();
|
2013-09-26 13:16:01 +00:00
|
|
|
_state._status = 0;
|
2016-05-17 14:13:56 +00:00
|
|
|
_state.modified = false;
|
2012-08-23 09:02:31 +00:00
|
|
|
_state.sel_client_ec = Native_thread::INVALID_INDEX;
|
2016-05-17 14:13:56 +00:00
|
|
|
_state.block();
|
2012-08-23 09:02:31 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
if (Native_thread::INVALID_INDEX == _selectors ||
|
|
|
|
Native_thread::INVALID_INDEX == _client_exc_pt_sel)
|
2016-04-15 13:19:22 +00:00
|
|
|
throw Region_map::Invalid_thread();
|
2013-09-23 07:07:33 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* ypos information not supported by now */
|
|
|
|
if (location.ypos()) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
warning("unsupported location ", location.xpos(), "x", location.ypos());
|
2016-04-15 13:19:22 +00:00
|
|
|
throw Region_map::Invalid_thread();
|
2012-08-23 09:02:31 +00:00
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* place Pager_object on specified CPU by selecting proper pager thread */
|
2016-11-04 12:01:09 +00:00
|
|
|
unsigned const genode_cpu_id = location.xpos();
|
|
|
|
unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(genode_cpu_id);
|
|
|
|
if (!kernel_hip()->is_cpu_enabled(kernel_cpu_id) ||
|
|
|
|
!pager_threads[genode_cpu_id]) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
warning("invalid CPU parameter used in pager object");
|
2016-04-15 13:19:22 +00:00
|
|
|
throw Region_map::Invalid_thread();
|
2015-10-06 11:49:49 +00:00
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2016-11-04 12:01:09 +00:00
|
|
|
addr_t ec_sel = pager_threads[genode_cpu_id]->native_thread().ec_sel;
|
2012-08-23 09:02:31 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* create portal for page-fault handler - 14 */
|
|
|
|
_exceptions.register_handler<14>(this, Mtd::QUAL | Mtd::EIP,
|
|
|
|
_page_fault_handler);
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* create portal for startup handler - 26 */
|
|
|
|
Mtd const mtd_startup(Mtd::ESP | Mtd::EIP);
|
|
|
|
_exceptions.register_handler<PT_SEL_STARTUP>(this, mtd_startup,
|
|
|
|
_startup_handler);
|
|
|
|
|
|
|
|
/* create portal for recall handler - 31 */
|
|
|
|
Mtd const mtd_recall(Mtd::ESP | Mtd::EIP | Mtd::ACDB | Mtd::EFL |
|
|
|
|
Mtd::EBSD | Mtd::FSGS);
|
|
|
|
_exceptions.register_handler<PT_SEL_RECALL>(this, mtd_recall,
|
|
|
|
_recall_handler);
|
2012-08-24 08:25:24 +00:00
|
|
|
|
2013-09-23 07:07:33 +00:00
|
|
|
/*
|
|
|
|
* Create semaphore required for Genode locking. It can be later on
|
|
|
|
* requested by the thread the same way as all exception portals.
|
|
|
|
*/
|
|
|
|
res = Nova::create_sm(exc_pt_sel_client() + SM_SEL_EC, pd_sel, 0);
|
|
|
|
if (res != Nova::NOVA_OK) {
|
2016-04-15 13:19:22 +00:00
|
|
|
throw Region_map::Invalid_thread();
|
2013-09-23 07:07:33 +00:00
|
|
|
}
|
|
|
|
|
2013-01-11 22:10:21 +00:00
|
|
|
/* create portal for final cleanup call used during destruction */
|
2014-09-05 15:00:31 +00:00
|
|
|
res = create_portal(sel_pt_cleanup(), pd_sel, ec_sel, Mtd(0),
|
2015-06-09 17:33:53 +00:00
|
|
|
reinterpret_cast<addr_t>(_invoke_handler), this);
|
2014-09-05 15:00:31 +00:00
|
|
|
if (res != Nova::NOVA_OK) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
error("could not create pager cleanup portal, error=", res);
|
2016-04-15 13:19:22 +00:00
|
|
|
throw Region_map::Invalid_thread();
|
2014-09-05 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
/* semaphore used to block paged thread during recall */
|
|
|
|
res = Nova::create_sm(sel_sm_block_pause(), pd_sel, 0);
|
2014-09-05 15:00:31 +00:00
|
|
|
if (res != Nova::NOVA_OK) {
|
2016-04-15 13:19:22 +00:00
|
|
|
throw Region_map::Invalid_thread();
|
2012-08-24 08:25:24 +00:00
|
|
|
}
|
|
|
|
|
2016-05-17 14:13:56 +00:00
|
|
|
/* semaphore used to block paged thread during OOM memory revoke */
|
|
|
|
res = Nova::create_sm(sel_sm_block_oom(), pd_sel, 0);
|
2012-08-24 08:25:24 +00:00
|
|
|
if (res != Nova::NOVA_OK) {
|
2016-04-15 13:19:22 +00:00
|
|
|
throw Region_map::Invalid_thread();
|
2012-08-24 08:25:24 +00:00
|
|
|
}
|
2012-06-19 13:54:41 +00:00
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2013-01-11 22:10:21 +00:00
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
Pager_object::~Pager_object()
|
|
|
|
{
|
2014-09-05 15:00:31 +00:00
|
|
|
/* sanity check that object got dissolved already - otherwise bug */
|
|
|
|
if (!_state.dissolved())
|
|
|
|
nova_die();
|
2013-01-16 15:07:04 +00:00
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/* revoke portal used for the cleanup call and sm cap for blocking state */
|
|
|
|
revoke(Obj_crd(_selectors, 2));
|
|
|
|
cap_map()->remove(_selectors, 2, false);
|
2013-09-11 08:45:23 +00:00
|
|
|
cap_map()->remove(exc_pt_sel_client(), NUM_INITIAL_PT_LOG2, false);
|
2011-12-22 15:19:25 +00:00
|
|
|
}
|
|
|
|
|
2016-11-24 20:57:33 +00:00
|
|
|
|
2015-06-09 17:33:53 +00:00
|
|
|
uint8_t Pager_object::handle_oom(addr_t transfer_from,
|
|
|
|
char const * src_pd, char const * src_thread,
|
|
|
|
enum Pager_object::Policy policy)
|
|
|
|
{
|
2016-11-28 09:54:06 +00:00
|
|
|
return handle_oom(transfer_from, pd_sel(), src_pd, src_thread, policy,
|
|
|
|
sel_sm_block_oom(), client_pd(), client_thread());
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t Pager_object::handle_oom(addr_t pd_from, addr_t pd_to,
|
|
|
|
char const * src_pd, char const * src_thread,
|
|
|
|
Policy policy, addr_t sm_notify,
|
|
|
|
char const * dst_pd, char const * dst_thread)
|
|
|
|
{
|
2016-11-10 10:46:30 +00:00
|
|
|
addr_t const core_pd_sel = platform_specific()->core_pd_sel();
|
2015-06-09 17:33:53 +00:00
|
|
|
|
|
|
|
enum { QUOTA_TRANSFER_PAGES = 2 };
|
|
|
|
|
2016-11-28 09:54:06 +00:00
|
|
|
if (pd_from == SRC_CORE_PD)
|
|
|
|
pd_from = core_pd_sel;
|
2015-06-09 17:33:53 +00:00
|
|
|
|
|
|
|
/* request current kernel quota usage of target pd */
|
|
|
|
addr_t limit_before = 0, usage_before = 0;
|
2016-11-28 09:54:06 +00:00
|
|
|
Nova::pd_ctrl_debug(pd_to, limit_before, usage_before);
|
2015-06-09 17:33:53 +00:00
|
|
|
|
|
|
|
if (verbose_oom) {
|
|
|
|
addr_t limit_source = 0, usage_source = 0;
|
|
|
|
/* request current kernel quota usage of source pd */
|
2016-11-28 09:54:06 +00:00
|
|
|
Nova::pd_ctrl_debug(pd_from, limit_source, usage_source);
|
2015-06-09 17:33:53 +00:00
|
|
|
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
log("oom - '", dst_pd, "':'", dst_thread, "' "
|
|
|
|
"(", usage_before, "/", limit_before, ") - "
|
|
|
|
"transfer ", (long)QUOTA_TRANSFER_PAGES, " pages "
|
|
|
|
"from '", src_pd, "':'", src_thread, "' "
|
|
|
|
"(", usage_source, "/", limit_source, ")");
|
2015-06-09 17:33:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t res = Nova::NOVA_PD_OOM;
|
|
|
|
|
2016-11-28 09:54:06 +00:00
|
|
|
if (pd_from != pd_to) {
|
2015-06-09 17:33:53 +00:00
|
|
|
/* upgrade quota */
|
2016-11-28 09:54:06 +00:00
|
|
|
uint8_t res = Nova::pd_ctrl(pd_from, Pd_op::TRANSFER_QUOTA,
|
|
|
|
pd_to, QUOTA_TRANSFER_PAGES);
|
2015-06-09 17:33:53 +00:00
|
|
|
if (res == Nova::NOVA_OK)
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* retry upgrade using core quota if policy permits */
|
|
|
|
if (policy == UPGRADE_PREFER_SRC_TO_DST) {
|
2016-11-28 09:54:06 +00:00
|
|
|
if (pd_from != core_pd_sel) {
|
2016-11-10 10:46:30 +00:00
|
|
|
res = Nova::pd_ctrl(core_pd_sel, Pd_op::TRANSFER_QUOTA,
|
2016-11-28 09:54:06 +00:00
|
|
|
pd_to, QUOTA_TRANSFER_PAGES);
|
2015-06-09 17:33:53 +00:00
|
|
|
if (res == Nova::NOVA_OK)
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
warning("kernel memory quota upgrade failed - trigger memory free up for "
|
|
|
|
"causing '", dst_pd, "':'", dst_thread, "' - "
|
|
|
|
"donator is '", src_pd, "':'", src_thread, "', "
|
|
|
|
"policy=", (int)policy);
|
2015-06-09 17:33:53 +00:00
|
|
|
|
|
|
|
/* if nothing helps try to revoke memory */
|
|
|
|
enum { REMOTE_REVOKE = true, PD_SELF = true };
|
|
|
|
Mem_crd crd_all(0, ~0U, Rights(true, true, true));
|
2016-11-28 09:54:06 +00:00
|
|
|
Nova::revoke(crd_all, PD_SELF, REMOTE_REVOKE, pd_to, sm_notify);
|
2015-06-09 17:33:53 +00:00
|
|
|
|
|
|
|
/* re-request current kernel quota usage of target pd */
|
|
|
|
addr_t limit_after = 0, usage_after = 0;
|
2016-11-28 09:54:06 +00:00
|
|
|
Nova::pd_ctrl_debug(pd_to, limit_after, usage_after);
|
2015-06-09 17:33:53 +00:00
|
|
|
/* if we could free up memory we continue */
|
|
|
|
if (usage_after < usage_before)
|
|
|
|
return Nova::NOVA_OK;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* There is still the chance that memory gets freed up, but one has to
|
|
|
|
* wait until RCU period is over. If we are in the pager code, we can
|
|
|
|
* instruct the kernel to block the faulting client thread during the reply
|
|
|
|
* syscall. If we are in a normal (non-pagefault) RPC service call,
|
|
|
|
* we can't block. The caller of this function can decide based on
|
|
|
|
* the return value what to do and whether blocking is ok.
|
|
|
|
*/
|
|
|
|
return Nova::NOVA_PD_OOM;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Pager_object::_oom_handler(addr_t pager_dst, addr_t pager_src,
|
|
|
|
addr_t reason)
|
|
|
|
{
|
|
|
|
if (sizeof(void *) == 4) {
|
|
|
|
/* On 32 bit edx and ecx as second and third regparm parameter is not
|
|
|
|
* available. It is used by the kernel internally to store ip/sp.
|
|
|
|
*/
|
|
|
|
asm volatile ("" : "=D" (pager_src));
|
|
|
|
asm volatile ("" : "=S" (reason));
|
|
|
|
}
|
|
|
|
|
2016-05-04 10:27:17 +00:00
|
|
|
Thread * myself = Thread::myself();
|
2015-06-09 17:33:53 +00:00
|
|
|
Utcb * utcb = reinterpret_cast<Utcb *>(myself->utcb());
|
|
|
|
Pager_object * obj_dst = reinterpret_cast<Pager_object *>(pager_dst);
|
|
|
|
Pager_object * obj_src = reinterpret_cast<Pager_object *>(pager_src);
|
|
|
|
|
|
|
|
/* Policy used if the Process of the paged thread runs out of memory */
|
|
|
|
enum Policy policy = Policy::UPGRADE_CORE_TO_DST;
|
|
|
|
|
|
|
|
|
|
|
|
/* check assertions - cases that should not happen on Genode@Nova */
|
|
|
|
enum { NO_OOM_PT = ~0UL, EC_OF_PT_OOM_OUTSIDE_OF_CORE };
|
|
|
|
|
|
|
|
/* all relevant (user) threads should have a OOM PT */
|
|
|
|
bool assert = pager_dst == NO_OOM_PT;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PT OOM solely created by core and they have to point to the pager
|
|
|
|
* thread inside core.
|
|
|
|
*/
|
|
|
|
assert |= pager_dst == EC_OF_PT_OOM_OUTSIDE_OF_CORE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This pager thread does solely reply to IPC calls - it should never
|
|
|
|
* cause OOM during the sending phase of a IPC.
|
|
|
|
*/
|
|
|
|
assert |= ((reason & (SELF | SEND)) == (SELF | SEND));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This pager thread should never send words (untyped items) - it just
|
|
|
|
* answers page faults by typed items (memory mappings).
|
|
|
|
*/
|
|
|
|
assert |= utcb->msg_words();
|
|
|
|
|
|
|
|
if (assert) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
error("unknown OOM case - stop core pager thread");
|
2015-06-09 17:33:53 +00:00
|
|
|
utcb->set_msg_word(0);
|
2016-03-11 16:32:43 +00:00
|
|
|
reply(myself->stack_top(), myself->native_thread().exc_pt_sel + Nova::SM_SEL_EC);
|
2015-06-09 17:33:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* be strict in case of the -strict- STOP policy - stop causing thread */
|
|
|
|
if (policy == STOP) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
error("PD has insufficient kernel memory left - stop thread");
|
2015-06-09 17:33:53 +00:00
|
|
|
utcb->set_msg_word(0);
|
2016-05-17 14:13:56 +00:00
|
|
|
reply(myself->stack_top(), obj_dst->sel_sm_block_pause());
|
2015-06-09 17:33:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char const * src_pd = "core";
|
|
|
|
char const * src_thread = "pager";
|
|
|
|
|
|
|
|
addr_t transfer_from = SRC_CORE_PD;
|
|
|
|
|
|
|
|
switch (pager_src) {
|
|
|
|
case SRC_PD_UNKNOWN:
|
|
|
|
/* should not happen on Genode - we create and know every PD in core */
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
error("Unknown PD has insufficient kernel memory left - stop thread");
|
2015-06-09 17:33:53 +00:00
|
|
|
utcb->set_msg_word(0);
|
2016-03-11 16:32:43 +00:00
|
|
|
reply(myself->stack_top(), myself->native_thread().exc_pt_sel + Nova::SM_SEL_EC);
|
2015-06-09 17:33:53 +00:00
|
|
|
|
|
|
|
case SRC_CORE_PD:
|
|
|
|
/* core PD -> other PD, which has insufficient kernel resources */
|
|
|
|
|
|
|
|
if (!(reason & SELF)) {
|
|
|
|
/* case that src thread != this thread in core */
|
|
|
|
src_thread = "unknown";
|
|
|
|
utcb->set_msg_word(0);
|
|
|
|
}
|
|
|
|
|
2016-11-10 10:46:30 +00:00
|
|
|
transfer_from = platform_specific()->core_pd_sel();
|
2015-06-09 17:33:53 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* non core PD -> non core PD */
|
|
|
|
utcb->set_msg_word(0);
|
|
|
|
|
|
|
|
if (pager_src == pager_dst || policy == UPGRADE_CORE_TO_DST)
|
2016-11-10 10:46:30 +00:00
|
|
|
transfer_from = platform_specific()->core_pd_sel();
|
2015-06-09 17:33:53 +00:00
|
|
|
else {
|
|
|
|
/* delegation of items between different PDs */
|
2016-05-19 18:33:36 +00:00
|
|
|
src_pd = obj_src->client_pd();
|
|
|
|
src_thread = obj_src->client_thread();
|
2015-06-09 17:33:53 +00:00
|
|
|
transfer_from = obj_src->pd_sel();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t res = obj_dst->handle_oom(transfer_from, src_pd, src_thread,
|
|
|
|
policy);
|
|
|
|
if (res == Nova::NOVA_OK)
|
|
|
|
/* handling succeeded - continue with original IPC */
|
|
|
|
reply(myself->stack_top());
|
|
|
|
|
|
|
|
/* transfer nothing */
|
|
|
|
utcb->set_msg_word(0);
|
|
|
|
|
|
|
|
if (res != Nova::NOVA_PD_OOM)
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
error("upgrading kernel memory failed, policy ", (int)policy, ", "
|
|
|
|
"error ", (int)res, " - stop thread finally");
|
|
|
|
|
2015-06-09 17:33:53 +00:00
|
|
|
/* else: caller will get blocked until RCU period is over */
|
|
|
|
|
|
|
|
/* block caller in semaphore */
|
2016-05-17 14:13:56 +00:00
|
|
|
reply(myself->stack_top(), obj_dst->sel_sm_block_oom());
|
2015-06-09 17:33:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
addr_t Pager_object::get_oom_portal()
|
|
|
|
{
|
2016-11-04 12:01:09 +00:00
|
|
|
addr_t const pt_oom = sel_oom_portal();
|
|
|
|
unsigned const genode_cpu_id = _location.xpos();
|
|
|
|
unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(genode_cpu_id);
|
2016-11-10 10:46:30 +00:00
|
|
|
addr_t const core_pd_sel = platform_specific()->core_pd_sel();
|
2015-06-09 17:33:53 +00:00
|
|
|
|
2016-11-04 12:01:09 +00:00
|
|
|
if (kernel_hip()->is_cpu_enabled(kernel_cpu_id) &&
|
|
|
|
pager_threads[genode_cpu_id]) {
|
2015-10-06 11:49:49 +00:00
|
|
|
|
2016-11-04 12:01:09 +00:00
|
|
|
addr_t const ec_sel = pager_threads[genode_cpu_id]->native_thread().ec_sel;
|
2016-11-10 10:46:30 +00:00
|
|
|
uint8_t res = create_portal(pt_oom, core_pd_sel, ec_sel, Mtd(0),
|
2015-10-06 11:49:49 +00:00
|
|
|
reinterpret_cast<addr_t>(_oom_handler),
|
|
|
|
this);
|
|
|
|
if (res == Nova::NOVA_OK)
|
|
|
|
return pt_oom;
|
|
|
|
}
|
2015-06-09 17:33:53 +00:00
|
|
|
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
error("creating portal for out of memory notification failed");
|
2015-06-09 17:33:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-12-22 15:19:25 +00:00
|
|
|
|
2016-05-19 18:33:36 +00:00
|
|
|
const char * Pager_object::client_thread() const
|
|
|
|
{
|
|
|
|
Platform_thread * client = reinterpret_cast<Platform_thread *>(_badge);
|
|
|
|
return client ? client->name() : "unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char * Pager_object::client_pd() const
|
|
|
|
{
|
|
|
|
Platform_thread * client = reinterpret_cast<Platform_thread *>(_badge);
|
|
|
|
return client ? client->pd_name() : "unknown";
|
|
|
|
}
|
|
|
|
|
2014-09-05 15:00:31 +00:00
|
|
|
/**********************
|
|
|
|
** Pager activation **
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
Pager_activation_base::Pager_activation_base(const char *name, size_t stack_size)
|
|
|
|
:
|
2016-05-04 10:27:17 +00:00
|
|
|
Thread(Cpu_session::Weight::DEFAULT_WEIGHT, name, stack_size,
|
|
|
|
Affinity::Location(which_cpu(this), 0)),
|
2014-09-05 15:00:31 +00:00
|
|
|
_cap(Native_capability()), _ep(0), _cap_valid(Lock::LOCKED)
|
|
|
|
{
|
|
|
|
/* creates local EC */
|
2016-05-04 10:27:17 +00:00
|
|
|
Thread::start();
|
2014-09-05 15:00:31 +00:00
|
|
|
|
2016-05-04 10:27:17 +00:00
|
|
|
reinterpret_cast<Nova::Utcb *>(Thread::utcb())->crd_xlt = Obj_crd(0, ~0UL);
|
2014-09-05 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Pager_activation_base::entry() { }
|
|
|
|
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
** Pager entrypoint **
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
|
2016-01-19 19:24:22 +00:00
|
|
|
Pager_entrypoint::Pager_entrypoint(Rpc_cap_factory &cap_factory)
|
2014-09-05 15:00:31 +00:00
|
|
|
{
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
/* sanity check for pager threads */
|
2014-09-05 15:00:31 +00:00
|
|
|
if (kernel_hip()->cpu_max() > PAGER_CPUS) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 17:07:09 +00:00
|
|
|
error("kernel supports more CPUs (", kernel_hip()->cpu_max(), ") "
|
|
|
|
"than Genode (", (unsigned)PAGER_CPUS, ")");
|
2014-09-05 15:00:31 +00:00
|
|
|
nova_die();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* detect enabled CPUs and create per CPU a pager thread */
|
|
|
|
typedef Pager_activation<PAGER_STACK_SIZE> Pager;
|
|
|
|
Pager * pager_of_cpu = reinterpret_cast<Pager *>(&pager_activation_mem);
|
|
|
|
|
2016-11-04 12:01:09 +00:00
|
|
|
for (unsigned i = 0; i < kernel_hip()->cpus(); i++, pager_of_cpu++) {
|
|
|
|
unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(i);
|
|
|
|
if (!kernel_hip()->is_cpu_enabled(kernel_cpu_id))
|
2014-09-05 15:00:31 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
pager_threads[i] = pager_of_cpu;
|
|
|
|
construct_at<Pager>(pager_threads[i]);
|
|
|
|
}
|
2011-12-22 15:19:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Pager_entrypoint::dissolve(Pager_object *obj)
|
|
|
|
{
|
2014-09-05 15:00:31 +00:00
|
|
|
/* take care that no faults are in-flight */
|
2012-12-04 08:49:01 +00:00
|
|
|
obj->cleanup_call();
|
2011-12-22 15:19:25 +00:00
|
|
|
}
|