1#include "InterruptManager.h"
2#include "pedigree/kernel/Log.h"
3#include "pedigree/kernel/panic.h"
4#include "pedigree/kernel/process/InterruptTimeAccounting.h"
5#include "pedigree/kernel/process/PerProcessorScheduler.h"
6#include "pedigree/kernel/process/Thread.h"
7#include "pedigree/kernel/processor/InterruptHandler.h"
8#include "pedigree/kernel/processor/PageFaultHandler.h"
9#include "pedigree/kernel/processor/Processor.h"
10#include "pedigree/kernel/processor/state.h"
12#include "SyscallManager.h"
14extern "C" void virtHandleIrq(InterruptState& state);
17void finishUserReturn(InterruptState& state) {
18 if (state.kernelMode()) {
27 bool terminal =
false;
36 if (terminal || !waited) {
45 panic(
"ARM64: terminal user return unexpectedly resumed");
50Arm64InterruptManager::Arm64InterruptManager()
65 return Arm64InterruptManager::instance();
73 if (!expected && !handler) {
76 return __atomic_compare_exchange_n(&m_Handlers[number], &expected, handler,
false,
77 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
87 if (!expected && !handler) {
90 return __atomic_compare_exchange_n(&m_DebugHandlers[number], &expected, handler,
false,
91 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
95void Arm64InterruptManager::dispatch(
size_t number, InterruptState& state) {
97 ERROR(
"ARM64: exception class " <<
Hex << number <<
" vector " << state.vector <<
" ESR "
98 << state.esr <<
" FAR " << state.far <<
" ELR "
99 << state.getInstructionPointer());
100 panic(
"ARM64: invalid exception number");
103 InterruptHandler* debugger = __atomic_load_n(&m_DebugHandlers[number], __ATOMIC_ACQUIRE);
108 InterruptHandler* handler = __atomic_load_n(&m_Handlers[number], __ATOMIC_ACQUIRE);
113 ERROR(
"ARM64: unhandled exception " <<
Dec << number <<
" at " <<
Hex
114 << state.getInstructionPointer() <<
" ESR " << state.esr);
115 panic(
"ARM64: unhandled exception");
118extern "C" void arm64HandleException(InterruptState* state) {
119 if (!state->kernelMode()) {
124 asm volatile(
"mrs %0, tpidr_el0" :
"=r"(tls));
128 const size_t vector = state->vector;
129 const size_t exceptionClass = (state->esr >> 26) & 0x3f;
130 if ((vector & 3) == 0 && exceptionClass == 0x15 && !state->kernelMode()) {
131 Arm64SyscallManager::handle(*
static_cast<SyscallState*
>(state));
136 if ((vector & 3) == 1) {
137 virtHandleIrq(*state);
138 }
else if (exceptionClass == 0x20 || exceptionClass == 0x21 || exceptionClass == 0x24 ||
139 exceptionClass == 0x25) {
140 Arm64InterruptManager::instance().dispatch(14, *state);
142 Arm64InterruptManager::instance().dispatch(exceptionClass, *state);
145 finishUserReturn(*state);
bool registerInterruptHandlerDebugger(size_t number, InterruptHandler *handler) override
bool registerInterruptHandler(size_t number, InterruptHandler *handler) override
Abstract base class for interrupt-handlers.
virtual void interrupt(size_t nInterruptNumber, InterruptState &state)=0
Handles interrupts and interrupt registrations from kernel components.
static EXPORTED_PUBLIC InterruptManager & instance()
static void finishUserReturn(Thread *thread)
void commitUserReturnTerminalState()
MUST_USE_RESULT bool serviceUserReturnWork(InterruptState &state, UserReturnFrame::Origin origin=UserReturnFrame::Origin::Interrupt, bool diagnosticSample=false)
static ProcessorInformation & information()
static void setInterrupts(bool bEnable)
void setTlsBase(uintptr_t base)
AffinityResult completeAffinityAtSafePoint(bool *waited=nullptr)
void EXPORTED_PUBLIC panic(const char *msg) NORETURN