diff --git a/sdk/xtdk/amd64/artypes.h b/sdk/xtdk/amd64/artypes.h index 14d1667..14d01ce 100644 --- a/sdk/xtdk/amd64/artypes.h +++ b/sdk/xtdk/amd64/artypes.h @@ -12,6 +12,7 @@ #include #include #include +#include ARCH_HEADER(xtstruct.h) /* Control Register 0 constants */ @@ -390,6 +391,9 @@ typedef enum _CPUID_REQUESTS CPUID_GET_STANDARD7_FEATURES } CPUID_REQUESTS, *PCPUID_REQUESTS; +/* Interrupt handler */ +typedef VOID (*PINTERRUPT_HANDLER)(PKTRAP_FRAME TrapFrame); + /* Processor identification information */ typedef struct _CPU_IDENTIFICATION { diff --git a/sdk/xtdk/amd64/ketypes.h b/sdk/xtdk/amd64/ketypes.h index b68a06a..5ccd61d 100644 --- a/sdk/xtdk/amd64/ketypes.h +++ b/sdk/xtdk/amd64/ketypes.h @@ -523,6 +523,7 @@ typedef struct _KPROCESSOR_BLOCK KAFFINITY SetMember; ULONG StallScaleFactor; UCHAR CpuNumber; + PINTERRUPT_HANDLER InterruptDispatchTable[256]; } KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK; /* Thread Environment Block (TEB) structure definition */ diff --git a/sdk/xtdk/i686/artypes.h b/sdk/xtdk/i686/artypes.h index ebf4a99..7ef9f15 100644 --- a/sdk/xtdk/i686/artypes.h +++ b/sdk/xtdk/i686/artypes.h @@ -12,6 +12,7 @@ #include #include #include +#include ARCH_HEADER(xtstruct.h) /* Control Register 0 constants */ @@ -355,6 +356,9 @@ typedef enum _CPUID_REQUESTS CPUID_GET_STANDARD7_FEATURES } CPUID_REQUESTS, *PCPUID_REQUESTS; +/* Interrupt handler */ +typedef VOID (*PINTERRUPT_HANDLER)(PKTRAP_FRAME TrapFrame); + /* Processor identification information */ typedef struct _CPU_IDENTIFICATION { diff --git a/sdk/xtdk/i686/ketypes.h b/sdk/xtdk/i686/ketypes.h index b731a27..2264fc7 100644 --- a/sdk/xtdk/i686/ketypes.h +++ b/sdk/xtdk/i686/ketypes.h @@ -478,6 +478,7 @@ typedef struct _KPROCESSOR_BLOCK KAFFINITY SetMember; ULONG StallScaleFactor; UCHAR CpuNumber; + PINTERRUPT_HANDLER InterruptDispatchTable[256]; } KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK; /* Thread Environment Block (TEB) structure definition */ diff --git a/xtoskrnl/ar/amd64/archsup.S b/xtoskrnl/ar/amd64/archsup.S index ebaba97..29c1d05 100644 --- a/xtoskrnl/ar/amd64/archsup.S +++ b/xtoskrnl/ar/amd64/archsup.S @@ -142,7 +142,7 @@ Dispatch\Type\Vector: call ArDispatchTrap .else /* Pass to the interrupt dispatcher */ - call ArDispatchTrap + call ArDispatchInterrupt .endif /* Restore the original trap frame stack pointer */ diff --git a/xtoskrnl/ar/amd64/data.cc b/xtoskrnl/ar/amd64/data.cc index 388bdc2..d7397ce 100644 --- a/xtoskrnl/ar/amd64/data.cc +++ b/xtoskrnl/ar/amd64/data.cc @@ -29,3 +29,6 @@ KTSS AR::ProcSup::InitialTss; /* Initial kernel NMI stack */ UCHAR AR::ProcSup::NmiStack[KERNEL_STACK_SIZE] = {}; + +/* Unhandled interrupt routine */ +PINTERRUPT_HANDLER AR::Traps::UnhandledInterruptRoutine = NULLPTR; diff --git a/xtoskrnl/ar/amd64/traps.cc b/xtoskrnl/ar/amd64/traps.cc index dc9bed6..5e748cd 100644 --- a/xtoskrnl/ar/amd64/traps.cc +++ b/xtoskrnl/ar/amd64/traps.cc @@ -9,6 +9,44 @@ #include +/** + * Dispatches the interrupt provided by common interrupt handler. + * + * @param TrapFrame + * Supplies a kernel trap frame pushed by common interrupt handler on the stack. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +AR::Traps::DispatchInterrupt(IN PKTRAP_FRAME TrapFrame) +{ + PINTERRUPT_HANDLER Handler; + + /* Read the handler pointer from the CPU's interrupt dispatch table */ + Handler = (PINTERRUPT_HANDLER)AR::CpuFunc::ReadGSQuadWord(FIELD_OFFSET(KPROCESSOR_BLOCK, InterruptDispatchTable) + + (TrapFrame->Vector * sizeof(PINTERRUPT_HANDLER))); + + /* Check if the interrupt has a handler registered */ + if(Handler != NULLPTR) + { + /* Call the handler */ + Handler(TrapFrame); + } + else if(UnhandledInterruptRoutine != NULLPTR) + { + /* Call the unhandled interrupt routine */ + UnhandledInterruptRoutine(TrapFrame); + } + else + { + /* Dispatcher not initialized, print a debug message */ + DebugPrint(L"ERROR: Caught unhandled interrupt: 0x%.2llX\n", TrapFrame->Vector); + } +} + /** * Dispatches the trap provided by common trap handler. * @@ -642,3 +680,21 @@ AR::Traps::InitializeSystemCallMsrs(VOID) /* Enable system call extensions (SCE) in EFER MSR */ CpuFunc::WriteModelSpecificRegister(X86_MSR_EFER, CpuFunc::ReadModelSpecificRegister(X86_MSR_EFER) | X86_MSR_EFER_SCE); } + +/** + * Sets the unhandled interrupt routine used for vectors that have no handler registered. + * + * @param Handler + * Supplies the pointer to the interrupt handler routine. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +AR::Traps::SetUnhandledInterruptRoutine(PINTERRUPT_HANDLER Handler) +{ + /* Set the unhandled interrupt routine */ + UnhandledInterruptRoutine = Handler; +} diff --git a/xtoskrnl/ar/i686/archsup.S b/xtoskrnl/ar/i686/archsup.S index 853b436..aa24d5c 100644 --- a/xtoskrnl/ar/i686/archsup.S +++ b/xtoskrnl/ar/i686/archsup.S @@ -136,7 +136,7 @@ Dispatch\Type\Vector: call _ArDispatchTrap .else /* Pass to the interrupt dispatcher */ - call _ArDispatchTrap + call _ArDispatchInterrupt .endif /* Clean up the stack */ diff --git a/xtoskrnl/ar/i686/data.cc b/xtoskrnl/ar/i686/data.cc index c8599e4..df2419b 100644 --- a/xtoskrnl/ar/i686/data.cc +++ b/xtoskrnl/ar/i686/data.cc @@ -35,3 +35,6 @@ UCHAR AR::ProcSup::NmiStack[KERNEL_STACK_SIZE] = {}; /* NMI task gate */ UCHAR AR::ProcSup::NonMaskableInterruptTss[KTSS_IO_MAPS]; + +/* Unhandled interrupt routine */ +PINTERRUPT_HANDLER AR::Traps::UnhandledInterruptRoutine = NULLPTR; diff --git a/xtoskrnl/ar/i686/traps.cc b/xtoskrnl/ar/i686/traps.cc index 2f2bfc7..2dda051 100644 --- a/xtoskrnl/ar/i686/traps.cc +++ b/xtoskrnl/ar/i686/traps.cc @@ -9,6 +9,44 @@ #include +/** + * Dispatches the interrupt provided by common interrupt handler. + * + * @param TrapFrame + * Supplies a kernel trap frame pushed by common interrupt handler on the stack. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +AR::Traps::DispatchInterrupt(IN PKTRAP_FRAME TrapFrame) +{ + PINTERRUPT_HANDLER Handler; + + /* Read the handler pointer from the CPU's interrupt dispatch table */ + Handler = (PINTERRUPT_HANDLER)AR::CpuFunc::ReadFSDualWord(FIELD_OFFSET(KPROCESSOR_BLOCK, InterruptDispatchTable) + + (TrapFrame->Vector * sizeof(PINTERRUPT_HANDLER))); + + /* Check if the interrupt has a handler registered */ + if(Handler != NULLPTR) + { + /* Call the handler */ + Handler(TrapFrame); + } + else if(UnhandledInterruptRoutine != NULLPTR) + { + /* Call the unhandled interrupt routine */ + UnhandledInterruptRoutine(TrapFrame); + } + else + { + /* Dispatcher not initialized, print a debug message */ + DebugPrint(L"ERROR: Caught unhandled interrupt: 0x%.2lX\n", TrapFrame->Vector); + } +} + /** * Dispatches the trap provided by common trap handler. * @@ -589,3 +627,21 @@ AR::Traps::HandleTrapFF(IN PKTRAP_FRAME TrapFrame) DebugPrint(L"Handled Unexpected-Interrupt (0xFF)!\n"); KE::Crash::Panic(0xFF); } + +/** + * Sets the unhandled interrupt routine used for vectors that have no handler registered. + * + * @param Handler + * Supplies the pointer to the interrupt handler routine. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +AR::Traps::SetUnhandledInterruptRoutine(PINTERRUPT_HANDLER Handler) +{ + /* Set the unhandled interrupt routine */ + UnhandledInterruptRoutine = Handler; +} diff --git a/xtoskrnl/hl/amd64/irq.cc b/xtoskrnl/hl/amd64/irq.cc index c071987..5d3ffdb 100644 --- a/xtoskrnl/hl/amd64/irq.cc +++ b/xtoskrnl/hl/amd64/irq.cc @@ -2,7 +2,7 @@ * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/amd64/irq.cc - * DESCRIPTION: Interrupts support for amd64 architecture + * DESCRIPTION: Interrupts support for AMD64 architecture * DEVELOPERS: Rafal Kupiec * Aiken Harris */ @@ -11,13 +11,62 @@ /** - * Sets new interrupt handler for the existing IDT entry. + * Returns the registered interrupt handler for the specified IDT vector. + * + * @param Vector + * Supplies the interrupt vector number. + * + * @return This routine returns the pointer to the IDT interrupt handler routine. + * + * @since XT 1.0 + */ +XTAPI +PVOID +HL::Irq::QueryInterruptHandler(IN ULONG Vector) +{ + PKPROCESSOR_BLOCK ProcessorBlock; + PKIDTENTRY IdtEntry; + + /* Get current processor block and IDT entry */ + ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); + IdtEntry = &ProcessorBlock->IdtBase[Vector]; + + /* Return address of the interrupt handler */ + return (PVOID)((ULONGLONG)IdtEntry->OffsetHigh << 32 | + (ULONGLONG)IdtEntry->OffsetMiddle << 16 | + (ULONGLONG)IdtEntry->OffsetLow); +} + +/** + * Returns the registered interrupt handler for the specified vector. + * + * @param Vector + * Supplies the interrupt vector number. + * + * @return This routine returns the pointer to the interrupt handler routine. + * + * @since XT 1.0 + */ +XTAPI +PVOID +HL::Irq::QuerySystemInterruptHandler(IN ULONG Vector) +{ + PKPROCESSOR_BLOCK ProcessorBlock; + + /* Get current processor block */ + ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); + + return (PVOID)ProcessorBlock->InterruptDispatchTable[Vector]; +} + +/** + * Registers new interrupt handler for the existing IDT entry. * * @param HalVector - * Supplies the HAL vector number. + * Supplies the interrupt vector number. * * @param Handler - * Supplies the new interrupt handler. + * Supplies the pointer to the interrupt handler routine. * * @return This routine does not return any value. * @@ -25,8 +74,8 @@ */ XTAPI VOID -HL::Irq::SetInterruptHandler(IN ULONG Vector, - IN PVOID Handler) +HL::Irq::RegisterInterruptHandler(IN ULONG Vector, + IN PVOID Handler) { PKPROCESSOR_BLOCK ProcessorBlock; @@ -42,3 +91,54 @@ HL::Irq::SetInterruptHandler(IN ULONG Vector, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE); } + +/** + * Registers the interrupt handler for the specified vector. + * + * @param HalVector + * Supplies the interrupt vector number. + * + * @param Handler + * Supplies the pointer to the interrupt handler routine. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +HL::Irq::RegisterSystemInterruptHandler(IN ULONG Vector, + IN PINTERRUPT_HANDLER Handler) +{ + PKPROCESSOR_BLOCK ProcessorBlock; + + /* Get current processor block */ + ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); + + /* Update interrupt handler in the processor's interrupt dispatch table */ + ProcessorBlock->InterruptDispatchTable[Vector] = Handler; +} + +/** + * Handles unexpected or unmapped system interrupts. + * + * @param TrapFrame + * Supplies a kernel trap frame pushed by common interrupt handler. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +HL::Irq::HandleUnexpectedInterrupt(IN PKTRAP_FRAME TrapFrame) +{ + UNIMPLEMENTED; + + /* Disable interrupts */ + AR::CpuFunc::ClearInterruptFlag(); + + /* Print debug message and raise kernel panic */ + DebugPrint(L"ERROR: Caught unexpected interrupt (0x%.2llX)!\n", TrapFrame->Vector); + KE::Crash::Panic(0x47, TrapFrame->Vector, 0, 0, 0); +} diff --git a/xtoskrnl/hl/i686/irq.cc b/xtoskrnl/hl/i686/irq.cc index cd658ec..b7111ec 100644 --- a/xtoskrnl/hl/i686/irq.cc +++ b/xtoskrnl/hl/i686/irq.cc @@ -11,13 +11,60 @@ /** - * Sets new interrupt handler for the existing IDT entry. + * Returns the registered interrupt handler for the specified IDT vector. + * + * @param Vector + * Supplies the interrupt vector number. + * + * @return This routine returns the pointer to the IDT interrupt handler routine. + * + * @since XT 1.0 + */ +XTAPI +PVOID +HL::Irq::QueryInterruptHandler(IN ULONG Vector) +{ + PKPROCESSOR_BLOCK ProcessorBlock; + PKIDTENTRY IdtEntry; + + /* Get current processor block and IDT entry */ + ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); + IdtEntry = &ProcessorBlock->IdtBase[Vector]; + + /* Return address of the interrupt handler */ + return (PVOID)(((IdtEntry->ExtendedOffset << 16) & 0xFFFF0000) | (IdtEntry->Offset & 0xFFFF)); +} + +/** + * Returns the registered interrupt handler for the specified vector. + * + * @param Vector + * Supplies the interrupt vector number. + * + * @return This routine returns the pointer to the interrupt handler routine. + * + * @since XT 1.0 + */ +XTAPI +PVOID +HL::Irq::QuerySystemInterruptHandler(IN ULONG Vector) +{ + PKPROCESSOR_BLOCK ProcessorBlock; + + /* Get current processor block */ + ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); + + return (PVOID)ProcessorBlock->InterruptDispatchTable[Vector]; +} + +/** + * Registers new interrupt handler for the existing IDT entry. * * @param HalVector - * Supplies the HAL vector number. + * Supplies the interrupt vector number. * * @param Handler - * Supplies the new interrupt handler. + * Supplies the pointer to the interrupt handler routine. * * @return This routine does not return any value. * @@ -25,8 +72,8 @@ */ XTAPI VOID -HL::Irq::SetInterruptHandler(IN ULONG Vector, - IN PVOID Handler) +HL::Irq::RegisterInterruptHandler(IN ULONG Vector, + IN PVOID Handler) { PKPROCESSOR_BLOCK ProcessorBlock; @@ -42,3 +89,54 @@ HL::Irq::SetInterruptHandler(IN ULONG Vector, KIDT_ACCESS_RING0, I686_INTERRUPT_GATE); } + +/** + * Registers the interrupt handler for the specified vector. + * + * @param HalVector + * Supplies the interrupt vector number. + * + * @param Handler + * Supplies the pointer to the interrupt handler routine. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +HL::Irq::RegisterSystemInterruptHandler(IN ULONG Vector, + IN PINTERRUPT_HANDLER Handler) +{ + PKPROCESSOR_BLOCK ProcessorBlock; + + /* Get current processor block */ + ProcessorBlock = KE::Processor::GetCurrentProcessorBlock(); + + /* Update interrupt handler in the processor's interrupt dispatch table */ + ProcessorBlock->InterruptDispatchTable[Vector] = Handler; +} + +/** + * Handles unexpected or unmapped system interrupts. + * + * @param TrapFrame + * Supplies a kernel trap frame pushed by common interrupt handler. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +HL::Irq::HandleUnexpectedInterrupt(IN PKTRAP_FRAME TrapFrame) +{ + UNIMPLEMENTED; + + /* Disable interrupts */ + AR::CpuFunc::ClearInterruptFlag(); + + /* Print debug message and raise kernel panic */ + DebugPrint(L"ERROR: Caught unexpected interrupt (0x%.2lX)!\n", TrapFrame->Vector); + KE::Crash::Panic(0x47, TrapFrame->Vector, 0, 0, 0); +} diff --git a/xtoskrnl/hl/x86/pic.cc b/xtoskrnl/hl/x86/pic.cc index 4031034..d20abb1 100644 --- a/xtoskrnl/hl/x86/pic.cc +++ b/xtoskrnl/hl/x86/pic.cc @@ -223,7 +223,7 @@ HL::Pic::InitializeApic(VOID) WriteApicRegister(APIC_LINT1, LvtRegister.Long); /* Register interrupt handlers */ - HL::Irq::SetInterruptHandler(APIC_VECTOR_SPURIOUS, (PVOID)ArHandleSpuriousInterrupt); + HL::Irq::RegisterInterruptHandler(APIC_VECTOR_SPURIOUS, (PVOID)ArHandleSpuriousInterrupt); /* Clear any pre-existing errors */ WriteApicRegister(APIC_ESR, 0); @@ -307,7 +307,7 @@ HL::Pic::InitializeLegacyPic(VOID) HL::IoPort::WritePort8(PIC2_DATA_PORT, 0xFF); /* Register interrupt handler */ - HL::Irq::SetInterruptHandler(PIC1_VECTOR_SPURIOUS, (PVOID)ArHandleSpuriousInterrupt); + HL::Irq::RegisterInterruptHandler(PIC1_VECTOR_SPURIOUS, (PVOID)ArHandleSpuriousInterrupt); } /** diff --git a/xtoskrnl/includes/ar/amd64/traps.hh b/xtoskrnl/includes/ar/amd64/traps.hh index cfd55d8..2481ea8 100644 --- a/xtoskrnl/includes/ar/amd64/traps.hh +++ b/xtoskrnl/includes/ar/amd64/traps.hh @@ -17,9 +17,14 @@ namespace AR { class Traps { + private: + STATIC PINTERRUPT_HANDLER UnhandledInterruptRoutine; + public: + STATIC XTCDECL VOID DispatchInterrupt(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("ArDispatchInterrupt"); STATIC XTCDECL VOID DispatchTrap(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("ArDispatchTrap"); STATIC XTCDECL VOID InitializeSystemCallMsrs(VOID); + STATIC XTCDECL VOID SetUnhandledInterruptRoutine(PINTERRUPT_HANDLER Handler); private: STATIC XTCDECL VOID HandleSystemCall32(VOID); diff --git a/xtoskrnl/includes/ar/i686/traps.hh b/xtoskrnl/includes/ar/i686/traps.hh index 5854f99..a497c56 100644 --- a/xtoskrnl/includes/ar/i686/traps.hh +++ b/xtoskrnl/includes/ar/i686/traps.hh @@ -17,8 +17,13 @@ namespace AR { class Traps { + private: + STATIC PINTERRUPT_HANDLER UnhandledInterruptRoutine; + public: + STATIC XTCDECL VOID DispatchInterrupt(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("_ArDispatchInterrupt"); STATIC XTCDECL VOID DispatchTrap(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("_ArDispatchTrap"); + STATIC XTCDECL VOID SetUnhandledInterruptRoutine(PINTERRUPT_HANDLER Handler); private: STATIC XTCDECL VOID HandleTrap00(IN PKTRAP_FRAME TrapFrame); diff --git a/xtoskrnl/includes/hl/irq.hh b/xtoskrnl/includes/hl/irq.hh index ac37a22..c1398ce 100644 --- a/xtoskrnl/includes/hl/irq.hh +++ b/xtoskrnl/includes/hl/irq.hh @@ -18,8 +18,13 @@ namespace HL class Irq { public: - STATIC XTAPI VOID SetInterruptHandler(IN ULONG Vector, - IN PVOID Handler); + STATIC XTAPI PVOID QueryInterruptHandler(IN ULONG Vector); + STATIC XTAPI PVOID QuerySystemInterruptHandler(IN ULONG Vector); + STATIC XTCDECL VOID HandleUnexpectedInterrupt(IN PKTRAP_FRAME TrapFrame); + STATIC XTAPI VOID RegisterInterruptHandler(IN ULONG Vector, + IN PVOID Handler); + STATIC XTAPI VOID RegisterSystemInterruptHandler(IN ULONG Vector, + IN PINTERRUPT_HANDLER Handler); }; }