Implement software interrupt dispatch table and secondary handler lookup
Some checks failed
Builds / ExectOS (amd64, debug) (push) Successful in 30s
Builds / ExectOS (i686, release) (push) Failing after 30s
Builds / ExectOS (i686, debug) (push) Failing after 39s
Builds / ExectOS (amd64, release) (push) Successful in 42s

This commit is contained in:
2026-04-08 20:13:35 +02:00
parent 4f65773aa9
commit 9ffb03217a
16 changed files with 358 additions and 17 deletions

View File

@@ -12,6 +12,7 @@
#include <xtdefs.h> #include <xtdefs.h>
#include <xtstruct.h> #include <xtstruct.h>
#include <xttypes.h> #include <xttypes.h>
#include ARCH_HEADER(xtstruct.h)
/* Control Register 0 constants */ /* Control Register 0 constants */
@@ -390,6 +391,9 @@ typedef enum _CPUID_REQUESTS
CPUID_GET_STANDARD7_FEATURES CPUID_GET_STANDARD7_FEATURES
} CPUID_REQUESTS, *PCPUID_REQUESTS; } CPUID_REQUESTS, *PCPUID_REQUESTS;
/* Interrupt handler */
typedef VOID (*PINTERRUPT_HANDLER)(PKTRAP_FRAME TrapFrame);
/* Processor identification information */ /* Processor identification information */
typedef struct _CPU_IDENTIFICATION typedef struct _CPU_IDENTIFICATION
{ {

View File

@@ -523,6 +523,7 @@ typedef struct _KPROCESSOR_BLOCK
KAFFINITY SetMember; KAFFINITY SetMember;
ULONG StallScaleFactor; ULONG StallScaleFactor;
UCHAR CpuNumber; UCHAR CpuNumber;
PINTERRUPT_HANDLER InterruptDispatchTable[256];
} KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK; } KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK;
/* Thread Environment Block (TEB) structure definition */ /* Thread Environment Block (TEB) structure definition */

View File

@@ -12,6 +12,7 @@
#include <xtdefs.h> #include <xtdefs.h>
#include <xtstruct.h> #include <xtstruct.h>
#include <xttypes.h> #include <xttypes.h>
#include ARCH_HEADER(xtstruct.h)
/* Control Register 0 constants */ /* Control Register 0 constants */
@@ -355,6 +356,9 @@ typedef enum _CPUID_REQUESTS
CPUID_GET_STANDARD7_FEATURES CPUID_GET_STANDARD7_FEATURES
} CPUID_REQUESTS, *PCPUID_REQUESTS; } CPUID_REQUESTS, *PCPUID_REQUESTS;
/* Interrupt handler */
typedef VOID (*PINTERRUPT_HANDLER)(PKTRAP_FRAME TrapFrame);
/* Processor identification information */ /* Processor identification information */
typedef struct _CPU_IDENTIFICATION typedef struct _CPU_IDENTIFICATION
{ {

View File

@@ -478,6 +478,7 @@ typedef struct _KPROCESSOR_BLOCK
KAFFINITY SetMember; KAFFINITY SetMember;
ULONG StallScaleFactor; ULONG StallScaleFactor;
UCHAR CpuNumber; UCHAR CpuNumber;
PINTERRUPT_HANDLER InterruptDispatchTable[256];
} KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK; } KPROCESSOR_BLOCK, *PKPROCESSOR_BLOCK;
/* Thread Environment Block (TEB) structure definition */ /* Thread Environment Block (TEB) structure definition */

View File

@@ -142,7 +142,7 @@ Dispatch\Type\Vector:
call ArDispatchTrap call ArDispatchTrap
.else .else
/* Pass to the interrupt dispatcher */ /* Pass to the interrupt dispatcher */
call ArDispatchTrap call ArDispatchInterrupt
.endif .endif
/* Restore the original trap frame stack pointer */ /* Restore the original trap frame stack pointer */

View File

@@ -29,3 +29,6 @@ KTSS AR::ProcSup::InitialTss;
/* Initial kernel NMI stack */ /* Initial kernel NMI stack */
UCHAR AR::ProcSup::NmiStack[KERNEL_STACK_SIZE] = {}; UCHAR AR::ProcSup::NmiStack[KERNEL_STACK_SIZE] = {};
/* Unhandled interrupt routine */
PINTERRUPT_HANDLER AR::Traps::UnhandledInterruptRoutine = NULLPTR;

View File

@@ -9,6 +9,44 @@
#include <xtos.hh> #include <xtos.hh>
/**
* 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. * Dispatches the trap provided by common trap handler.
* *
@@ -642,3 +680,21 @@ AR::Traps::InitializeSystemCallMsrs(VOID)
/* Enable system call extensions (SCE) in EFER MSR */ /* Enable system call extensions (SCE) in EFER MSR */
CpuFunc::WriteModelSpecificRegister(X86_MSR_EFER, CpuFunc::ReadModelSpecificRegister(X86_MSR_EFER) | X86_MSR_EFER_SCE); 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;
}

View File

@@ -136,7 +136,7 @@ Dispatch\Type\Vector:
call _ArDispatchTrap call _ArDispatchTrap
.else .else
/* Pass to the interrupt dispatcher */ /* Pass to the interrupt dispatcher */
call _ArDispatchTrap call _ArDispatchInterrupt
.endif .endif
/* Clean up the stack */ /* Clean up the stack */

View File

@@ -35,3 +35,6 @@ UCHAR AR::ProcSup::NmiStack[KERNEL_STACK_SIZE] = {};
/* NMI task gate */ /* NMI task gate */
UCHAR AR::ProcSup::NonMaskableInterruptTss[KTSS_IO_MAPS]; UCHAR AR::ProcSup::NonMaskableInterruptTss[KTSS_IO_MAPS];
/* Unhandled interrupt routine */
PINTERRUPT_HANDLER AR::Traps::UnhandledInterruptRoutine = NULLPTR;

View File

@@ -9,6 +9,44 @@
#include <xtos.hh> #include <xtos.hh>
/**
* 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. * 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"); DebugPrint(L"Handled Unexpected-Interrupt (0xFF)!\n");
KE::Crash::Panic(0xFF); 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;
}

View File

@@ -2,7 +2,7 @@
* PROJECT: ExectOS * PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory * COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/hl/amd64/irq.cc * FILE: xtoskrnl/hl/amd64/irq.cc
* DESCRIPTION: Interrupts support for amd64 architecture * DESCRIPTION: Interrupts support for AMD64 architecture
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org> * DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Aiken Harris <harraiken91@gmail.com> * Aiken Harris <harraiken91@gmail.com>
*/ */
@@ -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 * @param HalVector
* Supplies the HAL vector number. * Supplies the interrupt vector number.
* *
* @param Handler * @param Handler
* Supplies the new interrupt handler. * Supplies the pointer to the interrupt handler routine.
* *
* @return This routine does not return any value. * @return This routine does not return any value.
* *
@@ -25,7 +74,7 @@
*/ */
XTAPI XTAPI
VOID VOID
HL::Irq::SetInterruptHandler(IN ULONG Vector, HL::Irq::RegisterInterruptHandler(IN ULONG Vector,
IN PVOID Handler) IN PVOID Handler)
{ {
PKPROCESSOR_BLOCK ProcessorBlock; PKPROCESSOR_BLOCK ProcessorBlock;
@@ -42,3 +91,54 @@ HL::Irq::SetInterruptHandler(IN ULONG Vector,
KIDT_ACCESS_RING0, KIDT_ACCESS_RING0,
AMD64_INTERRUPT_GATE); 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);
}

View File

@@ -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 * @param HalVector
* Supplies the HAL vector number. * Supplies the interrupt vector number.
* *
* @param Handler * @param Handler
* Supplies the new interrupt handler. * Supplies the pointer to the interrupt handler routine.
* *
* @return This routine does not return any value. * @return This routine does not return any value.
* *
@@ -25,7 +72,7 @@
*/ */
XTAPI XTAPI
VOID VOID
HL::Irq::SetInterruptHandler(IN ULONG Vector, HL::Irq::RegisterInterruptHandler(IN ULONG Vector,
IN PVOID Handler) IN PVOID Handler)
{ {
PKPROCESSOR_BLOCK ProcessorBlock; PKPROCESSOR_BLOCK ProcessorBlock;
@@ -42,3 +89,54 @@ HL::Irq::SetInterruptHandler(IN ULONG Vector,
KIDT_ACCESS_RING0, KIDT_ACCESS_RING0,
I686_INTERRUPT_GATE); 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);
}

View File

@@ -223,7 +223,7 @@ HL::Pic::InitializeApic(VOID)
WriteApicRegister(APIC_LINT1, LvtRegister.Long); WriteApicRegister(APIC_LINT1, LvtRegister.Long);
/* Register interrupt handlers */ /* Register interrupt handlers */
HL::Irq::SetInterruptHandler(APIC_VECTOR_SPURIOUS, (PVOID)ArHandleSpuriousInterrupt); HL::Irq::RegisterInterruptHandler(APIC_VECTOR_SPURIOUS, (PVOID)ArHandleSpuriousInterrupt);
/* Clear any pre-existing errors */ /* Clear any pre-existing errors */
WriteApicRegister(APIC_ESR, 0); WriteApicRegister(APIC_ESR, 0);
@@ -307,7 +307,7 @@ HL::Pic::InitializeLegacyPic(VOID)
HL::IoPort::WritePort8(PIC2_DATA_PORT, 0xFF); HL::IoPort::WritePort8(PIC2_DATA_PORT, 0xFF);
/* Register interrupt handler */ /* Register interrupt handler */
HL::Irq::SetInterruptHandler(PIC1_VECTOR_SPURIOUS, (PVOID)ArHandleSpuriousInterrupt); HL::Irq::RegisterInterruptHandler(PIC1_VECTOR_SPURIOUS, (PVOID)ArHandleSpuriousInterrupt);
} }
/** /**

View File

@@ -17,9 +17,14 @@ namespace AR
{ {
class Traps class Traps
{ {
private:
STATIC PINTERRUPT_HANDLER UnhandledInterruptRoutine;
public: public:
STATIC XTCDECL VOID DispatchInterrupt(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("ArDispatchInterrupt");
STATIC XTCDECL VOID DispatchTrap(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("ArDispatchTrap"); STATIC XTCDECL VOID DispatchTrap(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("ArDispatchTrap");
STATIC XTCDECL VOID InitializeSystemCallMsrs(VOID); STATIC XTCDECL VOID InitializeSystemCallMsrs(VOID);
STATIC XTCDECL VOID SetUnhandledInterruptRoutine(PINTERRUPT_HANDLER Handler);
private: private:
STATIC XTCDECL VOID HandleSystemCall32(VOID); STATIC XTCDECL VOID HandleSystemCall32(VOID);

View File

@@ -17,8 +17,13 @@ namespace AR
{ {
class Traps class Traps
{ {
private:
STATIC PINTERRUPT_HANDLER UnhandledInterruptRoutine;
public: public:
STATIC XTCDECL VOID DispatchInterrupt(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("_ArDispatchInterrupt");
STATIC XTCDECL VOID DispatchTrap(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("_ArDispatchTrap"); STATIC XTCDECL VOID DispatchTrap(IN PKTRAP_FRAME TrapFrame) XTSYMBOL("_ArDispatchTrap");
STATIC XTCDECL VOID SetUnhandledInterruptRoutine(PINTERRUPT_HANDLER Handler);
private: private:
STATIC XTCDECL VOID HandleTrap00(IN PKTRAP_FRAME TrapFrame); STATIC XTCDECL VOID HandleTrap00(IN PKTRAP_FRAME TrapFrame);

View File

@@ -18,8 +18,13 @@ namespace HL
class Irq class Irq
{ {
public: public:
STATIC XTAPI VOID SetInterruptHandler(IN ULONG Vector, 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); IN PVOID Handler);
STATIC XTAPI VOID RegisterSystemInterruptHandler(IN ULONG Vector,
IN PINTERRUPT_HANDLER Handler);
}; };
} }