20 #include "InterruptManager.h" 21 #include "pedigree/kernel/LockGuard.h" 22 #include "pedigree/kernel/Log.h" 23 #include "pedigree/kernel/process/Thread.h" 24 #include "pedigree/kernel/processor/InterruptHandler.h" 25 #include "pedigree/kernel/processor/Processor.h" 26 #include "pedigree/kernel/processor/ProcessorInformation.h" 27 #include "pedigree/kernel/processor/state.h" 28 #include "pedigree/kernel/utilities/StaticString.h" 31 #include "pedigree/kernel/debugger/Debugger.h" 35 #include "pedigree/kernel/Subsystem.h" 36 #include "pedigree/kernel/process/Process.h" 37 #include "pedigree/kernel/process/TimeTracker.h" 40 static const char *g_ExceptionNames[] = {
46 "BOUND Range Exceeded",
48 "Device Not Available",
50 "Coprocessor Segment Overrun",
53 "Segment Not Present",
55 "General Protection Fault",
57 "FPU Floating-Point Error",
60 "SIMD Floating-Point Exception",
61 "Reserved: Interrupt 19",
62 "Reserved: Interrupt 20",
63 "Reserved: Interrupt 21",
64 "Reserved: Interrupt 22",
65 "Reserved: Interrupt 23",
66 "Reserved: Interrupt 24",
67 "Reserved: Interrupt 25",
68 "Reserved: Interrupt 26",
69 "Reserved: Interrupt 27",
70 "Reserved: Interrupt 28",
71 "Reserved: Interrupt 29",
72 "Reserved: Interrupt 30",
73 "Reserved: Interrupt 31"};
89 if (
UNLIKELY(nInterruptNumber >= 256))
91 if (
UNLIKELY(pHandler != 0 && m_pHandler[nInterruptNumber] != 0))
93 if (
UNLIKELY(pHandler == 0 && m_pHandler[nInterruptNumber] == 0))
97 m_pHandler[nInterruptNumber] = pHandler;
102 #if defined(DEBUGGER) 111 if (
UNLIKELY(nInterruptNumber >= 256))
113 if (
UNLIKELY(pHandler != 0 && m_pDbgHandler[nInterruptNumber] != 0))
115 if (
UNLIKELY(pHandler == 0 && m_pDbgHandler[nInterruptNumber] == 0))
119 m_pDbgHandler[nInterruptNumber] = pHandler;
136 TimeTracker tracker(0, !interruptState.kernelMode());
137 size_t nIntNumber = interruptState.getInterruptNumber();
139 #if defined(DEBUGGER) 146 pHandler = m_Instance.m_pDbgHandler[nIntNumber];
151 pHandler->
interrupt(nIntNumber, interruptState);
160 pHandler = m_Instance.m_pHandler[nIntNumber];
164 if (
LIKELY(pHandler != 0))
166 pHandler->
interrupt(nIntNumber, interruptState);
179 Subsystem *pSubsystem = pProcess->getSubsystem();
180 if (pSubsystem && !interruptState.kernelMode())
185 pThread, Subsystem::DivideByZero);
191 pThread, Subsystem::InvalidOpcode);
194 else if (
UNLIKELY(nIntNumber == 13))
197 pThread, Subsystem::GeneralProtectionFault);
200 else if (
UNLIKELY(nIntNumber == 16))
205 else if (
UNLIKELY(nIntNumber == 19))
208 pThread, Subsystem::SpecialFpuError);
218 if (
LIKELY(nIntNumber < 32 && nIntNumber != 1 && nIntNumber != 3))
227 e.append(
"Exception #0x");
228 e.append(nIntNumber, 16);
230 e.append(g_ExceptionNames[nIntNumber]);
242 e.append(pParent->
getId());
245 e.append(pThread->
getId());
249 if (nIntNumber == 14)
252 asm volatile(
"mov %%cr2, %%rax" :
"=a"(cr2));
254 e.append(cr2, 16, 16,
'0');
255 e.append(
", errorcode 0x");
256 e.append(interruptState.m_Errorcode, 16, 8,
'0');
259 if (nIntNumber == 13)
262 if (interruptState.m_Errorcode)
264 e.append(
" errorcode 0x");
265 e.append(interruptState.m_Errorcode, 16, 8,
'0');
268 e.append(interruptState.getInstructionPointer(), 16, 16,
'0');
274 ERROR_NOLOCK(
"(double fault, system is very unhappy)");
277 asm volatile(
"mov %%cr2, %%rax" :
"=a"(cr2));
279 " -> #DF possibly caused by #PF at " <<
Hex << cr2 <<
".");
283 ERROR(static_cast<const char *>(e));
285 #if defined(DEBUGGER) 304 }
PACKED idtr = {4095,
reinterpret_cast<uintptr_t
>(&m_Instance.m_IDT)};
306 asm volatile(
"lidt %0" ::
"m"(idtr));
310 size_t nInterruptNumber, uintptr_t interruptHandler)
312 m_IDT[nInterruptNumber].offset0 = interruptHandler & 0xFFFF;
313 m_IDT[nInterruptNumber].selector = 0x08;
314 m_IDT[nInterruptNumber].ist = 0;
315 m_IDT[nInterruptNumber].flags = 0xEE ;
316 m_IDT[nInterruptNumber].offset1 = (interruptHandler >> 16) & 0xFFFF;
317 m_IDT[nInterruptNumber].offset2 = (interruptHandler >> 32) & 0xFFFFFFFF;
318 m_IDT[nInterruptNumber].res = 0;
325 m_IDT[nInterruptNumber].ist = ist;
331 for (
size_t i = 0; i < 256; i++)
340 extern uintptr_t interrupt_handler_array[];
341 for (
size_t i = 0; i < 256; i++)
virtual ~X64InterruptManager()
static Debugger & instance()
Handles interrupts and interrupt registrations from kernel components.
InterruptHandler * m_pHandler[256]
static X64InterruptManager m_Instance
X64InterruptManager() INITIALISATION_ONLY
virtual void threadException(Thread *pThread, ExceptionType eType)
virtual size_t getBreakpointInterruptNumber() PURE
static ProcessorInformation & information()
static void interrupt(InterruptState &interruptState) USED
void start(InterruptState &state, LargeStaticString &description)
virtual size_t getDebugInterruptNumber() PURE
virtual void interrupt(size_t nInterruptNumber, InterruptState &state)=0
virtual bool registerInterruptHandlerDebugger(size_t nInterruptNumber, InterruptHandler *pHandler)
InterruptHandler * m_pDbgHandler[256]
void setInterruptGate(size_t nInterruptNumber, uintptr_t interruptHandler) INITIALISATION_ONLY
static void initialiseProcessor() INITIALISATION_ONLY
Process * getParent() const
Abstract base class for interrupt-handlers.
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
virtual bool registerInterruptHandler(size_t nInterruptNumber, InterruptHandler *pHandler)
static InterruptManager & instance()
void setIst(size_t nInterruptNumber, size_t ist)
static X64InterruptManager & instance()