diff options
-rw-r--r-- | sys/riscv/include/fpe.h | 1 | ||||
-rw-r--r-- | sys/riscv/riscv/machdep.c | 10 | ||||
-rw-r--r-- | sys/riscv/riscv/swtch.S | 53 | ||||
-rw-r--r-- | sys/riscv/riscv/trap.c | 7 |
4 files changed, 68 insertions, 3 deletions
diff --git a/sys/riscv/include/fpe.h b/sys/riscv/include/fpe.h index 1294ab0de8fa..a519094d4272 100644 --- a/sys/riscv/include/fpe.h +++ b/sys/riscv/include/fpe.h @@ -34,5 +34,6 @@ #define _MACHINE_FPE_H_ void fpe_state_save(struct thread *td); +void fpe_state_clear(void); #endif /* !_MACHINE_FPE_H_ */ diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c index 64d20126f3ad..430336408368 100644 --- a/sys/riscv/riscv/machdep.c +++ b/sys/riscv/riscv/machdep.c @@ -204,13 +204,14 @@ fill_fpregs(struct thread *td, struct fpreg *regs) * If we have just been running FPE instructions we will * need to save the state to memcpy it below. */ - fpe_state_save(td); + if (td == curthread) + fpe_state_save(td); memcpy(regs->fp_x, pcb->pcb_x, sizeof(regs->fp_x)); regs->fp_fcsr = pcb->pcb_fcsr; } else #endif - memset(regs->fp_x, 0, sizeof(regs->fp_x)); + memset(regs, 0, sizeof(*regs)); return (0); } @@ -219,12 +220,17 @@ int set_fpregs(struct thread *td, struct fpreg *regs) { #ifdef FPE + struct trapframe *frame; struct pcb *pcb; + frame = td->td_frame; pcb = td->td_pcb; memcpy(pcb->pcb_x, regs->fp_x, sizeof(regs->fp_x)); pcb->pcb_fcsr = regs->fp_fcsr; + pcb->pcb_fpflags |= PCB_FP_STARTED; + frame->tf_sstatus &= ~SSTATUS_FS_MASK; + frame->tf_sstatus |= SSTATUS_FS_CLEAN; #endif return (0); diff --git a/sys/riscv/riscv/swtch.S b/sys/riscv/riscv/swtch.S index b17de23ad395..8192abaf9869 100644 --- a/sys/riscv/riscv/swtch.S +++ b/sys/riscv/riscv/swtch.S @@ -154,6 +154,59 @@ END(fpe_state_save) #endif /* FPE */ /* + * void + * fpe_state_clear(void) + */ +ENTRY(fpe_state_clear) + /* + * Enable FPE usage in supervisor mode, + * so we can access registers. + */ + li t0, SSTATUS_FS_INITIAL + csrs sstatus, t0 + + fscsr zero + fcvt.d.l f0, zero + fcvt.d.l f1, zero + fcvt.d.l f2, zero + fcvt.d.l f3, zero + fcvt.d.l f4, zero + fcvt.d.l f5, zero + fcvt.d.l f6, zero + fcvt.d.l f7, zero + fcvt.d.l f8, zero + fcvt.d.l f9, zero + fcvt.d.l f10, zero + fcvt.d.l f11, zero + fcvt.d.l f12, zero + fcvt.d.l f13, zero + fcvt.d.l f14, zero + fcvt.d.l f15, zero + fcvt.d.l f16, zero + fcvt.d.l f17, zero + fcvt.d.l f18, zero + fcvt.d.l f19, zero + fcvt.d.l f20, zero + fcvt.d.l f21, zero + fcvt.d.l f22, zero + fcvt.d.l f23, zero + fcvt.d.l f24, zero + fcvt.d.l f25, zero + fcvt.d.l f26, zero + fcvt.d.l f27, zero + fcvt.d.l f28, zero + fcvt.d.l f29, zero + fcvt.d.l f30, zero + fcvt.d.l f31, zero + + /* Disable FPE usage in supervisor mode. */ + li t0, SSTATUS_FS_MASK + csrc sstatus, t0 + + ret +END(fpe_state_clear) + +/* * void cpu_throw(struct thread *old, struct thread *new) */ ENTRY(cpu_throw) diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c index ced05c52588f..57f5c558d286 100644 --- a/sys/riscv/riscv/trap.c +++ b/sys/riscv/riscv/trap.c @@ -57,6 +57,9 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_param.h> #include <vm/vm_extern.h> +#ifdef FPE +#include <machine/fpe.h> +#endif #include <machine/frame.h> #include <machine/pcb.h> #include <machine/pcpu.h> @@ -363,7 +366,9 @@ do_trap_user(struct trapframe *frame) * May be a FPE trap. Enable FPE usage * for this thread and try again. */ - frame->tf_sstatus |= SSTATUS_FS_INITIAL; + fpe_state_clear(); + frame->tf_sstatus &= ~SSTATUS_FS_MASK; + frame->tf_sstatus |= SSTATUS_FS_CLEAN; pcb->pcb_fpflags |= PCB_FP_STARTED; break; } |