diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp index a26debf3ba4..5f3ecfc1293 100644 --- a/Kernel/Arch/i386/CPU.cpp +++ b/Kernel/Arch/i386/CPU.cpp @@ -58,7 +58,7 @@ extern FlatPtr end_of_ro_after_init; namespace Kernel { READONLY_AFTER_INIT static DescriptorTablePointer s_idtr; -READONLY_AFTER_INIT static Descriptor s_idt[256]; +READONLY_AFTER_INIT static IDTEntry s_idt[256]; static GenericInterruptHandler* s_interrupt_handler[GENERIC_INTERRUPT_HANDLERS_COUNT]; @@ -484,14 +484,18 @@ void unregister_generic_interrupt_handler(u8 interrupt_number, GenericInterruptH UNMAP_AFTER_INIT void register_interrupt_handler(u8 index, void (*handler)()) { - s_idt[index].low = 0x00080000 | LSW((FlatPtr)(handler)); - s_idt[index].high = ((FlatPtr)(handler)&0xffff0000) | 0x8e00; + // FIXME: Why is that with selector 8? + // FIXME: Is the Gate Type really required to be an Interupt + // FIXME: Whats up with that storage segment 0? + s_idt[index] = IDTEntry((FlatPtr)handler, 8, IDTEntryType::InterruptGate32, 0, 0); } UNMAP_AFTER_INIT void register_user_callable_interrupt_handler(u8 index, void (*handler)()) { - s_idt[index].low = 0x00080000 | LSW(((FlatPtr)handler)); - s_idt[index].high = ((FlatPtr)(handler)&0xffff0000) | 0xef00; + // FIXME: Why is that with selector 8? + // FIXME: Is the Gate Type really required to be a Trap + // FIXME: Whats up with that storage segment 0? + s_idt[index] = IDTEntry((FlatPtr)handler, 8, IDTEntryType::TrapGate32, 0, 3); } UNMAP_AFTER_INIT void flush_idt() diff --git a/Kernel/Arch/x86/DescriptorTable.h b/Kernel/Arch/x86/DescriptorTable.h index 990da3dbacd..48d060755ad 100644 --- a/Kernel/Arch/x86/DescriptorTable.h +++ b/Kernel/Arch/x86/DescriptorTable.h @@ -111,4 +111,69 @@ union [[gnu::packed]] Descriptor { } }; +enum class IDTEntryType { + TaskGate32 = 0b0101, + InterruptGate16 = 0b110, + TrapGate16 = 0b111, + InterruptGate32 = 0b1110, + TrapGate32 = 0b1111, +}; + +// Clang doesn't format this right due to the compiler magic +// clang-format off +struct [[gnu::packed]] IDTEntry +{ + + u16 offset_1; // offset bits 0..15 + u16 selector; // a code segment selector in GDT or LDT + + u8 zero; // unused, set to 0 (maybe used on amd64) + struct { + // FIXME: Is the order correct? + u8 gate_type : 4; + u8 storage_segment : 1; + u8 descriptor_privilege_level : 2; + u8 present : 1; + } type_attr; // type and attributes + u16 offset_2; // offset bits 16..31 +#if !ARCH(I386) +// we may need to switch those around? + u32 offset_3; + u32 zeros; +#endif + + IDTEntry() = default; + IDTEntry(FlatPtr callback, u16 selector_, IDTEntryType type, u8 storage_segment, u8 privilige_level) + : offset_1 { (u16)((FlatPtr)callback & 0xFFFF) } + , selector { selector_ } + , zero { 0 } + , type_attr { + .gate_type = (u8)type, + .storage_segment = storage_segment, + .descriptor_privilege_level = (u8)(privilige_level & 0b11), + .present = 1, + } + , offset_2 { (u16)((FlatPtr)callback >> 16) } +#if !ARCH(I386) + , offset_3 { (u32)(((FlatPtr)callback) >> 32) } + , zeros { 0 } +#endif + { + } + + u32 off() + { +#if ARCH(I386) + return (u32)offset_2 << 16 & (u32)offset_1; +#else + return (u64)offset_3 << 32 & (u64)offset_2 << 16 & (u64)offset_1; +#endif + } + IDTEntryType type() + { + return IDTEntryType(type_attr.gate_type); + } +}; +// clang-format on + }