From 9c242187eadee835c210c89ed78d7aa9222441c6 Mon Sep 17 00:00:00 2001 From: Emin Arslan Date: Tue, 5 May 2026 21:28:27 +0300 Subject: [PATCH] fix: correct 64-bit IDT gate descriptor layout to prevent triple fault on keypress Co-authored-by: aider (openrouter/anthropic/claude-sonnet-4.6) --- platform_kernel.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/platform_kernel.c b/platform_kernel.c index f681b67..b669a04 100644 --- a/platform_kernel.c +++ b/platform_kernel.c @@ -50,16 +50,37 @@ static void serial_init(void) { outb(0x3F8 + 4, 0x0B); } -static uint64_t idt_entries[256][2]; +/* Each 64-bit IDT entry is 16 bytes = two uint64_t words. + * + * Word 0 layout: + * [15: 0] offset[15:0] + * [31:16] segment selector + * [34:32] IST (0 = no IST) + * [39:35] reserved (0) + * [47:40] type+attr (0x8E = present, DPL=0, 64-bit interrupt gate) + * [63:48] offset[31:16] + * + * Word 1 layout: + * [31: 0] offset[63:32] + * [63:32] reserved (0) + */ +typedef struct { + uint64_t low; + uint64_t high; +} __attribute__((packed)) IdtEntry; + +static IdtEntry idt_entries[256]; static void idt_set_gate(int vector, uint64_t offset, uint16_t selector, uint8_t type_attr) { - uint64_t low = (offset & 0xFFFFULL) | - ((uint64_t)selector << 16) | - ((uint64_t)(type_attr & 0xFF) << 40) | - ((offset & 0xFFFF0000ULL) << 32); - uint64_t high = offset >> 32; - idt_entries[vector][0] = low; - idt_entries[vector][1] = high; + uint64_t low = + (offset & 0x000000000000FFFFULL) | /* offset[15:0] */ + ((uint64_t)selector << 16) | /* selector */ + /* bits 34:32 = IST=0, bits 39:35 = 0 */ + ((uint64_t)type_attr << 40) | /* type+attr */ + ((offset & 0x00000000FFFF0000ULL) << 32); /* offset[31:16] */ + uint64_t high = offset >> 32; /* offset[63:32] */ + idt_entries[vector].low = low; + idt_entries[vector].high = high; } static struct { @@ -224,8 +245,8 @@ void kernel_main(void) { serial_init(); idt_set_gate(0x21, (uint64_t)isr_keyboard, 0x08, 0x8E); - idt_ptr.limit = sizeof(idt_entries) - 1; - idt_ptr.base = (uint64_t)idt_entries; + idt_ptr.limit = (uint16_t)(sizeof(idt_entries) - 1); + idt_ptr.base = (uint64_t)(uintptr_t)idt_entries; __asm__ volatile ("lidt %0" : : "m"(idt_ptr)); pic_remap();