From 36a74fd8d6e0713f5ff3d5cfadd1f3d13480e353 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 21 Jul 2023 15:14:52 +0200 Subject: [PATCH] kernel/x86_64: Provide an alternate kernel stack for exceptions This avoids stack-related triple faults, hopefully. Closes #33. --- kernel/src/arch/x86_64/init/GDT.cpp | 5 +++++ kernel/src/arch/x86_64/init/IDT.cpp | 9 +++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/kernel/src/arch/x86_64/init/GDT.cpp b/kernel/src/arch/x86_64/init/GDT.cpp index 54480a0e..d41cc50d 100644 --- a/kernel/src/arch/x86_64/init/GDT.cpp +++ b/kernel/src/arch/x86_64/init/GDT.cpp @@ -1,6 +1,8 @@ +#include "arch/MMU.h" #include "arch/x86_64/CPU.h" #include #include +#include #include struct [[gnu::packed]] GDTR @@ -75,10 +77,13 @@ static void set_tss_base(GDTEntry* tss1, HighGDTEntry* tss2, u64 addr) tss2->base_high = (u32)(addr >> 32); } +static u8 alternate_stack[ARCH_PAGE_SIZE * 4]; + static void setup_tss() { memset(&task_state_segment, 0, sizeof(TSS)); task_state_segment.iomap_base = sizeof(TSS); + task_state_segment.ist[0] = Stack { (u64)alternate_stack, ARCH_PAGE_SIZE * 4 }.top(); set_tss_base(&gdt.tss, &gdt.tss2, (u64)&task_state_segment); set_limit(&gdt.tss, sizeof(TSS) - 1); } diff --git a/kernel/src/arch/x86_64/init/IDT.cpp b/kernel/src/arch/x86_64/init/IDT.cpp index a226ff43..9fd41b1e 100644 --- a/kernel/src/arch/x86_64/init/IDT.cpp +++ b/kernel/src/arch/x86_64/init/IDT.cpp @@ -47,20 +47,21 @@ struct [[gnu::packed]] IDTR static_assert(sizeof(IDTR) == 10UL); -static void idt_add_handler(short num, void* handler, u8 type_attr) +static void idt_add_handler(short num, void* handler, u8 type_attr, u8 ist) { check(handler != nullptr); expect(num < 256, "IDT can only hold up to 256 entries"); IDTEntry* const entry_for_handler = &idt[num]; entry_for_handler->selector = 0x08; entry_for_handler->type_attr = type_attr; + entry_for_handler->ist = ist; entry_for_handler->set_offset((u64)handler); } #define INT(x) extern "C" void _isr##x() -#define TRAP(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_TrapGate) -#define IRQ(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_InterruptGate) -#define SYS(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_UserCallableInterruptGate) +#define TRAP(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_TrapGate, 1) +#define IRQ(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_InterruptGate, 0) +#define SYS(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_UserCallableInterruptGate, 0) INT(0); INT(1);