From 6043cc0d5c1960dbb8f49ee6ee901433b9b06a6b Mon Sep 17 00:00:00 2001 From: StepanovPlaton Date: Mon, 9 Feb 2026 11:48:24 +0400 Subject: [PATCH] Add exception handler --- src/kernel.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/kernel.h | 49 ++++++++++++++++++++++++++++- src/run.sh | 3 +- 3 files changed, 137 insertions(+), 3 deletions(-) mode change 100644 => 100755 src/run.sh diff --git a/src/kernel.c b/src/kernel.c index 8334982..4c05fcc 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -21,9 +21,95 @@ struct sbiret sbi_call(long arg0, long arg1, long arg2, long arg3, long arg4, void putchar(char ch) { sbi_call(ch, 0, 0, 0, 0, 0, 0, 1); } +__attribute__((naked)) __attribute__((aligned(4))) void kernel_entry(void) { + __asm__ __volatile__("csrw sscratch, sp\n" + "addi sp, sp, -4 * 31\n" + "sw ra, 4 * 0(sp)\n" + "sw gp, 4 * 1(sp)\n" + "sw tp, 4 * 2(sp)\n" + "sw t0, 4 * 3(sp)\n" + "sw t1, 4 * 4(sp)\n" + "sw t2, 4 * 5(sp)\n" + "sw t3, 4 * 6(sp)\n" + "sw t4, 4 * 7(sp)\n" + "sw t5, 4 * 8(sp)\n" + "sw t6, 4 * 9(sp)\n" + "sw a0, 4 * 10(sp)\n" + "sw a1, 4 * 11(sp)\n" + "sw a2, 4 * 12(sp)\n" + "sw a3, 4 * 13(sp)\n" + "sw a4, 4 * 14(sp)\n" + "sw a5, 4 * 15(sp)\n" + "sw a6, 4 * 16(sp)\n" + "sw a7, 4 * 17(sp)\n" + "sw s0, 4 * 18(sp)\n" + "sw s1, 4 * 19(sp)\n" + "sw s2, 4 * 20(sp)\n" + "sw s3, 4 * 21(sp)\n" + "sw s4, 4 * 22(sp)\n" + "sw s5, 4 * 23(sp)\n" + "sw s6, 4 * 24(sp)\n" + "sw s7, 4 * 25(sp)\n" + "sw s8, 4 * 26(sp)\n" + "sw s9, 4 * 27(sp)\n" + "sw s10, 4 * 28(sp)\n" + "sw s11, 4 * 29(sp)\n" + + "csrr a0, sscratch\n" + "sw a0, 4 * 30(sp)\n" + + "mv a0, sp\n" + "call handle_trap\n" + + "lw ra, 4 * 0(sp)\n" + "lw gp, 4 * 1(sp)\n" + "lw tp, 4 * 2(sp)\n" + "lw t0, 4 * 3(sp)\n" + "lw t1, 4 * 4(sp)\n" + "lw t2, 4 * 5(sp)\n" + "lw t3, 4 * 6(sp)\n" + "lw t4, 4 * 7(sp)\n" + "lw t5, 4 * 8(sp)\n" + "lw t6, 4 * 9(sp)\n" + "lw a0, 4 * 10(sp)\n" + "lw a1, 4 * 11(sp)\n" + "lw a2, 4 * 12(sp)\n" + "lw a3, 4 * 13(sp)\n" + "lw a4, 4 * 14(sp)\n" + "lw a5, 4 * 15(sp)\n" + "lw a6, 4 * 16(sp)\n" + "lw a7, 4 * 17(sp)\n" + "lw s0, 4 * 18(sp)\n" + "lw s1, 4 * 19(sp)\n" + "lw s2, 4 * 20(sp)\n" + "lw s3, 4 * 21(sp)\n" + "lw s4, 4 * 22(sp)\n" + "lw s5, 4 * 23(sp)\n" + "lw s6, 4 * 24(sp)\n" + "lw s7, 4 * 25(sp)\n" + "lw s8, 4 * 26(sp)\n" + "lw s9, 4 * 27(sp)\n" + "lw s10, 4 * 28(sp)\n" + "lw s11, 4 * 29(sp)\n" + "lw sp, 4 * 30(sp)\n" + "sret\n"); +} + +void handle_trap(struct trap_frame *f) { + uint32_t scause = READ_CSR(scause); + uint32_t stval = READ_CSR(stval); + uint32_t user_pc = READ_CSR(sepc); + + PANIC("unexpected trap scause=%x, stval=%x, sepc=%x\n", scause, stval, + user_pc); +} + void kernel_main(void) { memset(__bss, 0, (size_t)__bss_end - (size_t)__bss); + WRITE_CSR(stvec, (uint32_t)kernel_entry); + __asm__ __volatile__("unimp"); + PANIC("booted!"); printf("unreachable here!\n"); } @@ -33,4 +119,4 @@ __attribute__((section(".text.boot"))) __attribute__((naked)) void boot(void) { "j kernel_main\n" : : [stack_top] "r"(__stack_top)); -} \ No newline at end of file +} diff --git a/src/kernel.h b/src/kernel.h index adbb4f0..0987469 100644 --- a/src/kernel.h +++ b/src/kernel.h @@ -14,4 +14,51 @@ struct sbiret { printf("PANIC: %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \ while (1) { \ } \ - } while (0) \ No newline at end of file + } while (0) + +struct trap_frame { + uint32_t ra; + uint32_t gp; + uint32_t tp; + uint32_t t0; + uint32_t t1; + uint32_t t2; + uint32_t t3; + uint32_t t4; + uint32_t t5; + uint32_t t6; + uint32_t a0; + uint32_t a1; + uint32_t a2; + uint32_t a3; + uint32_t a4; + uint32_t a5; + uint32_t a6; + uint32_t a7; + uint32_t s0; + uint32_t s1; + uint32_t s2; + uint32_t s3; + uint32_t s4; + uint32_t s5; + uint32_t s6; + uint32_t s7; + uint32_t s8; + uint32_t s9; + uint32_t s10; + uint32_t s11; + uint32_t sp; +} __attribute__((packed)); + +#define READ_CSR(reg) \ + ({ \ + unsigned long __tmp; \ + __asm__ __volatile__("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; \ + }) + +#define WRITE_CSR(reg, value) \ + do { \ + uint32_t __tmp = (value); \ + __asm__ __volatile__("csrw " #reg ", %0" ::"r"(__tmp)); \ + } while (0) diff --git a/src/run.sh b/src/run.sh old mode 100644 new mode 100755 index ccbf846..8bf3a3c --- a/src/run.sh +++ b/src/run.sh @@ -1,4 +1,5 @@ #!/bin/bash set -xue -qemu-system-riscv32 -machine virt -bios default -nographic -serial mon:stdio --no-reboot -kernel kernel.elf \ No newline at end of file +make kernel +qemu-system-riscv32 -machine virt -bios default -nographic -serial mon:stdio --no-reboot -kernel kernel.elf