diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2025-12-31 18:00:55 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2025-12-31 18:00:55 +0800 |
| commit | dbba25aa24f86c1f8c3a0589c82985840adc1b6b (patch) | |
| tree | 11d1d7ee552030d953db9f911d5af6e079291c47 /src/kernel/trap | |
| parent | 7759eef8cdac79028dd5b468bd9ce0cf1c12b162 (diff) | |
| download | lume-dbba25aa24f86c1f8c3a0589c82985840adc1b6b.tar.gz lume-dbba25aa24f86c1f8c3a0589c82985840adc1b6b.tar.xz | |
dev:Refactor Memory Management and Process Management
Diffstat (limited to 'src/kernel/trap')
| -rw-r--r-- | src/kernel/trap/handler.cc | 242 |
1 files changed, 119 insertions, 123 deletions
diff --git a/src/kernel/trap/handler.cc b/src/kernel/trap/handler.cc index 14ef4c5..f7f8725 100644 --- a/src/kernel/trap/handler.cc +++ b/src/kernel/trap/handler.cc @@ -1,13 +1,16 @@ #include "kernel/trap.h" -#include "common/types.h" -#include "drivers/uart.h" +#include "kernel/riscv.h" #include "kernel/proc.h" -#include "kernel/timer.h" +#include "drivers/uart.h" #include "kernel/syscall.h" -#include "kernel/riscv.h" +#include "kernel/mm.h" +#include "kernel/timer.h" +#include "lib/string.h" -extern void usertrapret(); -extern void forkret(); + +extern "C" void kernelvec(); + +// Handle Function void panic(const char *s) { @@ -18,160 +21,153 @@ void panic(const char *s) ; } +// Trap Implementation + namespace Trap { void init() { - uint64 stvec_val = (uint64)kernelvec; - asm volatile("csrw stvec, %0" : : "r"(stvec_val)); + Drivers::uart_puts("[Trap] Global init done.\n"); + } - uint64 sstatus; - asm volatile("csrr %0, sstatus" : "=r"(sstatus)); - sstatus &= ~(1L << 1); - asm volatile("csrw sstatus, %0" : : "r"(sstatus)); + // Each CPU core needs to call this function when starting to set its own stvec + void inithart() + { + w_stvec((uint64)kernelvec); - Drivers::uart_puts("[Trap] Initialized stvec to: "); - Drivers::print_hex(stvec_val); - Drivers::uart_puts("\n"); + // Ensure that the S-Mode interrupt enable bit (SIE) is cleared during initialization + // Interrupt enabling will be done by the scheduler when the first process runs + w_sstatus(r_sstatus() & ~SSTATUS_SIE); + + // Enable the external interrupt, clock interrupt, and software interrupt bits in S-Mode (in SIE register) + uint64 sie = r_sie(); + sie |= SIE_SEIE | SIE_STIE | SIE_SSIE; + w_sie(sie); + + Drivers::uart_puts("[Trap] Hart initialized (stvec set).\n"); } - extern "C" void kerneltrap(struct Trapframe *tf) + // Device Interrupt Check + int devintr() { - uint64 scause, stval, sepc; + uint64 scause = r_scause(); - asm volatile("csrr %0, scause" : "=r"(scause)); - asm volatile("csrr %0, stval" : "=r"(stval)); - asm volatile("csrr %0, sepc" : "=r"(sepc)); + bool is_interrupt = (scause & 0x8000000000000000L) != 0; + uint64 code = scause & 0xff; - if (scause & (1L << 63)) + if (is_interrupt && code == 9) { - uint64 cause_code = scause & 0x7FFFFFFFFFFFFFFFL; - switch (cause_code) - { - case 1: - Drivers::uart_puts("[IRQ] Software Interrupt (Unexpected)\n"); - break; - - case 5: - Drivers::uart_puts("[IRQ] Timer Interrupt\n"); - Timer::set_next_trigger(); - ProcManager::yield(); - 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; - } + // Supervisor External Interrupt (IRQ 9) + return 1; } - else + else if (is_interrupt && code == 5) { - switch (scause) - { - case 8: - Drivers::uart_puts("[Syscall] ecall from Kernel Mode? Panic.\n"); - panic("Kernel Ecall"); - 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; - } + // Supervisor Timer Interrupt (IRQ 5) + Timer::set_next_trigger(); + // w_sip(r_sip() & ~2); + return 2; } + + return 0; } } +// Exception Handling Entry + +extern "C" void kerneltrap(struct Trapframe *tf) +{ + uint64 sepc = r_sepc(); + uint64 sstatus = r_sstatus(); + uint64 scause = r_scause(); + + if ((sstatus & SSTATUS_SPP) == 0) + panic("kerneltrap: not from supervisor mode"); + + if (intr_get() != 0) + panic("kerneltrap: interrupts enabled"); + + if (Trap::devintr() == 0) + { + Drivers::uart_puts("\n--- KERNEL EXCEPTION ---\n"); + Drivers::uart_puts("scause: "); + Drivers::print_hex(scause); + Drivers::uart_puts("\n"); + Drivers::uart_puts("sepc: "); + Drivers::print_hex(sepc); + Drivers::uart_puts("\n"); + Drivers::uart_puts("stval: "); + Drivers::print_hex(r_stval()); + Drivers::uart_puts("\n"); + panic("kerneltrap exception"); + } + + w_sepc(sepc); + w_sstatus(sstatus); +} + extern "C" void usertrap() { - asm volatile("csrw stvec, %0" : : "r"(Trap::kernelvec)); + // Drivers::uart_puts("[Debug] Entered usertrap!\n"); + int which_dev = 0; - uint64 scause; - asm volatile("csrr %0, scause" : "=r"(scause)); + if ((r_sstatus() & SSTATUS_SPP) != 0) + panic("usertrap: not from user mode"); + + w_stvec((uint64)kernelvec); struct Proc *p = myproc(); - - extern struct Proc procs[]; if (!p) - { - for (int i = 0; i < 10; ++i) - if (procs[i].state == RUNNING) - p = &procs[i]; - } + panic("usertrap: no process"); - uint64 sepc; - asm volatile("csrr %0, sepc" : "=r"(sepc)); - p->tf->epc = sepc; + p->tf->epc = r_sepc(); - if(scause == 8) + uint64 scause = r_scause(); + uint64 stval = r_stval(); + + if (scause == 8) // Syscall { - intr_on(); + if (p->state == ZOMBIE) + ProcManager::exit(-1); p->tf->epc += 4; - + intr_on(); syscall(); - intr_off(); } - else if ((scause & (1L << 63)) && (scause & 0xF) == 5) + else if (scause == 15) // Store Page Fault { - Drivers::uart_puts("\nTick\n"); - Timer::set_next_trigger(); - ProcManager::yield(); + if (VM::handle_cow_fault(p->pagetable, PGROUNDDOWN(stval)) != 0) + { + Drivers::uart_puts("usertrap: cow failed at "); + Drivers::print_hex(stval); + Drivers::uart_puts("\n"); + p->state = ZOMBIE; + ProcManager::exit(-1); + } + } + else if ((which_dev = Trap::devintr()) != 0) + { + if (which_dev == 2) + { + ProcManager::yield(); + } } else { - Drivers::uart_puts("Unexpected User Trap!\n"); + Drivers::uart_puts("\nusertrap(): unexpected scause "); Drivers::print_hex(scause); - while (1) - ; + Drivers::uart_puts(" pid="); + Drivers::uart_put_int(p->pid); + Drivers::uart_puts(" sepc="); + Drivers::print_hex(p->tf->epc); + Drivers::uart_puts(" stval="); + Drivers::print_hex(stval); + Drivers::uart_puts("\n"); + p->state = ZOMBIE; + ProcManager::exit(-1); } + if (p->state == ZOMBIE) + ProcManager::exit(-1); + usertrapret(); }
\ No newline at end of file |
