stos/amd64: cpu: Add exception handling groundwork
Signed-off-by: Chloe M. <chloe@mensia.org>
This commit is contained in:
@@ -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,6 +9,7 @@
|
|||||||
#include <hal/kpcr.h>
|
#include <hal/kpcr.h>
|
||||||
#include <ex/trace.h>
|
#include <ex/trace.h>
|
||||||
#include <machine/cpuid.h>
|
#include <machine/cpuid.h>
|
||||||
|
#include <machine/idt.h>
|
||||||
#include <stdef.h>
|
#include <stdef.h>
|
||||||
|
|
||||||
#define DTRACE(Fmt, ...) \
|
#define DTRACE(Fmt, ...) \
|
||||||
@@ -31,6 +32,9 @@ static const CHAR *ProcessorType[] = {
|
|||||||
[PROCESSOR_DUAL] = "Intel P5 dual processor"
|
[PROCESSOR_DUAL] = "Intel P5 dual processor"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* From cpu/vector.S */
|
||||||
|
extern VOID MdVectorInit(VOID);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called by ProcessorIdentify()
|
* Called by ProcessorIdentify()
|
||||||
*/
|
*/
|
||||||
@@ -113,4 +117,9 @@ HalKpcrP1Init(KPCR *Kpcr)
|
|||||||
|
|
||||||
Mcb = &Kpcr->Mcb;
|
Mcb = &Kpcr->Mcb;
|
||||||
ProcessorIdentify(Mcb);
|
ProcessorIdentify(Mcb);
|
||||||
|
|
||||||
|
/* Load the IDT */
|
||||||
|
MdVectorInit();
|
||||||
|
MdIdtLoad();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -13,4 +13,21 @@
|
|||||||
#define IDT_TRAP_GATE 0x8F
|
#define IDT_TRAP_GATE 0x8F
|
||||||
#define IDT_USER_GATE 0xEE
|
#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_ */
|
#endif /* !_MACHINE_IDT_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 <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_ */
|
||||||
@@ -18,12 +18,14 @@
|
|||||||
* @KNOT_UNBOUND_RSRC: Unbounded resource
|
* @KNOT_UNBOUND_RSRC: Unbounded resource
|
||||||
* @KNOT_BAD_BOOT_PROTO: Bad boot protocol
|
* @KNOT_BAD_BOOT_PROTO: Bad boot protocol
|
||||||
* @KNOT_OOM: Fatal out of memory
|
* @KNOT_OOM: Fatal out of memory
|
||||||
|
* @KNOT_EXCEPTION: Fatal exception
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
KNOT_MISC,
|
KNOT_MISC,
|
||||||
KNOT_UNBOUND_RSRC,
|
KNOT_UNBOUND_RSRC,
|
||||||
KNOT_BAD_BOOT_PROTO,
|
KNOT_BAD_BOOT_PROTO,
|
||||||
KNOT_OOM
|
KNOT_OOM,
|
||||||
|
KNOT_EXCEPTION
|
||||||
} KNOT_REASON;
|
} KNOT_REASON;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+2
-1
@@ -21,7 +21,8 @@ static const CHAR *ReasonTable[] = {
|
|||||||
[KNOT_MISC] = "unspecified reason",
|
[KNOT_MISC] = "unspecified reason",
|
||||||
[KNOT_UNBOUND_RSRC] = "unbounded resource",
|
[KNOT_UNBOUND_RSRC] = "unbounded resource",
|
||||||
[KNOT_BAD_BOOT_PROTO] = "bad boot protocol",
|
[KNOT_BAD_BOOT_PROTO] = "bad boot protocol",
|
||||||
[KNOT_OOM] = "out of memory"
|
[KNOT_OOM] = "out of memory",
|
||||||
|
[KNOT_EXCEPTION] = "fatal exception"
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
|
|||||||
Reference in New Issue
Block a user