20 #include "InterruptManager.h" 21 #include "pedigree/kernel/machine/Machine.h" 22 #include "pedigree/kernel/machine/types.h" 23 #include "pedigree/kernel/panic.h" 24 #include "pedigree/kernel/processor/Processor.h" 25 #include "pedigree/kernel/utilities/utility.h" 27 #include "pedigree/kernel/debugger/Debugger.h" 29 #include "pedigree/kernel/Log.h" 31 #define SYSCALL_INTERRUPT_NUMBER 8 32 #define BREAKPOINT_INTERRUPT_NUMBER 9 34 const char *g_ExceptionNames[32] = {
36 "TLB modification exception",
37 "TLB exception (load or instruction fetch)",
38 "TLB exception (store)",
39 "Address error exception (load or instruction fetch)",
40 "Address error exception (store)",
41 "Bus error exception (instruction fetch)",
42 "Bus error exception (data: load or store)",
44 "Breakpoint exception",
45 "Reserved instruction exception",
46 "Coprocessor unusable exception",
47 "Arithmetic overflow exception",
49 "LDCz/SDCz to uncached address",
50 "Virtual coherency exception",
51 "Machine check exception",
52 "Floating point exception",
58 "Watchpoint exception",
86 volatile uint32_t *mpuIntcRegisters =
reinterpret_cast<volatile uint32_t *
>(
88 if (!mpuIntcRegisters)
94 if (
UNLIKELY(handler != 0 && m_Handler[interruptNumber] != 0))
96 if (
UNLIKELY(handler == 0 && m_Handler[interruptNumber] == 0))
100 size_t n = (interruptNumber % 96) / 32;
101 mpuIntcRegisters[INTCPS_MIR_CLEAR + (n * 8)] = 1 << (interruptNumber % 32);
103 m_Handler[interruptNumber] = handler;
112 volatile uint32_t *mpuIntcRegisters =
reinterpret_cast<volatile uint32_t *
>(
114 if (!mpuIntcRegisters)
118 if (
UNLIKELY(interruptNumber >= 96))
120 if (
UNLIKELY(handler != 0 && m_DbgHandler[interruptNumber] != 0))
122 if (
UNLIKELY(handler == 0 && m_DbgHandler[interruptNumber] == 0))
126 size_t n = (interruptNumber % 96) / 32;
127 mpuIntcRegisters[INTCPS_MIR_CLEAR + (n * 8)] = 1 << (interruptNumber % 32);
129 m_DbgHandler[interruptNumber] = handler;
148 if (
UNLIKELY(Service >= serviceEnd))
150 if (
UNLIKELY(handler != 0 && m_SyscallHandler[Service] != 0))
152 if (
UNLIKELY(handler == 0 && m_SyscallHandler[Service] == 0))
155 m_SyscallHandler[Service] = handler;
160 Service_t service, uintptr_t
function, uintptr_t p1, uintptr_t p2,
161 uintptr_t p3, uintptr_t p4, uintptr_t p5)
168 void kdata_abort(InterruptState &state)
NORETURN;
169 void kdata_abort(InterruptState &state)
175 asm volatile(
"MRC p15,0,%0,c6,c0,0" :
"=r"(dfar));
176 asm volatile(
"MRC p15,0,%0,c5,c0,0" :
"=r"(dfsr));
179 bool bWrite = !!(dfsr & (1 << 11));
180 uint32_t status = (dfsr & (1 << 10) ? 1 << 4 : 0) | (dfsr & 0xF);
184 sError.append(
"Data Abort: ");
190 sError.append(dfar, 16, 8,
'0');
191 sError.append(
" @ 0x");
192 sError.append(state.getInstructionPointer(), 16, 8,
'0');
198 sError.append(
"Alignment fault");
202 sError.append(
"Translation fault");
206 sError.append(
"Access flag fault");
211 uint32_t domain = (dfsr >> 4) & 0xF;
212 sError.append(
"Domain fault for domain 0x");
213 sError.append(domain, 16, 8,
'0');
218 sError.append(
"Permission fault");
221 sError.append(
"Debug event");
224 sError.append(
"Sync external abort");
227 sError.append(
"Async external abort");
230 sError.append(
"Unknown fault");
233 ERROR_NOLOCK(static_cast<const char *>(sError));
243 void kprefetch_abort(InterruptState &state)
NORETURN;
244 void kprefetch_abort(InterruptState &state)
249 sError.append(
"Prefetch Abort at 0x");
250 sError.append(state.getInstructionPointer(), 16, 8,
'0');
258 void kswi_handler(InterruptState &state)
262 reinterpret_cast<const uint32_t *
>(state.getInstructionPointer() - 4);
263 uint32_t swi = (*at) & 0xFFFFFFUL;
269 for (
size_t i = 0; i < state.getRegisterCount(); ++i)
272 state.getRegisterName(i) <<
"=" <<
Hex << state.getRegister(i));
276 else if (swi == 0xdeb16)
280 sError.append(
"Debugger Trap at 0x");
281 sError.append(state.getInstructionPointer(), 16, 8,
'0');
290 extern "C" void arm_swint_handler(InterruptState &state);
291 extern "C" void arm_instundef_handler()
__attribute__((naked));
293 extern "C" void arm_irq_handler(InterruptState &state);
295 extern "C" void arm_prefetch_abort_handler(InterruptState &state)
297 extern "C" void arm_data_abort_handler(InterruptState &state)
299 extern "C" void arm_addrexcept_handler()
__attribute__((naked));
301 extern "C" void arm_swint_handler(InterruptState &state)
306 extern "C" void arm_instundef_handler()
308 NOTICE_NOLOCK(
"undefined instruction");
313 extern "C" void arm_fiq_handler()
315 NOTICE_NOLOCK(
"FIQ");
320 extern "C" void arm_irq_handler(InterruptState &state)
325 extern "C" void arm_reset_handler()
327 NOTICE_NOLOCK(
"reset");
332 extern "C" void arm_prefetch_abort_handler(InterruptState &state)
334 kprefetch_abort(state);
339 extern "C" void arm_data_abort_handler(InterruptState &state)
344 extern "C" void arm_addrexcept_handler()
346 NOTICE_NOLOCK(
"address exception");
351 extern uint32_t __arm_vector_table;
352 extern uint32_t __end_arm_vector_table;
365 reinterpret_cast<physical_uintptr_t>(&__arm_vector_table),
366 reinterpret_cast<void *>(0xFFFF0000),
372 asm volatile(
"MRC p15,0,%0,c1,c0,0" :
"=r"(sctlr));
373 if (!(sctlr & 0x2000))
375 asm volatile(
"MCR p15,0,%0,c1,c0,0" : :
"r"(sctlr));
378 volatile uint32_t *mpuIntcRegisters =
reinterpret_cast<volatile uint32_t *
>(
382 mpuIntcRegisters[INTCPS_SYSCONFIG] = 2;
383 while ((mpuIntcRegisters[INTCPS_SYSSTATUS] & 1) == 0)
387 uint32_t revision = mpuIntcRegisters[0];
389 "MPU interrupt controller at " 391 << reinterpret_cast<uintptr_t>(
393 <<
" - revision " <<
Dec << ((revision >> 4) & 0xF) <<
"." 394 << (revision & 0xF) <<
Hex);
398 mpuIntcRegisters[INTCPS_IDLE] = 0;
401 for (
size_t m = 0; m < 96; m++)
404 mpuIntcRegisters[INTCPS_ILR + m] = 0;
409 for (
size_t n = 0; n < 3; n++)
411 mpuIntcRegisters[INTCPS_MIR_SET + (n * 8)] = 0xFFFFFFFF;
412 mpuIntcRegisters[INTCPS_ISR_CLEAR + (n * 8)] = 0xFFFFFFFF;
416 mpuIntcRegisters[INTCPS_THRESHOLD] = 0xFF;
419 mpuIntcRegisters[INTCPS_CONTROL] = 3;
424 volatile uint32_t *mpuIntcRegisters =
reinterpret_cast<volatile uint32_t *
>(
426 if (!mpuIntcRegisters)
430 size_t intNumber = mpuIntcRegisters[INTCPS_SIR_IRQ] & 0x7F;
434 if (m_Instance.m_DbgHandler[intNumber] != 0)
435 m_Instance.m_DbgHandler[intNumber]->interrupt(
436 intNumber, interruptState);
440 if (m_Instance.m_Handler[intNumber] != 0)
441 m_Instance.m_Handler[intNumber]->interrupt(intNumber, interruptState);
444 mpuIntcRegisters[INTCPS_CONTROL] =
451 for (
size_t i = 0; i < 256; i++)
460 for (
size_t i = 0; i < serviceEnd; i++)
461 m_SyscallHandler[i] = 0;
static MemoryRegion m_MPUINTCRegion
virtual size_t getBreakpointInterruptNumber() PURE
static PhysicalMemoryManager & instance()
virtual bool registerInterruptHandlerDebugger(size_t interruptNumber, InterruptHandler *handler)
static const size_t continuous
static EXPORTED_PUBLIC SyscallManager & instance()
static Debugger & instance()
virtual bool registerInterruptHandler(size_t interruptNumber, InterruptHandler *handler)
Handles interrupts and interrupt registrations from kernel components.
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
static void interrupt(InterruptState &interruptState)
static const size_t Write
void start(InterruptState &state, LargeStaticString &description)
static const size_t KernelMode
virtual uintptr_t syscall(Service_t service, uintptr_t function, uintptr_t p1=0, uintptr_t p2=0, uintptr_t p3=0, uintptr_t p4=0, uintptr_t p5=0)
Special memory entity in the kernel's virtual address space.
virtual ~ARMV7InterruptManager()
static void initialiseProcessor()
void * virtualAddress() const
static ARMV7InterruptManager m_Instance
Abstract base class for interrupt-handlers.
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
static InterruptManager & instance()
virtual bool registerSyscallHandler(Service_t Service, SyscallHandler *handler)
virtual size_t getDebugInterruptNumber() PURE
static ARMV7InterruptManager & instance()