diff options
author | Ian Moffett <ian@osmora.org> | 2025-09-15 07:24:05 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-09-15 07:24:05 -0400 |
commit | 51aca35fe3cf86fc9652a20a3e6ae23553f27665 (patch) | |
tree | 8528cebe768f9cd4114f2a5b37f8a9a91aa69971 /src/sys/arch | |
parent | 2cdbcda1b9ed0e8d5e385f100c823cc3a23c716b (diff) |
kern/amd64: Add exception handlers
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'src/sys/arch')
-rw-r--r-- | src/sys/arch/amd64/cpu/cpu_conf.c | 24 | ||||
-rw-r--r-- | src/sys/arch/amd64/cpu/trap.S | 103 | ||||
-rw-r--r-- | src/sys/arch/amd64/cpu/trap.c | 157 |
3 files changed, 284 insertions, 0 deletions
diff --git a/src/sys/arch/amd64/cpu/cpu_conf.c b/src/sys/arch/amd64/cpu/cpu_conf.c index 9399973..de0e9bc 100644 --- a/src/sys/arch/amd64/cpu/cpu_conf.c +++ b/src/sys/arch/amd64/cpu/cpu_conf.c @@ -30,11 +30,35 @@ #include <sys/cpuvar.h> #include <machine/boot.h> #include <machine/msr.h> +#include <machine/idt.h> +#include <machine/trap.h> + +/* + * Initialize interrupt vectors + */ +static void +init_vectors(void) +{ + idt_set_desc(0x0, IDT_TRAP_GATE, ISR(arith_err), 0); + idt_set_desc(0x2, IDT_TRAP_GATE, ISR(nmi), 0); + idt_set_desc(0x3, IDT_TRAP_GATE, ISR(breakpoint_handler), 0); + idt_set_desc(0x4, IDT_TRAP_GATE, ISR(overflow), 0); + idt_set_desc(0x5, IDT_TRAP_GATE, ISR(bound_range), 0); + idt_set_desc(0x6, IDT_TRAP_GATE, ISR(invl_op), 0); + idt_set_desc(0x8, IDT_TRAP_GATE, ISR(double_fault), 0); + idt_set_desc(0xA, IDT_TRAP_GATE, ISR(invl_tss), 0); + idt_set_desc(0xB, IDT_TRAP_GATE, ISR(segnp), 0); + idt_set_desc(0xC, IDT_TRAP_GATE, ISR(ss_fault), 0); + idt_set_desc(0xD, IDT_TRAP_GATE, ISR(general_prot), 0); + idt_set_desc(0xE, IDT_TRAP_GATE, ISR(page_fault), 0); +} void cpu_conf(struct pcore *pcore) { pcore->self = pcore; + init_vectors(); + idt_load(); platform_boot(); /* We use %GS to store the processor */ diff --git a/src/sys/arch/amd64/cpu/trap.S b/src/sys/arch/amd64/cpu/trap.S new file mode 100644 index 0000000..fb756e8 --- /dev/null +++ b/src/sys/arch/amd64/cpu/trap.S @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2025 Ian Marco Moffett and L5 engineers + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <machine/frameasm.h> +#include <machine/trap.h> + + .globl breakpoint_handler +TRAP_ENTRY(breakpoint_handler, $TRAP_BREAKPOINT) + mov %rsp, %rdi + call trap_handler +TRAP_EXIT(breakpoint_handler) + + .globl arith_err +TRAP_ENTRY(arith_err, $TRAP_ARITH_ERR) + mov %rsp, %rdi + call trap_handler +TRAP_EXIT(arith_err) + + .globl overflow +TRAP_ENTRY(overflow, $TRAP_OVERFLOW) + mov %rsp, %rdi + call trap_handler +TRAP_EXIT(overflow) + + .globl bound_range +TRAP_ENTRY(bound_range, $TRAP_BOUND_RANGE) + mov %rsp, %rdi + call trap_handler +TRAP_EXIT(bound_range) + + .globl invl_op +TRAP_ENTRY(invl_op, $TRAP_INVLOP) + mov %rsp, %rdi + call trap_handler +TRAP_EXIT(invl_op) + + .globl double_fault +TRAP_ENTRY_EC(double_fault, $TRAP_DOUBLE_FAULT) + mov %rsp, %rdi + call trap_handler +TRAP_EXIT_EC(double_fault) + + .globl invl_tss +TRAP_ENTRY_EC(invl_tss, $TRAP_INVLTSS) + mov %rsp, %rdi + call trap_handler +TRAP_EXIT_EC(invl_tss) + + .globl segnp +TRAP_ENTRY_EC(segnp, $TRAP_SEGNP) + mov %rsp, %rdi + call trap_handler +TRAP_EXIT_EC(segnp) + + .globl general_prot +TRAP_ENTRY_EC(general_prot, $TRAP_PROTFLT) + mov %rsp, %rdi + call trap_handler +TRAP_EXIT_EC(general_prot) + + .globl page_fault +TRAP_ENTRY_EC(page_fault, $TRAP_PAGEFLT) + mov %rsp, %rdi + call trap_handler +TRAP_EXIT_EC(page_fault) + + .globl nmi +TRAP_ENTRY(nmi, $TRAP_NMI) + mov %rsp, %rdi + call trap_handler +TRAP_EXIT(nmi) + + .globl ss_fault +TRAP_ENTRY_EC(ss_fault, $TRAP_SS) + mov %rsp, %rdi + call trap_handler +TRAP_EXIT_EC(ss_fault) diff --git a/src/sys/arch/amd64/cpu/trap.c b/src/sys/arch/amd64/cpu/trap.c new file mode 100644 index 0000000..046263b --- /dev/null +++ b/src/sys/arch/amd64/cpu/trap.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2025 Ian Marco Moffett and L5 engineers + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Description: AMD64 trap handling module + * Author: Ian Marco Moffett + */ + +#include <sys/param.h> +#include <sys/cdefs.h> +#include <sys/panic.h> +#include <sys/syslog.h> +#include <machine/trap.h> + +/* + * Trap type to type string conversion table + * Indexed by trapno field in trapframe. + */ +static const char *trapstr[] = { + [TRAP_NONE] = "bad", + [TRAP_BREAKPOINT] = "breakpoint", + [TRAP_ARITH_ERR] = "arithmetic error", + [TRAP_OVERFLOW] = "overflow", + [TRAP_BOUND_RANGE] = "bound range exceeded", + [TRAP_INVLOP] = "invalid opcode", + [TRAP_DOUBLE_FAULT] = "double fault", + [TRAP_INVLTSS] = "invalid TSS", + [TRAP_SEGNP] = "segment not present", + [TRAP_PROTFLT] = "general protection", + [TRAP_PAGEFLT] = "page fault", + [TRAP_NMI] = "non-maskable interrupt", + [TRAP_SS] = "stack-segment fault" +}; + +/* + * Page fault flags (bit relative) + */ +static const char pf_flags[] = { + 'p', /* Present */ + 'w', /* Write */ + 'u', /* User */ + 'r', /* Reserved write */ + 'x', /* Instruction fetch */ + 'k', /* Protection key violation */ + 's' /* Shadow stack access */ +}; + +/* + * Return the current value of the page fault address + * register (CR2) + */ +static inline uintptr_t +pf_faultaddr(void) +{ + uintptr_t cr2; + + __ASMV( + "mov %%cr2, %0\n" + : "=r" (cr2) + : + : "memory" + ); + return cr2; +} + +/* + * Log the error code for page faults + * + * @error_code: Page fault error code to log + */ +static void +pf_code(uint64_t error_code) +{ + char tab[8] = { + '-', '-', '-', + '-', '-', '-', + '-', '\0' + }; + + for (int i = 0; i < 7; ++i) { + if (ISSET(error_code, BIT(i))) { + tab[i] = pf_flags[i]; + } + } + + printf("code=[%s]\n", tab); +} + +/* + * Dump a trapframe + * + * @tf: Trapframe to dump + */ +static inline void +trapframe_dump(struct trapframe *tf) +{ + uintptr_t cr3, cr2 = pf_faultaddr(); + + __ASMV("mov %%cr3, %0\n" + : "=r" (cr3) + : + : "memory" + ); + + if (tf->trapno == TRAP_PAGEFLT) { + pf_code(tf->error_code); + } + + printf("got trap (%s)\n\n" + "-- DUMPING PROCESSOR STATE --\n" + "RAX=%p RCX=%p RDX=%p\n" + "RBX=%p RSI=%p RDI=%p\n" + "RFL=%p CR2=%p CR3=%p\n" + "RBP=%p RSP=%p RIP=%p\n\n", + trapstr[tf->trapno], + tf->rax, tf->rcx, tf->rdx, + tf->rbx, tf->rsi, tf->rdi, + tf->rflags, cr2, cr3, + tf->rbp, tf->rsp, tf->rip); +} + +void +trap_handler(struct trapframe *tf) +{ + trapframe_dump(tf); + if (ISSET(tf->cs, 3)) { + panic("fatal user trap\n"); + } + + panic("fatal trap\n"); +} |