From caad8df87d20c5949ef4c1190bc5a63ccf75dc05 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 19 Jun 2025 00:53:55 -0400 Subject: kernel/aarch64: Add exception code + frame fixups - Add handle_exception() as higher level logic to handle the exceptions - Simplify frame.h - Call C handler in vector.S - Clean up stack after creating frame - Add register dump on exception Signed-off-by: Ian Moffett --- sys/arch/aarch64/aarch64/exception.c | 128 +++++++++++++++++++++++++++++++++++ sys/arch/aarch64/aarch64/vector.S | 51 +++++--------- sys/include/arch/aarch64/exception.h | 54 +++++++++++++++ sys/include/arch/aarch64/frame.h | 80 ++++++++++------------ sys/include/arch/aarch64/frameasm.h | 21 ++++-- 5 files changed, 249 insertions(+), 85 deletions(-) create mode 100644 sys/arch/aarch64/aarch64/exception.c create mode 100644 sys/include/arch/aarch64/exception.h diff --git a/sys/arch/aarch64/aarch64/exception.c b/sys/arch/aarch64/aarch64/exception.c new file mode 100644 index 0000000..d6f1f97 --- /dev/null +++ b/sys/arch/aarch64/aarch64/exception.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * 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 Hyra 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 +#include +#include +#include +#include + +#define pr_trace(fmt, ...) kprintf("exception: " fmt, ##__VA_ARGS__) +#define pr_error(...) pr_trace(__VA_ARGS__) + +static inline void +log_esr_class(uint8_t class) +{ + switch (class) { + case EC_WF: + pr_error("trapped WF\n"); + break; + case EC_MCRMRC: + pr_error("trapped MCR/MRC\n"); + break; + case EC_MCRRC: + pr_trace("trapped MCRR/MRRC\n"); + break; + case EC_LDCSTC: + pr_error("trapped LDC/STC\n"); + break; + case EC_SVE: + pr_trace("trapped SVE/SIMD/FP operation\n"); + break; + case EC_BRE: + pr_error("ibt: bad branch target\n"); + break; + case EC_ILLX: + pr_error("illegal execution state\n"); + break; + case EC_SVC64: + /* TODO */ + pr_error("supervisor call (TODO)!!\n"); + break; + case EC_PCALIGN: + pr_error("PC alignment fault\n"); + break; + case EC_DABORT: + case EC_EDABORT: + pr_error("data abort\n"); + break; + case EC_SPALIGN: + pr_error("SP alignment fault\n"); + break; + case EC_SERR: + pr_error("system error\n"); + break; + default: + pr_error("unknown exception\n"); + } +} + +static void +regdump(struct trapframe *tf, uint64_t elr) +{ + kprintf(OMIT_TIMESTAMP + "X0=%p X1=%p X2=%p\n" + "X3=%p X4=%p X5=%p\n" + "X6=%p X7=%p X8=%p\n" + "X9=%p X10=%p X11=%p\n" + "X12=%p X13=%p X14=%p\n" + "X15=%p X16=%p X17=%p\n" + "X18=%p X19=%p X20=%p\n" + "X21=%p X22=%p X23=%p\n" + "X24=%p X25=%p X26=%p\n" + "X27=%p X28=%p X29=%p\n" + "X30=%p\n" + "ELR=%p\n", + tf->x0, tf->x1, tf->x2, tf->x3, + tf->x4, tf->x5, tf->x6, tf->x7, + tf->x8, tf->x9, tf->x10, tf->x11, + tf->x12, tf->x13, tf->x14, tf->x15, + tf->x16, tf->x17, tf->x18, tf->x19, + tf->x20, tf->x21, tf->x22, tf->x23, + tf->x24, tf->x25, tf->x26, tf->x27, + tf->x28, tf->x29, tf->x30, elr); +} + +/* + * Handle an exception + * + * @esr: Copy of the Exception Syndrome Register + */ +void +handle_exception(struct trapframe *tf) +{ + uint8_t class; + + class = (tf->esr >> 26) & 0x3F; + log_esr_class(class); + regdump(tf, tf->elr); + for (;;) { + md_hlt(); + } +} diff --git a/sys/arch/aarch64/aarch64/vector.S b/sys/arch/aarch64/aarch64/vector.S index f38f24e..c8f77ca 100644 --- a/sys/arch/aarch64/aarch64/vector.S +++ b/sys/arch/aarch64/aarch64/vector.S @@ -36,54 +36,37 @@ b \label .endm - .section .data -error: - .ascii "got exception, halting\n\0" - .text x_sync_elx: - PUSH_XFRAME(TRAPNO_XSYNC) - ldr x0, =error - bl kprintf - POP_XFRAME() -1: - hlt #0 + PUSH_XFRAME(TRAPNO_XSYNC) // Synchronous: sp+top @ X0 + bl handle_exception // Handle the exception + POP_XFRAME() // Pop the trapframe +1: hlt #0 // TODO b 1b x_irq_elx: - PUSH_XFRAME(TRAPNO_XSYNC) - ldr x0, =error - bl kprintf - POP_XFRAME() -1: - hlt #0 + PUSH_XFRAME(TRAPNO_XIRQ) // IRQ: sp+top @ X0 + bl handle_exception // Handle the exception + POP_XFRAME() // Pop the trapframe +1: hlt #0 // TODO b 1b x_fiq_elx: - PUSH_XFRAME(TRAPNO_XSYNC) - ldr x0, =error - bl kprintf - POP_XFRAME() -1: - hlt #0 + PUSH_XFRAME(TRAPNO_XFIQ) // FIQ: sp+top @ X0 + bl handle_exception // Handle the exception + POP_XFRAME() // Pop the trapframe +1: hlt #0 b 1b x_serr_elx: - PUSH_XFRAME(TRAPNO_XSYNC) - ldr x0, =error - bl kprintf - POP_XFRAME() -1: - hlt #0 + PUSH_XFRAME(TRAPNO_XSERR) // SERR: sp+top @ X0 + bl handle_exception // Handle the exception + POP_XFRAME() // Pop the trapframe +1: hlt #0 // TODO b 1b x_unimpl: - PUSH_XFRAME(TRAPNO_XSYNC) - ldr x0, =error - bl kprintf - POP_XFRAME() -1: - hlt #0 +1: hlt #0 b 1b .align 11 // Table aligned @ 2 KiB diff --git a/sys/include/arch/aarch64/exception.h b/sys/include/arch/aarch64/exception.h new file mode 100644 index 0000000..9e89c81 --- /dev/null +++ b/sys/include/arch/aarch64/exception.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * 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 Hyra 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. + */ + +#ifndef _MACHINE_EXCEPTION_H_ +#define _MACHINE_EXCEPTION_H_ + +#include +#include + +/* Exception class */ +#define EC_UNKNOWN 0x00 /* Unknown type */ +#define EC_WF 0x01 /* Trapped WF instruction */ +#define EC_MCRMRC 0x03 /* Trapped MCR/MRC */ +#define EC_MCRRC 0x04 /* Trapped MCRR/MRRC */ +#define EC_LDCSTC 0x06 /* Trapped LDC/STC */ +#define EC_SVE 0x07 /* Trapped SVE/SIMD/FP op */ +#define EC_BRE 0x0D /* Branch target exception */ +#define EC_ILLX 0x0E /* Illegal execution state */ +#define EC_SVC64 0x15 /* AARCH64 SVC */ +#define EC_PCALIGN 0x22 /* PC alignment fault */ +#define EC_DABORT 0x24 /* Data abort (w/o ELx change) */ +#define EC_EDABORT 0x25 /* Data abort (w/ ELx change) */ +#define EC_SPALIGN 0x26 /* SP alignment fault */ +#define EC_SERR 0x2F /* System error (what the fuck!) */ + +void handle_exception(struct trapframe *tf); + +#endif /* !_MACHINE_EXCEPTION_H_ */ diff --git a/sys/include/arch/aarch64/frame.h b/sys/include/arch/aarch64/frame.h index f14fa01..143f4d0 100644 --- a/sys/include/arch/aarch64/frame.h +++ b/sys/include/arch/aarch64/frame.h @@ -31,46 +31,11 @@ #define _MACHINE_FRAME_H_ #include +#include typedef uint64_t lreg_t; typedef uint64_t frament_t; -/* General purpose registers */ -struct gpregs { - frament_t trapno; - lreg_t x0; - lreg_t x1; - lreg_t x2; - lreg_t x3; - lreg_t x4; - lreg_t x5; - lreg_t x6; - lreg_t x7; - lreg_t x8; - lreg_t x9; - lreg_t x10; - lreg_t x11; - lreg_t x12; - lreg_t x13; - lreg_t x14; - lreg_t x15; - lreg_t x16; - lreg_t x17; - lreg_t x18; - lreg_t x19; - lreg_t x20; - lreg_t x21; - lreg_t x22; - lreg_t x23; - lreg_t x24; - lreg_t x25; - lreg_t x26; - lreg_t x27; - lreg_t x28; - lreg_t x29; - lreg_t x30; -}; - /* Stack regs */ struct sregs { lreg_t sp_el0; @@ -85,14 +50,41 @@ struct pstat { lreg_t spsr_el3; }; -struct trapframe { - struct gpregs gp; - struct sregs stack; - struct pstat status; - lreg_t elr_el1; - lreg_t elr_el2; - lreg_t elr_el3; - lreg_t pc; +struct __aligned(16) trapframe { + lreg_t x30; + lreg_t x29; + lreg_t x28; + lreg_t x27; + lreg_t x26; + lreg_t x25; + lreg_t x24; + lreg_t x23; + lreg_t x22; + lreg_t x21; + lreg_t x20; + lreg_t x19; + lreg_t x18; + lreg_t x17; + lreg_t x16; + lreg_t x15; + lreg_t x14; + lreg_t x13; + lreg_t x12; + lreg_t x11; + lreg_t x10; + lreg_t x9; + lreg_t x8; + lreg_t x7; + lreg_t x6; + lreg_t x5; + lreg_t x4; + lreg_t x3; + lreg_t x2; + lreg_t x1; + lreg_t x0; + lreg_t elr; + lreg_t esr; + frament_t trapno; }; #define TF_IP(TFP) ((TFP)->pc) diff --git a/sys/include/arch/aarch64/frameasm.h b/sys/include/arch/aarch64/frameasm.h index 5664ff5..ca7f81a 100644 --- a/sys/include/arch/aarch64/frameasm.h +++ b/sys/include/arch/aarch64/frameasm.h @@ -31,13 +31,14 @@ #define _MACHINE_FRAMEASM_H_ /* XXX: Must be 16-byte aligned!!! */ -#define XFRAME_STACK_SIZE (34 * 8) +#define XFRAME_STACK_SIZE (38 * 8) /* Trap numbers */ -#define TRAPNO_XSYNC #0 /* Synchronous */ -#define TRAPNO_XIRQ #1 /* IRQ */ -#define TRAPNO_XFIQ #2 /* FIQ */ -#define TRAPNO_XSERR #3 /* System error */ +#define TRAPNO_UNKNOWN #0 +#define TRAPNO_XSYNC #1 /* Synchronous */ +#define TRAPNO_XIRQ #2 /* IRQ */ +#define TRAPNO_XFIQ #3 /* FIQ */ +#define TRAPNO_XSERR #4 /* System error */ #define PUSH_XFRAME(TRAPNO) \ sub sp, sp, #XFRAME_STACK_SIZE ; \ @@ -57,11 +58,16 @@ stp x4, x3, [sp, #(26 * 8)] ; \ stp x2, x1, [sp, #(28 * 8)] ; \ str x0, [sp, #(30 * 8)] ; \ + ; \ + mrs x0, elr_el1 ; \ + str x0, [sp, #(31 * 8)] ; \ + mrs x0, esr_el1 ; \ + str x0, [sp, #(32 * 8)] ; \ mov x0, TRAPNO ; \ - str x0, [sp, #(31 * 8)] + str x0, [sp, #(33 * 8)] ; \ + mov x0, sp #define POP_XFRAME() \ - add sp, sp, #8 ; \ ldr x0, [sp, #(30 * 8)] ; \ ldp x2, x1, [sp, #(28 * 8)] ; \ ldp x4, x3, [sp, #(26 * 8)] ; \ @@ -78,5 +84,6 @@ ldp x26, x25, [sp, #(4 * 8)] ; \ ldp x28, x27, [sp, #(2 * 8)] ; \ ldp x30, x29, [sp, #(0 * 8)] ; \ + add sp, sp, #XFRAME_STACK_SIZE #endif /* !_MACHINE_FRAMEASM_H_ */ -- cgit v1.2.3