From b6d4a1c963f2c9b9002675db417a0e5b149a2377 Mon Sep 17 00:00:00 2001 From: "Chloe M." Date: Tue, 23 Jun 2026 19:11:14 +0000 Subject: [PATCH] stos/amd64: cpu: Add exception handling groundwork Signed-off-by: Chloe M. --- paw/stos/arch/amd64/cpu/idt.S | 87 ++++++++++++++ paw/stos/arch/amd64/cpu/init.c | 9 ++ paw/stos/arch/amd64/cpu/trap.c | 49 ++++++++ paw/stos/arch/amd64/cpu/vector.S | 196 +++++++++++++++++++++++++++++++ paw/stos/head/arch/amd64/idt.h | 17 +++ paw/stos/head/arch/amd64/trap.h | 38 ++++++ paw/stos/head/ke/knot.h | 4 +- paw/stos/ke/knot.c | 3 +- 8 files changed, 401 insertions(+), 2 deletions(-) create mode 100644 paw/stos/arch/amd64/cpu/idt.S create mode 100644 paw/stos/arch/amd64/cpu/trap.c create mode 100644 paw/stos/arch/amd64/cpu/vector.S create mode 100644 paw/stos/head/arch/amd64/trap.h diff --git a/paw/stos/arch/amd64/cpu/idt.S b/paw/stos/arch/amd64/cpu/idt.S new file mode 100644 index 0000000..e75982d --- /dev/null +++ b/paw/stos/arch/amd64/cpu/idt.S @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: Interrupt descriptor table + * Author: Chloe M. + */ + +#include +#include + + #define IDT_VECTOR_SHIFT 4 + + .text + .globl MdIdtSetEntry +MdIdtSetEntry: + /* + * Set an IDT entry + * + * @[RDI]: Interrupt vector of entry to set + * @[RSI]: Interrupt service routine base + * @[RDX]: Interrupt gate type + * @[RCX]: Interrupt stack table index + */ + + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + + shl $IDT_VECTOR_SHIFT, %rdi /* Scale the vector by IDT size */ + lea IdtTable(%rip), %rbx /* IDT base -> RBX */ + add %rdi, %rbx /* Obtain the entry */ + + mov %rsi, %rax /* ISR base -> RAX */ + and $0xFFFF, %rax /* Obtain ISR[15:0] */ + mov %ax, 0(%rbx) /* Set the ISR base */ + + movw $GDT_KCODE, 2(%rbx) /* Set the code selector */ + xor %rax, %rax /* Clear out RAX */ + and $0x3, %cl /* Ensure we only have 3 bits */ + or %cl, %al /* Merge it with RAX */ + + and $0xF, %rdx /* Ensure we only get 4 bits */ + shl $8, %rdx /* Prepare to merge it */ + or %rdx, %rax /* Merge it */ + or $1<<15, %rax /* Mark as present */ + + cmpb $IDT_USER_GATE, %dl /* Is this DPL3? */ + jne 1f /* No, skip .Dpl3 */ + +.Dpl3: + or $3<<13, %rax /* Set DPL 3 */ +1: mov %rsi, %r12 /* Copy ISR base to R12 */ + shr $16, %r12 /* Obtain the middle 16-bits */ + and $0xFFFF, %r12 /* Isolate it */ + shl $16, %r12 /* Shift it back up */ + or %r12, %rax /* Merge it */ + + mov %rax, 4(%rbx) /* Set the second dword */ + mov %rsi, %r12 /* Copy ISR base to R12 */ + shr $32, %r12 /* Isolate the upper dword */ + mov %r12, 8(%rbx) /* Write it */ + + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + retq + + .globl MdIdtLoad +MdIdtLoad: + lea Idtr(%rip), %rax + lidt (%rax) + retq + + .section .data +Idtr: + .word 4095 + .quad IdtTable + + .section .bss + .align 8 +IdtTable: + .skip 4096, 0 diff --git a/paw/stos/arch/amd64/cpu/init.c b/paw/stos/arch/amd64/cpu/init.c index 78eafe5..7c16d45 100644 --- a/paw/stos/arch/amd64/cpu/init.c +++ b/paw/stos/arch/amd64/cpu/init.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #define DTRACE(Fmt, ...) \ @@ -31,6 +32,9 @@ static const CHAR *ProcessorType[] = { [PROCESSOR_DUAL] = "Intel P5 dual processor" }; +/* From cpu/vector.S */ +extern VOID MdVectorInit(VOID); + /* * Called by ProcessorIdentify() */ @@ -113,4 +117,9 @@ HalKpcrP1Init(KPCR *Kpcr) Mcb = &Kpcr->Mcb; ProcessorIdentify(Mcb); + + /* Load the IDT */ + MdVectorInit(); + MdIdtLoad(); + } diff --git a/paw/stos/arch/amd64/cpu/trap.c b/paw/stos/arch/amd64/cpu/trap.c new file mode 100644 index 0000000..aa07e40 --- /dev/null +++ b/paw/stos/arch/amd64/cpu/trap.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: Trap handling + * Author: Chloe M. + */ + +#include +#include +#include + +/* Used to convert trap codes to strings */ +static const char *TrapTab[] = { + [TRAP_DIVERR] = "divide error", + [TRAP_DBG] = "debug exception", + [TRAP_NMI] = "non-maskable interrupt", + [TRAP_BP] = "breakpoint", + [TRAP_OF] = "overflow", + [TRAP_BR] = "bound range exceeded", + [TRAP_UD] = "undefined opcode", + [TRAP_NM] = "no math coprocessor", + [TRAP_DF] = "double fault", + [TRAP_CPR] = "reserved exception", + [TRAP_TS] = "invalid TSS", + [TRAP_NP] = "segment not present", + [TRAP_SS] = "stack segment fault", + [TRAP_GP] = "general protection fault", + [TRAP_PF] = "page fault" +}; + + +VOID +MdTrapDispatch(TRAP_FRAME *Frame) +{ + if (Frame == NULL) { + return; + } + + if (Frame->Vector >= NELEM(TrapTab)) { + KeKnot( + KNOT_EXCEPTION, + "Fatal unknown vector %x\n", + Frame->Vector + ); + } + + KeKnot(KNOT_EXCEPTION, "Fatal %s\n", TrapTab[Frame->Vector]); +} diff --git a/paw/stos/arch/amd64/cpu/vector.S b/paw/stos/arch/amd64/cpu/vector.S new file mode 100644 index 0000000..9b957ac --- /dev/null +++ b/paw/stos/arch/amd64/cpu/vector.S @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: Interrupt Vector entries + * Author: Chloe M. + */ + +#include +#include +#include + + .macro SetTrap, Vector, Isr, Ist + mov $\Vector, %rdi + lea \Isr(%rip), %rsi + mov $IDT_TRAP_GATE, %rdx + mov $\Ist, %rcx + call MdIdtSetEntry + .endm + + .text + .globl MdVectorInit +MdVectorInit: + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + push %rbp + + SetTrap 0x00, DivErr, 0 + SetTrap 0x01, DebugExcept, 0 + SetTrap 0x02, Nmi, 0 + SetTrap 0x03, Breakpoint, 0 + SetTrap 0x04, Overflow, 0 + SetTrap 0x05, BoundRange, 0 + SetTrap 0x06, InvalidOpcode, 0 + SetTrap 0x07, NoCoproc, 0 + SetTrap 0x08, DoubleFault, 0 + SetTrap 0x0A, InvalidTss, 0 + SetTrap 0x0B, SegNp, 0 + SetTrap 0x0C, StackSegFault, 0 + SetTrap 0x0D, Gpf, 0 + SetTrap 0x0E, PageFault, 0 + + pop %rbp + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + retq + + .text + .extern MdTrapDispatch + .align 8 +DivErr: + KFENCE + PushFrame 0x00 + mov %rsp, %rdi + call MdTrapDispatch + KFENCE +1: cli + hlt + jmp 1b + +DebugExcept: + KFENCE + PushFrame 0x1 + mov %rsp, %rdi + call MdTrapDispatch + KFENCE +1: cli + hlt + jmp 1b + +Nmi: + KFENCE + PushFrame 0x2 + mov %rsp, %rdi + call MdTrapDispatch + KFENCE +1: cli + hlt + jmp 1b + +Breakpoint: + KFENCE + PushFrame 0x3 + mov %rsp, %rdi + call MdTrapDispatch + KFENCE +1: cli + hlt + jmp 1b + +Overflow: + KFENCE + PushFrame 0x4 + mov %rsp, %rdi + call MdTrapDispatch + KFENCE +1: cli + hlt + jmp 1b + +BoundRange: + KFENCE + PushFrame 0x5 + mov %rsp, %rdi + call MdTrapDispatch + KFENCE +1: cli + hlt + jmp 1b + +InvalidOpcode: + KFENCE + PushFrame 0x6 + mov %rsp, %rdi + call MdTrapDispatch + KFENCE +1: cli + hlt + jmp 1b + +NoCoproc: + KFENCE + PushFrame 0x7 + mov %rsp, %rdi + call MdTrapDispatch + KFENCE +1: cli + hlt + jmp 1b + +DoubleFault: + KFENCE_EC + PushFrame 0x8 + mov %rsp, %rdi + call MdTrapDispatch + KFENCE_EC +1: cli + hlt + jmp 1b + +InvalidTss: + KFENCE_EC + PushFrame 0xA + mov %rsp, %rdi + call MdTrapDispatch + KFENCE_EC +1: cli + hlt + jmp 1b + +SegNp: + KFENCE_EC + PushFrame 0xB + mov %rsp, %rdi + call MdTrapDispatch + KFENCE_EC +1: cli + hlt + jmp 1b + +StackSegFault: + KFENCE_EC + PushFrame 0xC + mov %rsp, %rdi + call MdTrapDispatch + KFENCE_EC +1: cli + hlt + jmp 1b + +Gpf: + KFENCE_EC + PushFrame 0xD + mov %rsp, %rdi + call MdTrapDispatch + KFENCE_EC +1: cli + hlt + jmp 1b + +PageFault: + KFENCE_EC + PushFrame 0xE + mov %rsp, %rdi + call MdTrapDispatch + KFENCE_EC +1: cli + hlt + jmp 1b + hlt diff --git a/paw/stos/head/arch/amd64/idt.h b/paw/stos/head/arch/amd64/idt.h index 753e776..a940c2f 100644 --- a/paw/stos/head/arch/amd64/idt.h +++ b/paw/stos/head/arch/amd64/idt.h @@ -13,4 +13,21 @@ #define IDT_TRAP_GATE 0x8F #define IDT_USER_GATE 0xEE +#ifndef __ASSEMBLER__ +/* + * Set an IDT entry + * + * @Vector: Interrupt vector to set + * @IsrBase: ISR base to set + * @Type: Gate type + * @Ist: Interrupt stack table index + */ +VOID MdIdtSetEntry(UCHAR Vector, UPTR IsrBase, UCHAR Type, UCHAR Ist); + +/* + * Load the IDT + */ +VOID MdIdtLoad(VOID); + +#endif /* !__ASSEMBLER__ */ #endif /* !_MACHINE_IDT_H_ */ diff --git a/paw/stos/head/arch/amd64/trap.h b/paw/stos/head/arch/amd64/trap.h new file mode 100644 index 0000000..5663823 --- /dev/null +++ b/paw/stos/head/arch/amd64/trap.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: Trap handling + * Author: Chloe M. + */ + +#ifndef _MACHINE_TRAP_H_ +#define _MACHINE_TRAP_H_ 1 + +#include +#include + +#define TRAP_DIVERR 0x00 /* Divide error */ +#define TRAP_DBG 0x01 /* Debug exception */ +#define TRAP_NMI 0x02 /* Non-maskable interrupt */ +#define TRAP_BP 0x03 /* Breakpoint */ +#define TRAP_OF 0x04 /* Overflow */ +#define TRAP_BR 0x05 /* BOUND range exceeded */ +#define TRAP_UD 0x06 /* Undefined opcode */ +#define TRAP_NM 0x07 /* No math coprocessor */ +#define TRAP_DF 0x08 /* Double fault */ +#define TRAP_CPR 0x09 /* Reserved */ +#define TRAP_TS 0x0A /* Invalid TSS */ +#define TRAP_NP 0x0B /* Segment not present */ +#define TRAP_SS 0x0C /* Stack segment fault */ +#define TRAP_GP 0x0D /* General protection fault */ +#define TRAP_PF 0x0E /* Page fault */ + +/* + * Used for dispatching traps + * + * @Frame: Trap-frame associated with trap + */ +VOID MdTrapDispatch(TRAP_FRAME *Frame); + +#endif /* !_MACHINE_TRAP_H_ */ diff --git a/paw/stos/head/ke/knot.h b/paw/stos/head/ke/knot.h index bb6e019..3d47316 100644 --- a/paw/stos/head/ke/knot.h +++ b/paw/stos/head/ke/knot.h @@ -18,12 +18,14 @@ * @KNOT_UNBOUND_RSRC: Unbounded resource * @KNOT_BAD_BOOT_PROTO: Bad boot protocol * @KNOT_OOM: Fatal out of memory + * @KNOT_EXCEPTION: Fatal exception */ typedef enum { KNOT_MISC, KNOT_UNBOUND_RSRC, KNOT_BAD_BOOT_PROTO, - KNOT_OOM + KNOT_OOM, + KNOT_EXCEPTION } KNOT_REASON; /* diff --git a/paw/stos/ke/knot.c b/paw/stos/ke/knot.c index b88d11a..ca5513f 100644 --- a/paw/stos/ke/knot.c +++ b/paw/stos/ke/knot.c @@ -21,7 +21,8 @@ static const CHAR *ReasonTable[] = { [KNOT_MISC] = "unspecified reason", [KNOT_UNBOUND_RSRC] = "unbounded resource", [KNOT_BAD_BOOT_PROTO] = "bad boot protocol", - [KNOT_OOM] = "out of memory" + [KNOT_OOM] = "out of memory", + [KNOT_EXCEPTION] = "fatal exception" }; /* Globals */