From: jsg Date: Wed, 5 May 2021 00:53:08 +0000 (+0000) Subject: rename trap.S exception.S and trap_machdep.c trap.c to match other archs X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=3356529948a21cdb5d7ebee259b388465015139c;p=openbsd rename trap.S exception.S and trap_machdep.c trap.c to match other archs ok kettenis@ --- diff --git a/sys/arch/riscv64/conf/Makefile.riscv64 b/sys/arch/riscv64/conf/Makefile.riscv64 index 6d09a49aa8a..204cb8991c5 100644 --- a/sys/arch/riscv64/conf/Makefile.riscv64 +++ b/sys/arch/riscv64/conf/Makefile.riscv64 @@ -144,7 +144,7 @@ depend obj: locore0.o: ${_archdir}/${_arch}/locore0.S assym.h copy.o copystr.o copyinout.o: assym.h pagezero.o: assym.h -cpuswitch.o trap.o support.o: assym.h +cpuswitch.o exception.o support.o: assym.h locore.o trampoline.o: assym.h hardlink-obsd: diff --git a/sys/arch/riscv64/conf/files.riscv64 b/sys/arch/riscv64/conf/files.riscv64 index 2294c06354b..f0d0db59a91 100644 --- a/sys/arch/riscv64/conf/files.riscv64 +++ b/sys/arch/riscv64/conf/files.riscv64 @@ -18,7 +18,7 @@ file arch/riscv64/riscv64/disksubr.c disk file arch/riscv64/riscv64/locore.S file arch/riscv64/riscv64/copy.S file arch/riscv64/riscv64/copystr.S -file arch/riscv64/riscv64/trap.S +file arch/riscv64/riscv64/exception.S file arch/riscv64/riscv64/cpuswitch.S file arch/riscv64/riscv64/machdep.c file arch/riscv64/riscv64/intr.c @@ -31,7 +31,7 @@ file arch/riscv64/riscv64/softintr.c file arch/riscv64/riscv64/support.S file arch/riscv64/riscv64/syscall.c file arch/riscv64/riscv64/pagezero.S -file arch/riscv64/riscv64/trap_machdep.c +file arch/riscv64/riscv64/trap.c file arch/riscv64/riscv64/sbi.c file arch/riscv64/riscv64/cpufunc_asm.S file arch/riscv64/riscv64/fpu.c diff --git a/sys/arch/riscv64/riscv64/exception.S b/sys/arch/riscv64/riscv64/exception.S new file mode 100644 index 00000000000..7d461ff06e2 --- /dev/null +++ b/sys/arch/riscv64/riscv64/exception.S @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2020 Mengshi Li + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "assym.h" +#include +#include +#include + +.macro save_registers el + addi sp, sp, -(TRAPFRAME_SIZEOF) + + sd ra, (TF_RA)(sp) + +.if \el == 0 /* We came from userspace. */ + sd gp, (TF_GP)(sp) +.option push +.option norelax + /* Load the kernel's global pointer */ + la gp, __global_pointer$ +.option pop + + /* Load our pcpu */ + sd tp, (TF_TP)(sp) + ld tp, (TRAPFRAME_SIZEOF)(sp) +.endif + + sd t0, (TF_T + 0 * 8)(sp) + sd t1, (TF_T + 1 * 8)(sp) + sd t2, (TF_T + 2 * 8)(sp) + sd t3, (TF_T + 3 * 8)(sp) + sd t4, (TF_T + 4 * 8)(sp) + sd t5, (TF_T + 5 * 8)(sp) + sd t6, (TF_T + 6 * 8)(sp) + + sd s0, (TF_S + 0 * 8)(sp) + sd s1, (TF_S + 1 * 8)(sp) + sd s2, (TF_S + 2 * 8)(sp) + sd s3, (TF_S + 3 * 8)(sp) + sd s4, (TF_S + 4 * 8)(sp) + sd s5, (TF_S + 5 * 8)(sp) + sd s6, (TF_S + 6 * 8)(sp) + sd s7, (TF_S + 7 * 8)(sp) + sd s8, (TF_S + 8 * 8)(sp) + sd s9, (TF_S + 9 * 8)(sp) + sd s10, (TF_S + 10 * 8)(sp) + sd s11, (TF_S + 11 * 8)(sp) + + sd a0, (TF_A + 0 * 8)(sp) + sd a1, (TF_A + 1 * 8)(sp) + sd a2, (TF_A + 2 * 8)(sp) + sd a3, (TF_A + 3 * 8)(sp) + sd a4, (TF_A + 4 * 8)(sp) + sd a5, (TF_A + 5 * 8)(sp) + sd a6, (TF_A + 6 * 8)(sp) + sd a7, (TF_A + 7 * 8)(sp) + +.if \el == 1 + /* Store kernel sp */ + li t1, TRAPFRAME_SIZEOF + add t0, sp, t1 + sd t0, (TF_SP)(sp) +.else + /* Store user sp */ + csrr t0, sscratch + sd t0, (TF_SP)(sp) +.endif + li t0, 0 + csrw sscratch, t0 + csrr t0, sepc + sd t0, (TF_SEPC)(sp) + csrr t0, sstatus + sd t0, (TF_SSTATUS)(sp) + csrr t0, stval + sd t0, (TF_STVAL)(sp) + csrr t0, scause + sd t0, (TF_SCAUSE)(sp) +.endm + +.macro restore_registers el + ld t0, (TF_SSTATUS)(sp) +.if \el == 0 + /* Ensure user interrupts will be enabled on eret */ + li t1, SSTATUS_SPIE + or t0, t0, t1 +.else + /* + * Disable interrupts for supervisor mode exceptions. + * For user mode exceptions we have already done this + * in do_ast. + */ + li t1, ~SSTATUS_SIE + and t0, t0, t1 +.endif + csrw sstatus, t0 + + ld t0, (TF_SEPC)(sp) + csrw sepc, t0 + +.if \el == 0 + /* We go to userspace. Load user sp */ + ld t0, (TF_SP)(sp) + csrw sscratch, t0 + + /* Store our pcpu */ + sd tp, (TRAPFRAME_SIZEOF)(sp) + ld tp, (TF_TP)(sp) + + /* And restore the user's global pointer */ + ld gp, (TF_GP)(sp) +.endif + + ld ra, (TF_RA)(sp) + + ld t0, (TF_T + 0 * 8)(sp) + ld t1, (TF_T + 1 * 8)(sp) + ld t2, (TF_T + 2 * 8)(sp) + ld t3, (TF_T + 3 * 8)(sp) + ld t4, (TF_T + 4 * 8)(sp) + ld t5, (TF_T + 5 * 8)(sp) + ld t6, (TF_T + 6 * 8)(sp) + + ld s0, (TF_S + 0 * 8)(sp) + ld s1, (TF_S + 1 * 8)(sp) + ld s2, (TF_S + 2 * 8)(sp) + ld s3, (TF_S + 3 * 8)(sp) + ld s4, (TF_S + 4 * 8)(sp) + ld s5, (TF_S + 5 * 8)(sp) + ld s6, (TF_S + 6 * 8)(sp) + ld s7, (TF_S + 7 * 8)(sp) + ld s8, (TF_S + 8 * 8)(sp) + ld s9, (TF_S + 9 * 8)(sp) + ld s10, (TF_S + 10 * 8)(sp) + ld s11, (TF_S + 11 * 8)(sp) + + ld a0, (TF_A + 0 * 8)(sp) + ld a1, (TF_A + 1 * 8)(sp) + ld a2, (TF_A + 2 * 8)(sp) + ld a3, (TF_A + 3 * 8)(sp) + ld a4, (TF_A + 4 * 8)(sp) + ld a5, (TF_A + 5 * 8)(sp) + ld a6, (TF_A + 6 * 8)(sp) + ld a7, (TF_A + 7 * 8)(sp) + + addi sp, sp, (TRAPFRAME_SIZEOF) +.endm + +.macro do_ast + /* Disable interrupts */ + csrr a4, sstatus +1: + csrci sstatus, (SSTATUS_SIE) + + /* Check for astpending */ + ld a1, CI_CURPROC(tp) + beqz a1, 2f + lw a2, P_ASTPENDING(a1) + beqz a2, 2f + + sw x0, P_ASTPENDING(a1) + + /* Restore interrupts */ + csrw sstatus, a4 + + /* handle the ast */ + mv a0, sp + la t0, _C_LABEL(ast) + jalr t0 + j 1b +2: +.endm + +ENTRY(cpu_trap_handler) + csrrw sp, sscratch, sp + beqz sp, 1f + /* User mode detected */ + j cpu_trap_handler_user +1: + /* Supervisor mode detected */ + csrrw sp, sscratch, sp + j cpu_trap_handler_supervisor +END(cpu_trap_handler) + +ENTRY(cpu_trap_handler_supervisor) + save_registers 1 + mv a0, sp + call _C_LABEL(do_trap_supervisor) + restore_registers 1 + sret +END(cpu_trap_handler_supervisor) + +ENTRY(cpu_trap_handler_user) + save_registers 0 + mv a0, sp + call _C_LABEL(do_trap_user) + do_ast + restore_registers 0 + csrrw sp, sscratch, sp + sret +END(cpu_trap_handler_user) + +ENTRY(syscall_return) + do_ast + restore_registers 0 + csrrw sp, sscratch, sp + sret +END(syscall_return) diff --git a/sys/arch/riscv64/riscv64/trap.S b/sys/arch/riscv64/riscv64/trap.S deleted file mode 100644 index 7d461ff06e2..00000000000 --- a/sys/arch/riscv64/riscv64/trap.S +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) 2020 Mengshi Li - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "assym.h" -#include -#include -#include - -.macro save_registers el - addi sp, sp, -(TRAPFRAME_SIZEOF) - - sd ra, (TF_RA)(sp) - -.if \el == 0 /* We came from userspace. */ - sd gp, (TF_GP)(sp) -.option push -.option norelax - /* Load the kernel's global pointer */ - la gp, __global_pointer$ -.option pop - - /* Load our pcpu */ - sd tp, (TF_TP)(sp) - ld tp, (TRAPFRAME_SIZEOF)(sp) -.endif - - sd t0, (TF_T + 0 * 8)(sp) - sd t1, (TF_T + 1 * 8)(sp) - sd t2, (TF_T + 2 * 8)(sp) - sd t3, (TF_T + 3 * 8)(sp) - sd t4, (TF_T + 4 * 8)(sp) - sd t5, (TF_T + 5 * 8)(sp) - sd t6, (TF_T + 6 * 8)(sp) - - sd s0, (TF_S + 0 * 8)(sp) - sd s1, (TF_S + 1 * 8)(sp) - sd s2, (TF_S + 2 * 8)(sp) - sd s3, (TF_S + 3 * 8)(sp) - sd s4, (TF_S + 4 * 8)(sp) - sd s5, (TF_S + 5 * 8)(sp) - sd s6, (TF_S + 6 * 8)(sp) - sd s7, (TF_S + 7 * 8)(sp) - sd s8, (TF_S + 8 * 8)(sp) - sd s9, (TF_S + 9 * 8)(sp) - sd s10, (TF_S + 10 * 8)(sp) - sd s11, (TF_S + 11 * 8)(sp) - - sd a0, (TF_A + 0 * 8)(sp) - sd a1, (TF_A + 1 * 8)(sp) - sd a2, (TF_A + 2 * 8)(sp) - sd a3, (TF_A + 3 * 8)(sp) - sd a4, (TF_A + 4 * 8)(sp) - sd a5, (TF_A + 5 * 8)(sp) - sd a6, (TF_A + 6 * 8)(sp) - sd a7, (TF_A + 7 * 8)(sp) - -.if \el == 1 - /* Store kernel sp */ - li t1, TRAPFRAME_SIZEOF - add t0, sp, t1 - sd t0, (TF_SP)(sp) -.else - /* Store user sp */ - csrr t0, sscratch - sd t0, (TF_SP)(sp) -.endif - li t0, 0 - csrw sscratch, t0 - csrr t0, sepc - sd t0, (TF_SEPC)(sp) - csrr t0, sstatus - sd t0, (TF_SSTATUS)(sp) - csrr t0, stval - sd t0, (TF_STVAL)(sp) - csrr t0, scause - sd t0, (TF_SCAUSE)(sp) -.endm - -.macro restore_registers el - ld t0, (TF_SSTATUS)(sp) -.if \el == 0 - /* Ensure user interrupts will be enabled on eret */ - li t1, SSTATUS_SPIE - or t0, t0, t1 -.else - /* - * Disable interrupts for supervisor mode exceptions. - * For user mode exceptions we have already done this - * in do_ast. - */ - li t1, ~SSTATUS_SIE - and t0, t0, t1 -.endif - csrw sstatus, t0 - - ld t0, (TF_SEPC)(sp) - csrw sepc, t0 - -.if \el == 0 - /* We go to userspace. Load user sp */ - ld t0, (TF_SP)(sp) - csrw sscratch, t0 - - /* Store our pcpu */ - sd tp, (TRAPFRAME_SIZEOF)(sp) - ld tp, (TF_TP)(sp) - - /* And restore the user's global pointer */ - ld gp, (TF_GP)(sp) -.endif - - ld ra, (TF_RA)(sp) - - ld t0, (TF_T + 0 * 8)(sp) - ld t1, (TF_T + 1 * 8)(sp) - ld t2, (TF_T + 2 * 8)(sp) - ld t3, (TF_T + 3 * 8)(sp) - ld t4, (TF_T + 4 * 8)(sp) - ld t5, (TF_T + 5 * 8)(sp) - ld t6, (TF_T + 6 * 8)(sp) - - ld s0, (TF_S + 0 * 8)(sp) - ld s1, (TF_S + 1 * 8)(sp) - ld s2, (TF_S + 2 * 8)(sp) - ld s3, (TF_S + 3 * 8)(sp) - ld s4, (TF_S + 4 * 8)(sp) - ld s5, (TF_S + 5 * 8)(sp) - ld s6, (TF_S + 6 * 8)(sp) - ld s7, (TF_S + 7 * 8)(sp) - ld s8, (TF_S + 8 * 8)(sp) - ld s9, (TF_S + 9 * 8)(sp) - ld s10, (TF_S + 10 * 8)(sp) - ld s11, (TF_S + 11 * 8)(sp) - - ld a0, (TF_A + 0 * 8)(sp) - ld a1, (TF_A + 1 * 8)(sp) - ld a2, (TF_A + 2 * 8)(sp) - ld a3, (TF_A + 3 * 8)(sp) - ld a4, (TF_A + 4 * 8)(sp) - ld a5, (TF_A + 5 * 8)(sp) - ld a6, (TF_A + 6 * 8)(sp) - ld a7, (TF_A + 7 * 8)(sp) - - addi sp, sp, (TRAPFRAME_SIZEOF) -.endm - -.macro do_ast - /* Disable interrupts */ - csrr a4, sstatus -1: - csrci sstatus, (SSTATUS_SIE) - - /* Check for astpending */ - ld a1, CI_CURPROC(tp) - beqz a1, 2f - lw a2, P_ASTPENDING(a1) - beqz a2, 2f - - sw x0, P_ASTPENDING(a1) - - /* Restore interrupts */ - csrw sstatus, a4 - - /* handle the ast */ - mv a0, sp - la t0, _C_LABEL(ast) - jalr t0 - j 1b -2: -.endm - -ENTRY(cpu_trap_handler) - csrrw sp, sscratch, sp - beqz sp, 1f - /* User mode detected */ - j cpu_trap_handler_user -1: - /* Supervisor mode detected */ - csrrw sp, sscratch, sp - j cpu_trap_handler_supervisor -END(cpu_trap_handler) - -ENTRY(cpu_trap_handler_supervisor) - save_registers 1 - mv a0, sp - call _C_LABEL(do_trap_supervisor) - restore_registers 1 - sret -END(cpu_trap_handler_supervisor) - -ENTRY(cpu_trap_handler_user) - save_registers 0 - mv a0, sp - call _C_LABEL(do_trap_user) - do_ast - restore_registers 0 - csrrw sp, sscratch, sp - sret -END(cpu_trap_handler_user) - -ENTRY(syscall_return) - do_ast - restore_registers 0 - csrrw sp, sscratch, sp - sret -END(syscall_return) diff --git a/sys/arch/riscv64/riscv64/trap.c b/sys/arch/riscv64/riscv64/trap.c new file mode 100644 index 00000000000..fd84ee9a6ae --- /dev/null +++ b/sys/arch/riscv64/riscv64/trap.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2020 Shivam Waghela + * Copyright (c) 2020 Brian Bamsch + * Copyright (c) 2020 Mengshi Li + * Copyright (c) 2015 Dale Rahn + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Called from exception.S */ +void do_trap_supervisor(struct trapframe *); +void do_trap_user(struct trapframe *); + +static void data_abort(struct trapframe *, int); + +static void +dump_regs(struct trapframe *frame) +{ + int n; + int i; + + n = (sizeof(frame->tf_t) / sizeof(frame->tf_t[0])); + for (i = 0; i < n; i++) + printf("t[%d] == 0x%016lx\n", i, frame->tf_t[i]); + + n = (sizeof(frame->tf_s) / sizeof(frame->tf_s[0])); + for (i = 0; i < n; i++) + printf("s[%d] == 0x%016lx\n", i, frame->tf_s[i]); + + n = (sizeof(frame->tf_a) / sizeof(frame->tf_a[0])); + for (i = 0; i < n; i++) + printf("a[%d] == 0x%016lx\n", i, frame->tf_a[i]); + + printf("sepc == 0x%016lx\n", frame->tf_sepc); + printf("sstatus == 0x%016lx\n", frame->tf_sstatus); +} + +void +do_trap_supervisor(struct trapframe *frame) +{ + uint64_t exception; + + /* Ensure we came from supervisor mode, interrupts disabled */ + KASSERTMSG((csr_read(sstatus) & (SSTATUS_SPP | SSTATUS_SIE)) == + SSTATUS_SPP, "Came from S mode with interrupts enabled"); + + if (frame->tf_scause & EXCP_INTR) { + /* Interrupt */ + riscv_cpu_intr(frame); + return; + } + + exception = (frame->tf_scause & EXCP_MASK); + switch(exception) { + case EXCP_FAULT_LOAD: + case EXCP_FAULT_STORE: + case EXCP_FAULT_FETCH: + case EXCP_STORE_PAGE_FAULT: + case EXCP_LOAD_PAGE_FAULT: + data_abort(frame, 0); + break; + case EXCP_BREAKPOINT: +#ifdef DDB + // kdb_trap(exception, 0, frame); + db_trapper(frame->tf_sepc,0/*XXX*/, frame, exception); +#else + dump_regs(frame); + panic("No debugger in kernel.\n"); +#endif + break; + case EXCP_ILLEGAL_INSTRUCTION: + dump_regs(frame); + panic("Illegal instruction at 0x%016lx\n", frame->tf_sepc); + break; + default: + dump_regs(frame); + panic("Unknown kernel exception %llx trap value %lx\n", + exception, frame->tf_stval); + } +} + + +void +do_trap_user(struct trapframe *frame) +{ + uint64_t exception; + union sigval sv; + struct proc *p; + struct pcb *pcb; + + p = curcpu()->ci_curproc; + p->p_addr->u_pcb.pcb_tf = frame; + pcb = curcpu()->ci_curpcb; + + /* Ensure we came from usermode, interrupts disabled */ + KASSERTMSG((csr_read(sstatus) & (SSTATUS_SPP | SSTATUS_SIE)) == 0, + "Came from U mode with interrupts enabled"); + + /* Save fpu context before (possibly) calling interrupt handler. + * Could end up context switching in interrupt handler. + */ + fpu_save(p, frame); + + exception = (frame->tf_scause & EXCP_MASK); + if (frame->tf_scause & EXCP_INTR) { + /* Interrupt */ + riscv_cpu_intr(frame); + frame->tf_sstatus &= ~SSTATUS_FS_MASK; + if (pcb->pcb_fpcpu == curcpu() && curcpu()->ci_fpuproc == p) { + frame->tf_sstatus |= SSTATUS_FS_CLEAN; + } + return; + } + + enable_interrupts(); //XXX allow preemption? + +#if 0 // XXX Debug logging + printf( "do_trap_user: curproc: %p, sepc: %lx, ra: %lx frame: %p\n", + curcpu()->ci_curproc, frame->tf_sepc, frame->tf_ra, frame); +#endif + + switch(exception) { + case EXCP_FAULT_LOAD: + case EXCP_FAULT_STORE: + case EXCP_FAULT_FETCH: + case EXCP_STORE_PAGE_FAULT: + case EXCP_LOAD_PAGE_FAULT: + case EXCP_INST_PAGE_FAULT: + data_abort(frame, 1); + break; + case EXCP_USER_ECALL: + frame->tf_sepc += 4; /* Next instruction */ + svc_handler(frame); + break; + case EXCP_ILLEGAL_INSTRUCTION: + + if ((frame->tf_sstatus & SSTATUS_FS_MASK) == + SSTATUS_FS_OFF) { + if(fpu_valid_opcode(frame->tf_stval)) { + + /* XXX do this here or should it be in the + * trap handler in the restore path? + */ + fpu_load(p); + + frame->tf_sstatus &= ~SSTATUS_FS_MASK; + break; + } + } + printf("ILL at %lx scause %lx stval %lx\n", frame->tf_sepc, frame->tf_scause, frame->tf_stval); + sv.sival_ptr = (void *)frame->tf_stval; + trapsignal(p, SIGILL, 0, ILL_ILLTRP, sv); + userret(p); + break; + case EXCP_BREAKPOINT: + printf("BREAKPOINT\n"); + sv.sival_ptr = (void *)frame->tf_stval; + trapsignal(p, SIGTRAP, 0, TRAP_BRKPT, sv); + userret(p); + break; + default: + dump_regs(frame); + panic("Unknown userland exception %llx, trap value %lx\n", + exception, frame->tf_stval); + } + disable_interrupts(); /* XXX - ??? */ + /* now that we will not context switch again, + * see if we should enable FPU + */ + frame->tf_sstatus &= ~SSTATUS_FS_MASK; + if (pcb->pcb_fpcpu == curcpu() && curcpu()->ci_fpuproc == p) { + frame->tf_sstatus |= SSTATUS_FS_CLEAN; + //printf ("FPU enabled userland %p %p\n", + // pcb->pcb_fpcpu, curcpu()->ci_fpuproc); + } +} + +static void +data_abort(struct trapframe *frame, int usermode) +{ + struct vm_map *map; + uint64_t stval; + union sigval sv; + struct pcb *pcb; + vm_prot_t ftype; + vaddr_t va; + struct proc *p; + int error, sig, code, access_type; + + pcb = curcpu()->ci_curpcb; + p = curcpu()->ci_curproc; + stval = frame->tf_stval; + + va = trunc_page(stval); + + //if (va >= VM_MAXUSER_ADDRESS) + // curcpu()->ci_flush_bp(); + + if ((frame->tf_scause == EXCP_FAULT_STORE) || + (frame->tf_scause == EXCP_STORE_PAGE_FAULT)) { + access_type = PROT_WRITE; + } else if (frame->tf_scause == EXCP_INST_PAGE_FAULT) { + access_type = PROT_EXEC; + } else { + access_type = PROT_READ; + } + + ftype = VM_FAULT_INVALID; // should check for failed permissions. + + if (usermode) + map = &p->p_vmspace->vm_map; + else if (stval >= VM_MAX_USER_ADDRESS) + map = kernel_map; + else { + if (pcb->pcb_onfault == 0) + goto fatal; + map = &p->p_vmspace->vm_map; + } + + if (pmap_fault_fixup(map->pmap, va, ftype, usermode)) + goto done; + + KERNEL_LOCK(); + error = uvm_fault(map, va, ftype, access_type); + KERNEL_UNLOCK(); + + if (error != 0) { + if (usermode) { + if (error == ENOMEM) { + sig = SIGKILL; + code = 0; + } else if (error == EIO) { + sig = SIGBUS; + code = BUS_OBJERR; + } else if (error == EACCES) { + sig = SIGSEGV; + code = SEGV_ACCERR; + } else { + sig = SIGSEGV; + code = SEGV_MAPERR; + } + sv.sival_ptr = (void *)stval; + trapsignal(p, sig, 0, code, sv); + } else { + if (curcpu()->ci_idepth == 0 && pcb->pcb_onfault != 0) { + frame->tf_a[0] = error; + frame->tf_sepc = (register_t)pcb->pcb_onfault; + return; + } + goto fatal; + } + } + +done: + if (usermode) + userret(p); + return; + +fatal: + dump_regs(frame); + panic("Fatal page fault at %#lx: %#08lx", frame->tf_sepc, + (vaddr_t)sv.sival_ptr); +} + diff --git a/sys/arch/riscv64/riscv64/trap_machdep.c b/sys/arch/riscv64/riscv64/trap_machdep.c deleted file mode 100644 index c82f2a1b2c8..00000000000 --- a/sys/arch/riscv64/riscv64/trap_machdep.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (c) 2020 Shivam Waghela - * Copyright (c) 2020 Brian Bamsch - * Copyright (c) 2020 Mengshi Li - * Copyright (c) 2015 Dale Rahn - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Called from trap.S */ -void do_trap_supervisor(struct trapframe *); -void do_trap_user(struct trapframe *); - -static void data_abort(struct trapframe *, int); - -static void -dump_regs(struct trapframe *frame) -{ - int n; - int i; - - n = (sizeof(frame->tf_t) / sizeof(frame->tf_t[0])); - for (i = 0; i < n; i++) - printf("t[%d] == 0x%016lx\n", i, frame->tf_t[i]); - - n = (sizeof(frame->tf_s) / sizeof(frame->tf_s[0])); - for (i = 0; i < n; i++) - printf("s[%d] == 0x%016lx\n", i, frame->tf_s[i]); - - n = (sizeof(frame->tf_a) / sizeof(frame->tf_a[0])); - for (i = 0; i < n; i++) - printf("a[%d] == 0x%016lx\n", i, frame->tf_a[i]); - - printf("sepc == 0x%016lx\n", frame->tf_sepc); - printf("sstatus == 0x%016lx\n", frame->tf_sstatus); -} - -void -do_trap_supervisor(struct trapframe *frame) -{ - uint64_t exception; - - /* Ensure we came from supervisor mode, interrupts disabled */ - KASSERTMSG((csr_read(sstatus) & (SSTATUS_SPP | SSTATUS_SIE)) == - SSTATUS_SPP, "Came from S mode with interrupts enabled"); - - if (frame->tf_scause & EXCP_INTR) { - /* Interrupt */ - riscv_cpu_intr(frame); - return; - } - - exception = (frame->tf_scause & EXCP_MASK); - switch(exception) { - case EXCP_FAULT_LOAD: - case EXCP_FAULT_STORE: - case EXCP_FAULT_FETCH: - case EXCP_STORE_PAGE_FAULT: - case EXCP_LOAD_PAGE_FAULT: - data_abort(frame, 0); - break; - case EXCP_BREAKPOINT: -#ifdef DDB - // kdb_trap(exception, 0, frame); - db_trapper(frame->tf_sepc,0/*XXX*/, frame, exception); -#else - dump_regs(frame); - panic("No debugger in kernel.\n"); -#endif - break; - case EXCP_ILLEGAL_INSTRUCTION: - dump_regs(frame); - panic("Illegal instruction at 0x%016lx\n", frame->tf_sepc); - break; - default: - dump_regs(frame); - panic("Unknown kernel exception %llx trap value %lx\n", - exception, frame->tf_stval); - } -} - - -void -do_trap_user(struct trapframe *frame) -{ - uint64_t exception; - union sigval sv; - struct proc *p; - struct pcb *pcb; - - p = curcpu()->ci_curproc; - p->p_addr->u_pcb.pcb_tf = frame; - pcb = curcpu()->ci_curpcb; - - /* Ensure we came from usermode, interrupts disabled */ - KASSERTMSG((csr_read(sstatus) & (SSTATUS_SPP | SSTATUS_SIE)) == 0, - "Came from U mode with interrupts enabled"); - - /* Save fpu context before (possibly) calling interrupt handler. - * Could end up context switching in interrupt handler. - */ - fpu_save(p, frame); - - exception = (frame->tf_scause & EXCP_MASK); - if (frame->tf_scause & EXCP_INTR) { - /* Interrupt */ - riscv_cpu_intr(frame); - frame->tf_sstatus &= ~SSTATUS_FS_MASK; - if (pcb->pcb_fpcpu == curcpu() && curcpu()->ci_fpuproc == p) { - frame->tf_sstatus |= SSTATUS_FS_CLEAN; - } - return; - } - - enable_interrupts(); //XXX allow preemption? - -#if 0 // XXX Debug logging - printf( "do_trap_user: curproc: %p, sepc: %lx, ra: %lx frame: %p\n", - curcpu()->ci_curproc, frame->tf_sepc, frame->tf_ra, frame); -#endif - - switch(exception) { - case EXCP_FAULT_LOAD: - case EXCP_FAULT_STORE: - case EXCP_FAULT_FETCH: - case EXCP_STORE_PAGE_FAULT: - case EXCP_LOAD_PAGE_FAULT: - case EXCP_INST_PAGE_FAULT: - data_abort(frame, 1); - break; - case EXCP_USER_ECALL: - frame->tf_sepc += 4; /* Next instruction */ - svc_handler(frame); - break; - case EXCP_ILLEGAL_INSTRUCTION: - - if ((frame->tf_sstatus & SSTATUS_FS_MASK) == - SSTATUS_FS_OFF) { - if(fpu_valid_opcode(frame->tf_stval)) { - - /* XXX do this here or should it be in the - * trap handler in the restore path? - */ - fpu_load(p); - - frame->tf_sstatus &= ~SSTATUS_FS_MASK; - break; - } - } - printf("ILL at %lx scause %lx stval %lx\n", frame->tf_sepc, frame->tf_scause, frame->tf_stval); - sv.sival_ptr = (void *)frame->tf_stval; - trapsignal(p, SIGILL, 0, ILL_ILLTRP, sv); - userret(p); - break; - case EXCP_BREAKPOINT: - printf("BREAKPOINT\n"); - sv.sival_ptr = (void *)frame->tf_stval; - trapsignal(p, SIGTRAP, 0, TRAP_BRKPT, sv); - userret(p); - break; - default: - dump_regs(frame); - panic("Unknown userland exception %llx, trap value %lx\n", - exception, frame->tf_stval); - } - disable_interrupts(); /* XXX - ??? */ - /* now that we will not context switch again, - * see if we should enable FPU - */ - frame->tf_sstatus &= ~SSTATUS_FS_MASK; - if (pcb->pcb_fpcpu == curcpu() && curcpu()->ci_fpuproc == p) { - frame->tf_sstatus |= SSTATUS_FS_CLEAN; - //printf ("FPU enabled userland %p %p\n", - // pcb->pcb_fpcpu, curcpu()->ci_fpuproc); - } -} - -static void -data_abort(struct trapframe *frame, int usermode) -{ - struct vm_map *map; - uint64_t stval; - union sigval sv; - struct pcb *pcb; - vm_prot_t ftype; - vaddr_t va; - struct proc *p; - int error, sig, code, access_type; - - pcb = curcpu()->ci_curpcb; - p = curcpu()->ci_curproc; - stval = frame->tf_stval; - - va = trunc_page(stval); - - //if (va >= VM_MAXUSER_ADDRESS) - // curcpu()->ci_flush_bp(); - - if ((frame->tf_scause == EXCP_FAULT_STORE) || - (frame->tf_scause == EXCP_STORE_PAGE_FAULT)) { - access_type = PROT_WRITE; - } else if (frame->tf_scause == EXCP_INST_PAGE_FAULT) { - access_type = PROT_EXEC; - } else { - access_type = PROT_READ; - } - - ftype = VM_FAULT_INVALID; // should check for failed permissions. - - if (usermode) - map = &p->p_vmspace->vm_map; - else if (stval >= VM_MAX_USER_ADDRESS) - map = kernel_map; - else { - if (pcb->pcb_onfault == 0) - goto fatal; - map = &p->p_vmspace->vm_map; - } - - if (pmap_fault_fixup(map->pmap, va, ftype, usermode)) - goto done; - - KERNEL_LOCK(); - error = uvm_fault(map, va, ftype, access_type); - KERNEL_UNLOCK(); - - if (error != 0) { - if (usermode) { - if (error == ENOMEM) { - sig = SIGKILL; - code = 0; - } else if (error == EIO) { - sig = SIGBUS; - code = BUS_OBJERR; - } else if (error == EACCES) { - sig = SIGSEGV; - code = SEGV_ACCERR; - } else { - sig = SIGSEGV; - code = SEGV_MAPERR; - } - sv.sival_ptr = (void *)stval; - trapsignal(p, sig, 0, code, sv); - } else { - if (curcpu()->ci_idepth == 0 && pcb->pcb_onfault != 0) { - frame->tf_a[0] = error; - frame->tf_sepc = (register_t)pcb->pcb_onfault; - return; - } - goto fatal; - } - } - -done: - if (usermode) - userret(p); - return; - -fatal: - dump_regs(frame); - panic("Fatal page fault at %#lx: %#08lx", frame->tf_sepc, - (vaddr_t)sv.sival_ptr); -} -