stos/amd64: cpu: Add exception handling groundwork

Signed-off-by: Chloe M. <chloe@mensia.org>
This commit is contained in:
Chloe M.
2026-06-23 19:11:14 +00:00
parent 27af606ba2
commit b6d4a1c963
8 changed files with 401 additions and 2 deletions
+87
View File
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2026, Chloe M.
* Provided under the BSD-3 clause.
*
* Description: Interrupt descriptor table
* Author: Chloe M.
*/
#include <machine/idt.h>
#include <machine/gdt.h>
#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
+9
View File
@@ -9,6 +9,7 @@
#include <hal/kpcr.h>
#include <ex/trace.h>
#include <machine/cpuid.h>
#include <machine/idt.h>
#include <stdef.h>
#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();
}
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2026, Chloe M.
* Provided under the BSD-3 clause.
*
* Description: Trap handling
* Author: Chloe M.
*/
#include <machine/trap.h>
#include <ke/knot.h>
#include <stdef.h>
/* 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]);
}
+196
View File
@@ -0,0 +1,196 @@
/*
* Copyright (c) 2026, Chloe M.
* Provided under the BSD-3 clause.
*
* Description: Interrupt Vector entries
* Author: Chloe M.
*/
#include <machine/idt.h>
#include <machine/kfence.h>
#include <machine/frame.h>
.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
+17
View File
@@ -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_ */
+38
View File
@@ -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 <stdef.h>
#include <machine/frame.h>
#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_ */
+3 -1
View File
@@ -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;
/*
+2 -1
View File
@@ -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 */