* riscv64/riscv64/locore.S: Replace x86 trap stubs with RISC-V trap entry and
exit.
The alltraps entry saves all 31 GPs and 4 CSRs (scause, stval, sepc, sstatus)
into a riscv64_saved_state frame on the kernel stack and calls riscv64_trap().
The return path restores CSRs and registers, then executes sret.
thread_bootstrap_return, thread_exception_return, and thread_syscall_return
are implemented as wrappers that jump to the common return path.
* riscv64/riscv64/trap.c: Remove dead x86 code from riscv64_exception stub
and implement interrupted_pc to return regs->sepc.
---
riscv64/riscv64/locore.S | 173 ++++++++++++++++++++++++++++-----------
riscv64/riscv64/trap.c | 14 +---
2 files changed, 130 insertions(+), 57 deletions(-)
diff --git a/riscv64/riscv64/locore.S b/riscv64/riscv64/locore.S
index 3d0f4030..45d9c690 100644
--- a/riscv64/riscv64/locore.S
+++ b/riscv64/riscv64/locore.S
@@ -168,66 +168,147 @@ ENTRY(t_debug)
ENTRY(t_page_fault)
/*
- * All 'exceptions' enter here with:
- * esp-> trap number
- * error code
- * old eip
- * old cs
- * old eflags
- * old esp if trapped from user
- * old ss if trapped from user
+ * RISC-V trap entry/exit.
+ *
+ * On entry, hardware has set:
+ * scause - trap cause
+ * stval - faulting address or instruction
+ * sepc - interrupted PC
+ * sstatus - previous status (SPP, SPIE, SIE)
+ *
+ * We build a riscv64_saved_state frame (35 * 8 = 280 bytes, padded to 288)
+ * on the kernel stack and call riscv64_trap(regs).
+ *
+ * Frame layout (offsets match struct riscv64_saved_state in thread.h):
+ * 0 t6 8 t5 16 t4 24 t3
+ * 32 s11 40 s10 48 s9 56 s8
+ * 64 s7 72 s6 80 s5 88 s4
+ * 96 s3 104 s2 112 a7 120 a6
+ * 128 a5 136 a4 144 a3 152 a2
+ * 160 a1 168 a0 176 s1 184 fp
+ * 192 t2 200 t1 208 t0 216 tp
+ * 224 gp 232 sp 240 ra
+ * 248 scause 256 stval 264 sepc 272 sstatus
*/
+
+#define FRAME_SIZE 288
+
ENTRY(alltraps)
-trap_push_segs:
-trap_set_segs:
trap_from_user:
+trap_from_kernel:
_take_trap:
-
-/*
- * Return from trap or system call, checking for ASTs.
- * On PCB stack.
- */
+ addi sp, sp, -FRAME_SIZE
+
+ sd t6, 0(sp)
+ sd t5, 8(sp)
+ sd t4, 16(sp)
+ sd t3, 24(sp)
+ sd s11, 32(sp)
+ sd s10, 40(sp)
+ sd s9, 48(sp)
+ sd s8, 56(sp)
+ sd s7, 64(sp)
+ sd s6, 72(sp)
+ sd s5, 80(sp)
+ sd s4, 88(sp)
+ sd s3, 96(sp)
+ sd s2, 104(sp)
+ sd a7, 112(sp)
+ sd a6, 120(sp)
+ sd a5, 128(sp)
+ sd a4, 136(sp)
+ sd a3, 144(sp)
+ sd a2, 152(sp)
+ sd a1, 160(sp)
+ sd a0, 168(sp)
+ sd s1, 176(sp)
+ sd fp, 184(sp)
+ sd t2, 192(sp)
+ sd t1, 200(sp)
+ sd t0, 208(sp)
+ sd tp, 216(sp)
+ sd gp, 224(sp)
+ sd ra, 240(sp)
+
+ /* Save original sp */
+ addi t0, sp, FRAME_SIZE
+ sd t0, 232(sp)
+
+ /* Save CSRs */
+ csrr t0, scause
+ sd t0, 248(sp)
+ csrr t0, stval
+ sd t0, 256(sp)
+ csrr t0, sepc
+ sd t0, 264(sp)
+ csrr t0, sstatus
+ sd t0, 272(sp)
+
+ /* Call C: void riscv64_trap(struct riscv64_saved_state *regs) */
+ mv a0, sp
+ call riscv64_trap
_return_from_trap:
-
_return_to_user:
-
-/*
- * Return from kernel mode to interrupted thread.
+ /* Restore sstatus and sepc */
+ ld t0, 272(sp)
+ csrw sstatus, t0
+ ld t0, 264(sp)
+ csrw sepc, t0
+
+ /* Restore caller-saved and callee-saved registers */
+ ld t6, 0(sp)
+ ld t5, 8(sp)
+ ld t4, 16(sp)
+ ld t3, 24(sp)
+ ld s11, 32(sp)
+ ld s10, 40(sp)
+ ld s9, 48(sp)
+ ld s8, 56(sp)
+ ld s7, 64(sp)
+ ld s6, 72(sp)
+ ld s5, 80(sp)
+ ld s4, 88(sp)
+ ld s3, 96(sp)
+ ld s2, 104(sp)
+ ld a7, 112(sp)
+ ld a6, 120(sp)
+ ld a5, 128(sp)
+ ld a4, 136(sp)
+ ld a3, 144(sp)
+ ld a2, 152(sp)
+ ld a1, 160(sp)
+ ld a0, 168(sp)
+ ld s1, 176(sp)
+ ld fp, 184(sp)
+ ld t2, 192(sp)
+ ld t1, 200(sp)
+ ld t0, 208(sp)
+ ld tp, 216(sp)
+ ld gp, 224(sp)
+ ld ra, 240(sp)
+ ld sp, 232(sp)
+
+ sret
+END(alltraps)
+
+/*
+ * Return from kernel as if from an exception.
+ * Called as a C function; saved state is on the current stack.
*/
-
-_return_from_kernel:
-_kret_popl_gs:
-_kret_popl_fs:
-_kret_popl_es:
-_kret_popl_ds:
-_kret_iret:
-
-
-/*
- * Trap from kernel mode. No need to switch stacks.
- */
-trap_from_kernel:
-#if MACH_KDB || MACH_TTD
-#else /* MACH_KDB || MACH_TTD */
-#endif /* MACH_KDB || MACH_TTD */
-
-
-/*
- * Called as a function, makes the current thread
- * return from the kernel as if from an exception.
- */
-
ENTRY(thread_exception_return)
ENTRY(thread_bootstrap_return)
+ j _return_from_trap
+END(thread_bootstrap_return)
/*
- * Called as a function, makes the current thread
- * return from the kernel as if from a syscall.
- * Takes the syscall's return code as an argument.
+ * Return from syscall. a0 = return code.
+ * Stored into the saved state's a0 slot on the stack.
*/
-
ENTRY(thread_syscall_return)
+ sd a0, 168(sp)
+ j _return_from_trap
+END(thread_syscall_return)
ENTRY(call_continuation)
diff --git a/riscv64/riscv64/trap.c b/riscv64/riscv64/trap.c
index 014e48cf..4e790d68 100644
--- a/riscv64/riscv64/trap.c
+++ b/riscv64/riscv64/trap.c
@@ -169,15 +169,7 @@ riscv64_exception(
int code,
long subcode)
{
- spl_t s;
-
- /*
- * Turn off delayed FPU error handling.
- */
- panic("TODO: not implemented");
-
- exception(exc, code, subcode);
- /*NOTREACHED*/
+ panic("riscv64_exception: exc=%d code=%d", exc, code);
}
#if MACH_PCSAMPLE > 0
@@ -187,8 +179,8 @@ riscv64_exception(
unsigned
interrupted_pc(const thread_t t)
{
- panic("TODO: not implemented");
- return 0;
+ struct riscv64_saved_state *regs = USER_REGS(t);
+ return regs->sepc;
}
#endif /* MACH_PCSAMPLE > 0 */
--
2.43.0