c5877b5575
Issue #1652
102 lines
2.3 KiB
C++
102 lines
2.3 KiB
C++
/*
|
|
* \brief Kernel backend for execution contexts in userland
|
|
* \author Martin Stein
|
|
* \author Stefan Kalkowski
|
|
* \date 2013-11-11
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 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.
|
|
*/
|
|
|
|
/* core includes */
|
|
#include <assert.h>
|
|
#include <kernel/thread.h>
|
|
#include <kernel/pd.h>
|
|
#include <kernel/kernel.h>
|
|
|
|
using namespace Kernel;
|
|
|
|
|
|
Thread::Thread(unsigned const priority, unsigned const quota,
|
|
char const * const label)
|
|
: Thread_base(this), Cpu_job(priority, quota),
|
|
_state(AWAITS_START), _signal_receiver(0),
|
|
_label(label) { cpu_exception = RESET; }
|
|
|
|
|
|
void Thread::exception(unsigned const cpu)
|
|
{
|
|
switch (cpu_exception) {
|
|
case SUPERVISOR_CALL:
|
|
_call();
|
|
return;
|
|
case PREFETCH_ABORT:
|
|
_mmu_exception();
|
|
return;
|
|
case DATA_ABORT:
|
|
_mmu_exception();
|
|
return;
|
|
case INTERRUPT_REQUEST:
|
|
_interrupt(cpu);
|
|
return;
|
|
case FAST_INTERRUPT_REQUEST:
|
|
_interrupt(cpu);
|
|
return;
|
|
case UNDEFINED_INSTRUCTION:
|
|
if (_cpu->retry_undefined_instr(&_lazy_state)) { return; }
|
|
PWRN("%s -> %s: undefined instruction at ip=%p",
|
|
pd_label(), label(), (void*)ip);
|
|
_stop();
|
|
return;
|
|
case RESET:
|
|
return;
|
|
default:
|
|
PWRN("%s -> %s: triggered an unknown exception %lu",
|
|
pd_label(), label(), (unsigned long)cpu_exception);
|
|
_stop();
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
Thread_event Thread::* Thread::_event(unsigned const id) const
|
|
{
|
|
static Thread_event Thread::* _events[] = {
|
|
/* [0] */ &Thread::_fault
|
|
};
|
|
return id < sizeof(_events)/sizeof(_events[0]) ? _events[id] : 0;
|
|
}
|
|
|
|
|
|
void Thread::_mmu_exception()
|
|
{
|
|
_become_inactive(AWAITS_RESUME);
|
|
if (in_fault(_fault_addr, _fault_writes)) {
|
|
_fault_pd = (addr_t)_pd->platform_pd();
|
|
_fault_signal = (addr_t)_fault.signal_context();
|
|
|
|
/**
|
|
* core should never raise a page-fault,
|
|
* if this happens print out an error message with debug information
|
|
*/
|
|
if (_pd == Kernel::core_pd())
|
|
PERR("Pagefault in core thread (%s): ip=%p fault=%p",
|
|
label(), (void*)ip, (void*)_fault_addr);
|
|
|
|
_fault.submit();
|
|
return;
|
|
}
|
|
PERR("unknown MMU exception");
|
|
}
|
|
|
|
|
|
void Thread::_call_update_pd()
|
|
{
|
|
Pd * const pd = (Pd *) user_arg_1();
|
|
if (Cpu_domain_update::_do_global(pd->asid)) { _pause(); }
|
|
}
|