From 497e4a1b2f6f9181518e9887991c0464bd8f6bcf Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Wed, 10 Dec 2025 01:19:32 +0800 Subject: feat: Add initial Supervisor Mode Trap Handler Implement the initial mechanism for handling traps and exceptions in Supervisor Mode. Set up the stvec Control and Status Register (CSR) to direct all S-Mode Traps (Interrupts and Exceptions) to a unified assembly entry point. Implemented assembly code for saving and restoring the Trap Context (register state). Provides the foundational framework necessary for future Timer Interrupts and System Calls. --- src/kernel/trap/handler.cc | 123 +++++++++++++++++++++++++++++++++++++++++++++ src/kernel/trap/trap.S | 87 ++++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 src/kernel/trap/handler.cc create mode 100644 src/kernel/trap/trap.S (limited to 'src/kernel/trap') diff --git a/src/kernel/trap/handler.cc b/src/kernel/trap/handler.cc new file mode 100644 index 0000000..9cc19d1 --- /dev/null +++ b/src/kernel/trap/handler.cc @@ -0,0 +1,123 @@ +#include "kernel/trap.h" +#include "common/types.h" +#include "drivers/uart.h" + +void panic(const char *s) +{ + Drivers::uart_puts("\n\n!!! KERNEL PANIC !!!\n"); + Drivers::uart_puts(s); + Drivers::uart_puts("\nSystem Halted.\n"); + while (1) + ; +} + +namespace Trap +{ + void init() + { + uint64 stvec_val = (uint64)kernelvec; + asm volatile("csrw stvec, %0" : : "r"(stvec_val)); + + uint64 sstatus; + asm volatile("csrr %0, sstatus" : "=r"(sstatus)); + sstatus &= ~(1L << 1); + asm volatile("csrw sstatus, %0" : : "r"(sstatus)); + + Drivers::uart_puts("[Trap] Initialized stvec to: "); + Drivers::print_hex(stvec_val); + Drivers::uart_puts("\n"); + } + + extern "C" void kerneltrap(struct Trapframe *tf) + { + uint64 scause, stval, sepc; + + asm volatile("csrr %0, scause" : "=r"(scause)); + asm volatile("csrr %0, stval" : "=r"(stval)); + asm volatile("csrr %0, sepc" : "=r"(sepc)); + + if (scause & (1L << 63)) + { + uint64 cause_code = scause & 0x7FFFFFFFFFFFFFFFL; + switch (cause_code) + { + case 1: + Drivers::uart_puts("[IRQ] Software Interrupt\n"); + asm volatile("csrc sip, %0" : : "r"(1 << 1)); + break; + + case 5: + Drivers::uart_puts("[IRQ] Timer Interrupt\n"); + + break; + + case 9: + Drivers::uart_puts("[IRQ] External Interrupt\n"); + break; + + default: + Drivers::uart_puts("[IRQ] Unknown Interrupt: "); + Drivers::print_hex(cause_code); + Drivers::uart_puts("\n"); + break; + } + } + else + { + switch (scause) + { + case 8: + Drivers::uart_puts("[Syscall] ecall for User Mode\n"); + tf->epc += 4; + break; + + case 12: + case 13: + case 15: + Drivers::uart_puts("\n--- PAGE FAULT ---\n"); + Drivers::uart_puts("Cause Code: "); + Drivers::print_hex(scause); + Drivers::uart_puts("\n"); + Drivers::uart_puts("Fault Addr (stval): "); + Drivers::print_hex(stval); + Drivers::uart_puts("\n"); + Drivers::uart_puts("Instruction (sepc): "); + Drivers::print_hex(sepc); + Drivers::uart_puts("\n"); + + if (stval == 0) + { + panic("Null Pointer Dereference!"); + } + else if (stval < 0x80000000) + { + panic("Invalid Low Memory Access!"); + } + else + { + panic("Segmentation Fault (Unmapped Area)"); + } + break; + + case 2: + Drivers::uart_puts("\n--- ILLEGAL INSTRUCTION ---\n"); + Drivers::uart_puts("Instruction (sepc): "); + Drivers::print_hex(sepc); + Drivers::uart_puts("\n"); + panic("CPU encountered an unknown opcode"); + break; + + default: + Drivers::uart_puts("\n--- UNHANDLED EXCEPTION ---\n"); + Drivers::uart_puts("Cause: "); + Drivers::print_hex(scause); + Drivers::uart_puts("\n"); + Drivers::uart_puts("sepc: "); + Drivers::print_hex(sepc); + Drivers::uart_puts("\n"); + panic("System Halt"); + break; + } + } + } +} \ No newline at end of file diff --git a/src/kernel/trap/trap.S b/src/kernel/trap/trap.S new file mode 100644 index 0000000..ffce52a --- /dev/null +++ b/src/kernel/trap/trap.S @@ -0,0 +1,87 @@ +.section .text +.global kernelvec +.align 4 + +kernelvec: + + addi sp, sp, -256 + + sd ra, 40(sp) + sd sp, 48(sp) + sd gp, 56(sp) + sd tp, 64(sp) + sd t0, 72(sp) + sd t1, 80(sp) + sd t2, 88(sp) + sd s0, 96(sp) + sd s1, 104(sp) + sd a0, 112(sp) + sd a1, 120(sp) + sd a2, 128(sp) + sd a3, 136(sp) + sd a4, 144(sp) + sd a5, 152(sp) + sd a6, 160(sp) + sd a7, 168(sp) + sd s2, 176(sp) + sd s3, 184(sp) + sd s4, 192(sp) + sd s5, 200(sp) + sd s6, 208(sp) + sd s7, 216(sp) + sd s8, 224(sp) + sd s9, 232(sp) + sd s10, 240(sp) + sd s11, 248(sp) + sd t3, 256(sp) + sd t4, 264(sp) + sd t5, 272(sp) + sd t6, 280(sp) + + csrr t0, sepc + csrr t1, sstatus + sd t0, 24(sp) # Trapframe.epc + sd t1, 32(sp) # Trapframe.kernel_hartid + + mv a0, sp + call kerneltrap + + ld t0, 24(sp) + ld t1, 32(sp) + csrw sepc, t0 + csrw sstatus, t1 + + ld ra, 40(sp) + ld gp, 56(sp) + ld tp, 64(sp) + ld t0, 72(sp) + ld t1, 80(sp) + ld t2, 88(sp) + ld s0, 96(sp) + ld s1, 104(sp) + ld a0, 112(sp) + ld a1, 120(sp) + ld a2, 128(sp) + ld a3, 136(sp) + ld a4, 144(sp) + ld a5, 152(sp) + ld a6, 160(sp) + ld a7, 168(sp) + ld s2, 176(sp) + ld s3, 184(sp) + ld s4, 192(sp) + ld s5, 200(sp) + ld s6, 208(sp) + ld s7, 216(sp) + ld s8, 224(sp) + ld s9, 232(sp) + ld s10, 240(sp) + ld s11, 248(sp) + ld t3, 256(sp) + ld t4, 264(sp) + ld t5, 272(sp) + ld t6, 280(sp) + + addi sp, sp, 256 + + sret \ No newline at end of file -- cgit v1.2.3