diff options
| -rw-r--r-- | mos/sys/arch/x86_64/cpu/idt.c | 38 | ||||
| -rw-r--r-- | mos/sys/arch/x86_64/cpu/locore.S | 3 | ||||
| -rw-r--r-- | mos/sys/arch/x86_64/cpu/trap.c | 16 | ||||
| -rw-r--r-- | mos/sys/arch/x86_64/cpu/vector.S | 214 | ||||
| -rw-r--r-- | mos/sys/inc/arch/x86_64/frame.h | 40 | ||||
| -rw-r--r-- | mos/sys/inc/arch/x86_64/idt.h | 69 | ||||
| -rw-r--r-- | mos/sys/inc/arch/x86_64/kfence.h | 31 | ||||
| -rw-r--r-- | mos/sys/inc/kern/panic.h | 18 | ||||
| -rw-r--r-- | mos/sys/kern/kern_panic.c | 29 | ||||
| -rw-r--r-- | usr/sdk/inc/sdk/defs.h | 1 |
10 files changed, 459 insertions, 0 deletions
diff --git a/mos/sys/arch/x86_64/cpu/idt.c b/mos/sys/arch/x86_64/cpu/idt.c new file mode 100644 index 0000000..569fe71 --- /dev/null +++ b/mos/sys/arch/x86_64/cpu/idt.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025, Ian Moffett. + * Provided under the BSD-3 clause. + */ + +#include <sdk/defs.h> +#include <md/idt.h> +#include <md/gdt.h> + +ALIGN(8) static IDT_GATE idt[256]; +static IDT_DESCRIPTOR idtr = { + .limit = sizeof(idt) - 1, + .offset = (UPTR)&idt[0] +}; + +void +md_idt_set_entry(UBYTE vector, UPTR isr, UBYTE type, UBYTE ist) +{ + IDT_GATE *gate = &idt[vector]; + + gate->offset_low = isr & 0xFFFF; + gate->offset_mid = (isr >> 16) & 0xFFFF; + gate->offset_high = (isr >> 32) & 0xFFFFFFFF; + gate->p = 1; + gate->dpl = (type == IDT_USER_GATE) ? 3 : 0; + gate->zero = 0; + gate->zero1 = 0; + gate->reserved = 0; + gate->ist = ist; + gate->target_cs = GDT_KCODE; + gate->type = type; +} + +void +md_idt_load(void) +{ + ASM("lidt %0" :: "m" (idtr) : "memory"); +} diff --git a/mos/sys/arch/x86_64/cpu/locore.S b/mos/sys/arch/x86_64/cpu/locore.S index 5fdd741..b0eb068 100644 --- a/mos/sys/arch/x86_64/cpu/locore.S +++ b/mos/sys/arch/x86_64/cpu/locore.S @@ -15,6 +15,9 @@ _start: lea g_GDTR(%rip), %rdi /* BSP GDTR base */ call md_gdt_load /* Load it */ + call md_set_vectors /* Set interrupt vectors */ + call md_idt_load /* Load the IDT */ + xor %rbp, %rbp /* Terminate callstack */ call kern_main /* Call kernel main */ diff --git a/mos/sys/arch/x86_64/cpu/trap.c b/mos/sys/arch/x86_64/cpu/trap.c new file mode 100644 index 0000000..bacf9c2 --- /dev/null +++ b/mos/sys/arch/x86_64/cpu/trap.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025, Ian Moffett. + * Provided under the BSD-3 clause. + */ + +#include <kern/panic.h> +#include <md/frame.h> + +/* Forward declaration */ +void trap_dispatch(TRAPFRAME *tf); + +void +trap_dispatch(TRAPFRAME *tf) +{ + panic("fatal vector %x\n", tf->vector); +} diff --git a/mos/sys/arch/x86_64/cpu/vector.S b/mos/sys/arch/x86_64/cpu/vector.S new file mode 100644 index 0000000..6d29afb --- /dev/null +++ b/mos/sys/arch/x86_64/cpu/vector.S @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2025, Ian Moffett. + * Provided under the BSD-3 clause. + */ + +#include <md/idt.h> +#include <md/kfence.h> + + .macro set_trap vector, isr, ist + mov $\vector, %rdi + lea \isr(%rip), %rsi + mov $IDT_TRAP_GATE, %rdx + mov $\ist, %rcx + call md_idt_set_entry + .endm + + .macro push_trapframe vector + .if \vector == 10 || \vector == 11 || \vector == 12 || \vector == 13 \ + || \vector == 14 + subq $8, %rsp + .endif + + push %rax + push %rbx + push %rcx + push %rdx + push %rsi + push %rdi + push %rbp + push %r8 + push %r9 + push %r10 + push %r11 + push %r12 + push %r13 + push %r14 + push %r15 + push $\vector + .endm + + .text + .globl md_set_vectors +md_set_vectors: + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + push %rbp + + set_trap 0x00, diverr, 0 + set_trap 0x01, debug_except, 0 + set_trap 0x02, nmi, 0 + set_trap 0x03, breakpoint, 0 + set_trap 0x04, overflow, 0 + set_trap 0x05, bound_range, 0 + set_trap 0x06, invalid_tss, 0 + set_trap 0x07, no_coproc, 0 + set_trap 0x08, double_fault, 0 + set_trap 0x0A, invalid_tss, 0 + set_trap 0x0B, seg_np, 0 + set_trap 0x0C, ss_fault, 0 + set_trap 0x0D, gpf, 0 + set_trap 0x0E, page_fault, 0 + + pop %rbp + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + retq + + .align 8 +diverr: + KFENCE + push_trapframe 0x00 + mov %rsp, %rdi + call trap_dispatch + KFENCE +1: cli + hlt + jmp 1b + +debug_except: + KFENCE + push_trapframe 0x1 + mov %rsp, %rdi + call trap_dispatch + KFENCE +1: cli + hlt + jmp 1b + +nmi: + KFENCE + push_trapframe 0x2 + mov %rsp, %rdi + call trap_dispatch + KFENCE +1: cli + hlt + jmp 1b + +breakpoint: + KFENCE + push_trapframe 0x3 + mov %rsp, %rdi + call trap_dispatch + KFENCE +1: cli + hlt + jmp 1b + +overflow: + KFENCE + push_trapframe 0x4 + mov %rsp, %rdi + call trap_dispatch + KFENCE +1: cli + hlt + jmp 1b + +bound_range: + KFENCE + push_trapframe 0x5 + mov %rsp, %rdi + call trap_dispatch + KFENCE +1: cli + hlt + jmp 1b + +invl_opc: + KFENCE + push_trapframe 0x6 + mov %rsp, %rdi + call trap_dispatch + KFENCE +1: cli + hlt + jmp 1b + +no_coproc: + KFENCE + push_trapframe 0x7 + mov %rsp, %rdi + call trap_dispatch + KFENCE +1: cli + hlt + jmp 1b + +double_fault: + KFENCE_EC + push_trapframe 0x8 + mov %rsp, %rdi + call trap_dispatch + KFENCE_EC +1: cli + hlt + jmp 1b + +invalid_tss: + KFENCE_EC + push_trapframe 0xA + mov %rsp, %rdi + call trap_dispatch + KFENCE_EC +1: cli + hlt + jmp 1b + +seg_np: + KFENCE_EC + push_trapframe 0xB + mov %rsp, %rdi + call trap_dispatch + KFENCE_EC +1: cli + hlt + jmp 1b + +ss_fault: + KFENCE_EC + push_trapframe 0xC + mov %rsp, %rdi + call trap_dispatch + KFENCE_EC +1: cli + hlt + jmp 1b + +gpf: + KFENCE_EC + push_trapframe 0xD + mov %rsp, %rdi + call trap_dispatch + KFENCE_EC +1: cli + hlt + jmp 1b + +page_fault: + KFENCE_EC + push_trapframe 0xE + mov %rsp, %rdi + call trap_dispatch + KFENCE_EC +1: cli + hlt + jmp 1b + hlt diff --git a/mos/sys/inc/arch/x86_64/frame.h b/mos/sys/inc/arch/x86_64/frame.h new file mode 100644 index 0000000..5908d93 --- /dev/null +++ b/mos/sys/inc/arch/x86_64/frame.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025, Ian Moffett. + * Provided under the BSD-3 clause. + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ 1 + +#include <sdk/types.h> +#include <sdk/defs.h> + +/* + * Processor state + */ +typedef struct { + UQUAD vector; + UQUAD r15; + UQUAD r14; + UQUAD r13; + UQUAD r12; + UQUAD r11; + UQUAD r10; + UQUAD r9; + UQUAD r8; + UQUAD rbp; + UQUAD rdi; + UQUAD rsi; + UQUAD rbx; + UQUAD rdx; + UQUAD rcx; + UQUAD rax; + UQUAD error_code; + UQUAD rip; + UQUAD cs; + UQUAD rflags; + UQUAD rsp; + UQUAD ss; +} PACKED TRAPFRAME; + +#endif /* !_MACHINE_FRAME_H_ */ diff --git a/mos/sys/inc/arch/x86_64/idt.h b/mos/sys/inc/arch/x86_64/idt.h new file mode 100644 index 0000000..aa03925 --- /dev/null +++ b/mos/sys/inc/arch/x86_64/idt.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025, Ian Moffett. + * Provided under the BSD-3 clause. + */ + +#ifndef _MACHINE_IDT_H_ +#define _MACHINE_IDT_H_ 1 + +#ifndef __ASSEMBLER__ +#include <sdk/types.h> +#include <sdk/defs.h> +#endif /* !__ASSEMBLER__ */ + +#define IDT_INT_GATE 0x8E +#define IDT_TRAP_GATE 0x8F +#define IDT_USER_GATE 0xEE + +#ifndef __ASSEMBLER__ + +/* + * Represents a 64-bit interrupt gate descriptor + * for the x86_64 architecture. See section 6.14.1 + * for more information. + */ +typedef struct { + USHORT offset_low; + USHORT target_cs; + UBYTE ist : 3; + UBYTE zero : 5; + UBYTE type : 4; + UBYTE zero1 : 1; + UBYTE dpl : 2; + UBYTE p : 1; + USHORT offset_mid; + ULONG offset_high; + ULONG reserved; +} IDT_GATE; + +/* + * This descriptor is loaded into the processor core + * for when it needs to reference a gate descriptor. + * + * @limit: IDT limit + * @offset: Base address of IDT + */ +typedef struct { + USHORT limit; + UPTR offset; +} PACKED IDT_DESCRIPTOR; + +/* + * Set an interrupt gate descriptor within the + * interrupt descriptor table. + * + * @vector: Interrupt vector to set + * @isr: Interrupt service routine + * @type: Gate descriptor type + * @ist: Interrupt stack table index to use + */ +void md_idt_set_entry(UBYTE vector, UPTR isr, UBYTE type, UBYTE ist); + +/* + * Load the interrupt descriptor table into the current + * processor core. + */ +void md_idt_load(void); + +#endif /* !__ASSEMBLER__ */ +#endif /* !_MACHINE_IDT_H_ */ diff --git a/mos/sys/inc/arch/x86_64/kfence.h b/mos/sys/inc/arch/x86_64/kfence.h new file mode 100644 index 0000000..f44336c --- /dev/null +++ b/mos/sys/inc/arch/x86_64/kfence.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025, Ian Moffett. + * Provided under the BSD-3 clause. + */ + +#ifndef _MACHINE_KFENCE_H_ +#define _MACHINE_KFENCE_H_ 1 + +/* + * Kernel fence for interrupt entries that do + * not have an error code + */ +#define KFENCE \ + testq $0x3, 8(%rsp) ; \ + jz 1f ; \ + lfence ; \ + swapgs ; \ +1: nop + +/* + * Kernel fence for interrupt entries that + * have an error code + */ +#define KFENCE_EC \ + testq $0x3, 16(%rsp) ; \ + jz 1f ; \ + lfence ; \ + swapgs ; \ +1: nop + +#endif /* !_MACHINE_KFENCE_H_ */ diff --git a/mos/sys/inc/kern/panic.h b/mos/sys/inc/kern/panic.h new file mode 100644 index 0000000..a7aac0e --- /dev/null +++ b/mos/sys/inc/kern/panic.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025, Ian Moffett. + * Provided under the BSD-3 clause. + */ + +#ifndef _KERN_PANIC_H_ +#define _KERN_PANIC_H_ 1 + +#include <sdk/types.h> +#include <sdk/stdarg.h> + +/* + * Signal to the operator that a severe error has + * occurred and the system has been halted. + */ +void panic(const char *fmt, ...); + +#endif /* !_KERN_PANIC_H_ */ diff --git a/mos/sys/kern/kern_panic.c b/mos/sys/kern/kern_panic.c new file mode 100644 index 0000000..8f03e6a --- /dev/null +++ b/mos/sys/kern/kern_panic.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025, Ian Moffett. + * Provided under the BSD-3 clause. + */ + +#include <sdk/string.h> +#include <kern/panic.h> +#include <kern/spinlock.h> +#include <kern/trace.h> +#include <mu/cpu.h> + +static SPINLOCK panic_sync; +static char panic_buf[256]; +static va_list ap; + +void +panic(const char *fmt, ...) +{ + spinlock_acquire(&panic_sync, SPINLOCK_IRQMUT); + va_start(ap, fmt); + + vsnprintf(panic_buf, sizeof(panic_buf), fmt, ap); + trace("panic: "); + trace(panic_buf); + + for (;;) { + mu_cpu_halt(); + } +} diff --git a/usr/sdk/inc/sdk/defs.h b/usr/sdk/inc/sdk/defs.h index 3d4ccfc..1b7cd23 100644 --- a/usr/sdk/inc/sdk/defs.h +++ b/usr/sdk/inc/sdk/defs.h @@ -11,5 +11,6 @@ #define ALIGN(n) ATTR(aligned((n))) #define NO_RETURN ATTR(no_return) #define ALWAYS_INLINE ATTR(always_inline) +#define PACKED ATTR(packed) #endif /* !_SDK_DEFS_H_ */ |
