20 #include "InterruptManager.h" 21 #include "pedigree/kernel/LockGuard.h" 22 #include "pedigree/kernel/panic.h" 23 #include "pedigree/kernel/processor/Processor.h" 24 #include "pedigree/kernel/utilities/StaticString.h" 26 #include "pedigree/kernel/debugger/Debugger.h" 30 #include "pedigree/kernel/Subsystem.h" 31 #include "pedigree/kernel/process/Process.h" 34 #include "pedigree/kernel/utilities/utility.h" 36 #define SYSCALL_INTERRUPT_NUMBER 255 38 const char *g_ExceptionNames[] = {
44 "BOUND Range Exceeded",
46 "Device Not Available",
48 "Coprocessor Segment Overrun",
51 "Segment Not Present",
53 "General Protection Fault",
55 "Reserved: Interrupt 15",
56 "FPU Floating-Point Error",
59 "SIMD Floating-Point Exception",
60 "Reserved: Interrupt 20",
61 "Reserved: Interrupt 21",
62 "Reserved: Interrupt 22",
63 "Reserved: Interrupt 23",
64 "Reserved: Interrupt 24",
65 "Reserved: Interrupt 25",
66 "Reserved: Interrupt 26",
67 "Reserved: Interrupt 27",
68 "Reserved: Interrupt 28",
69 "Reserved: Interrupt 29",
70 "Reserved: Interrupt 30",
71 "Reserved: Interrupt 31"};
90 nInterruptNumber >= 256 ||
91 nInterruptNumber == SYSCALL_INTERRUPT_NUMBER))
93 if (
UNLIKELY(pHandler != 0 && m_pHandler[nInterruptNumber] != 0))
95 if (
UNLIKELY(pHandler == 0 && m_pHandler[nInterruptNumber] == 0))
98 m_pHandler[nInterruptNumber] = pHandler;
110 nInterruptNumber >= 256 ||
111 nInterruptNumber == SYSCALL_INTERRUPT_NUMBER))
113 if (
UNLIKELY(pHandler != 0 && m_pDbgHandler[nInterruptNumber] != 0))
115 if (
UNLIKELY(pHandler == 0 && m_pDbgHandler[nInterruptNumber] == 0))
118 m_pDbgHandler[nInterruptNumber] = pHandler;
137 if (
UNLIKELY(Service >= serviceEnd))
139 if (
UNLIKELY(pHandler != 0 && m_pSyscallHandler[Service] != 0))
141 if (
UNLIKELY(pHandler == 0 && m_pSyscallHandler[Service] == 0))
144 m_pSyscallHandler[Service] = pHandler;
150 size_t nIntNumber = interruptState.getInterruptNumber();
156 #if defined(DEBUGGER) 163 pHandler = m_Instance.m_pDbgHandler[nIntNumber];
168 pHandler->
interrupt(nIntNumber, interruptState);
173 if (nIntNumber == SYSCALL_INTERRUPT_NUMBER)
175 size_t serviceNumber = interruptState.getSyscallService();
177 if (
UNLIKELY(serviceNumber >= serviceEnd))
188 pHandler = m_Instance.m_pSyscallHandler[serviceNumber];
191 if (
LIKELY(pHandler != 0))
193 interruptState.m_Eax = pHandler->
syscall(interruptState);
194 interruptState.m_Ebx =
199 NOTICE(
"Unwind state exit, in interrupt handler");
215 pHandler = m_Instance.m_pHandler[nIntNumber];
219 if (
LIKELY(pHandler != 0))
221 pHandler->
interrupt(nIntNumber, interruptState);
229 Subsystem *pSubsystem = pProcess->getSubsystem();
235 pThread, Subsystem::DivideByZero, interruptState);
241 pThread, Subsystem::InvalidOpcode, interruptState);
244 else if (
UNLIKELY(nIntNumber == 13))
247 pThread, Subsystem::GeneralProtectionFault, interruptState);
250 else if (
UNLIKELY(nIntNumber == 16))
253 pThread, Subsystem::FpuError, interruptState);
256 else if (
UNLIKELY(nIntNumber == 19))
259 pThread, Subsystem::SpecialFpuError, interruptState);
268 if (
LIKELY(nIntNumber < 32 && nIntNumber != 1 && nIntNumber != 3))
275 e.append(
"Exception #");
276 e.append(nIntNumber, 10);
278 e.append(g_ExceptionNames[nIntNumber]);
280 if (nIntNumber == 14)
283 asm volatile(
"mov %%cr2, %%eax" :
"=a"(cr2));
285 e.append(cr2, 16, 8,
'0');
286 e.append(
", errorcode 0x");
287 e.append(interruptState.m_Errorcode, 16, 8,
'0');
297 ERROR_NOLOCK(
"--------------------------- DOUBLE FAULT " 298 "---------------------------");
300 ERROR_NOLOCK(
"EIP was: " << tss->eip <<
".");
301 ERROR_NOLOCK(
"ESP/EBP: " << tss->esp <<
", " << tss->ebp <<
".");
303 ERROR_NOLOCK(
"GPs:");
305 "EAX: " << tss->eax <<
", EBX: " << tss->ebx
306 <<
", ECX: " << tss->ecx <<
".");
308 "EDX: " << tss->edx <<
", ESI: " << tss->esi
309 <<
", EDI: " << tss->edi <<
".");
311 ERROR_NOLOCK(
"Segments:");
313 "CS: " << tss->cs <<
", DS: " << tss->ds <<
", ES: " << tss->es
316 "FS: " << tss->fs <<
", GS: " << tss->gs <<
", SS: " << tss->ss
320 asm volatile(
"mov %%cr2, %%eax" :
"=a"(cr2));
321 NOTICE_NOLOCK(
"Possible #PF at address " << cr2 <<
".");
324 interruptState.setInstructionPointer(tss->eip);
325 interruptState.setBasePointer(tss->ebp);
326 interruptState.setFlags(tss->eflags);
328 #if defined(DEBUGGER) 331 panic(
"Can't return from a #DF");
339 Service_t service, uintptr_t
function, uintptr_t p1, uintptr_t p2,
340 uintptr_t p3, uintptr_t p4, uintptr_t p5)
342 uint32_t eax = ((service & 0xFFFF) << 16) | (
function & 0xFFFF);
344 asm volatile(
"int $255" 346 :
"0"(eax),
"b"(p1),
"c"(p2),
"d"(p3),
"S"(p4),
"D"(p5));
361 }
PACKED idtr = {2047,
reinterpret_cast<uintptr_t
>(&m_Instance.m_IDT)};
363 asm volatile(
"lidt %0" ::
"m"(idtr));
367 size_t nInterruptNumber, uintptr_t interruptHandler,
bool bUserspace)
369 m_IDT[nInterruptNumber].offset0 = interruptHandler & 0xFFFF;
370 m_IDT[nInterruptNumber].selector = 0x08;
371 m_IDT[nInterruptNumber].res = 0;
372 m_IDT[nInterruptNumber].flags = bUserspace ? 0xEE : 0x8E;
373 m_IDT[nInterruptNumber].offset1 = (interruptHandler >> 16) & 0xFFFF;
378 m_IDT[nInterruptNumber].offset0 = 0;
379 m_IDT[nInterruptNumber].selector = tssSeg;
380 m_IDT[nInterruptNumber].res = 0;
381 m_IDT[nInterruptNumber].flags = 0xE5;
382 m_IDT[nInterruptNumber].offset1 = 0;
388 for (
size_t i = 0; i < 256; i++)
391 #if defined(DEBUGGER) 397 for (
size_t i = 0; i < serviceEnd; i++)
401 extern uintptr_t interrupt_handler_array[];
402 for (
size_t i = 0; i < 256; i++)
404 i, interrupt_handler_array[i],
405 (i == SYSCALL_INTERRUPT_NUMBER || i == 3 ) ?
virtual bool registerSyscallHandler(Service_t Service, SyscallHandler *pHandler)
static EXPORTED_PUBLIC SyscallManager & instance()
static Debugger & instance()
static X86InterruptManager m_Instance
Handles interrupts and interrupt registrations from kernel components.
virtual uintptr_t syscall(SyscallState &State)=0
virtual void threadException(Thread *pThread, ExceptionType eType)
static ProcessorInformation & information()
void setTaskGate(size_t nInterruptNumber, uint16_t tssSeg) INITIALISATION_ONLY
InterruptHandler * m_pHandler[256]
InterruptHandler * m_pDbgHandler[256]
void start(InterruptState &state, LargeStaticString &description)
virtual void interrupt(size_t nInterruptNumber, InterruptState &state)=0
virtual ~X86InterruptManager()
static void initialiseProcessor() INITIALISATION_ONLY
SyscallHandler * m_pSyscallHandler[serviceEnd]
virtual size_t getDebugInterruptNumber() PURE
Process * getParent() const
X86InterruptManager() INITIALISATION_ONLY
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)
virtual size_t getBreakpointInterruptNumber() PURE
Abstract base class for interrupt-handlers.
static void interrupt(InterruptState &interruptState)
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
static X86InterruptManager & instance()
void setInterruptGate(size_t nInterruptNumber, uintptr_t interruptHandler, bool bUserspace) INITIALISATION_ONLY
virtual bool registerInterruptHandlerDebugger(size_t nInterruptNumber, InterruptHandler *pHandler)
static InterruptManager & instance()
virtual bool registerInterruptHandler(size_t nInterruptNumber, InterruptHandler *pHandler)