Skip to content

Commit 5a66af2

Browse files
committed
arch/riscv: preserve t3–t6 across traps and recover U-mode faults
- Save/restore t3–t6 in the trap frame so ecall cannot clobber lui bases for BSS/data - Treat all U-mode illegal/load/store/fetch faults as recoverable thread kills
1 parent 39b4cc5 commit 5a66af2

2 files changed

Lines changed: 24 additions & 8 deletions

File tree

arch/riscv/arch.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <ulmk_arch.h>
1111
#include "irq_internal.h"
1212

13-
#define TF_SIZE 128u
13+
#define TF_SIZE 144u
1414
#define TF_RA 0u
1515
#define TF_S0 28u
1616
#define TF_S1 32u
@@ -509,14 +509,13 @@ void _ulmk_trap_dispatch(struct riscv_trap_frame *frame)
509509
/*
510510
* U-mode fetch of kernel text may raise INST_FAULT (PMP deny) or,
511511
* when a NAPOT user RX window overlaps and the first insn is a
512-
* privileged CSR (-O1+), ILLEGAL_INST. Both mean the thread must
513-
* die; only panic if the fault came from M-mode.
512+
* privileged CSR (-O1+), ILLEGAL_INST. Userspace load/store/fetch
513+
* faults are recoverable (kill thread). M-mode faults panic.
514514
*/
515515
mstatus = frame->regs[TF_MSTATUS / 4u];
516-
if (code == MCAUSE_LOAD_FAULT || code == MCAUSE_STORE_FAULT ||
517-
code == MCAUSE_INST_FAULT ||
518-
(code == MCAUSE_ILLEGAL_INST &&
519-
((mstatus >> MSTATUS_MPP_SHIFT) & 3u) == 0u))
516+
if (((mstatus >> MSTATUS_MPP_SHIFT) & 3u) == 0u &&
517+
(code == MCAUSE_LOAD_FAULT || code == MCAUSE_STORE_FAULT ||
518+
code == MCAUSE_INST_FAULT || code == MCAUSE_ILLEGAL_INST))
520519
ulmk_arch_trap_entry(0u, (uint8_t)code);
521520
else
522521
ulmk_arch_trap_entry(mcause_to_trap_class(mcause), (uint8_t)code);

arch/riscv/trap.S

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
* RISC-V trap entry — arch/riscv/trap.S
44
*/
55

6-
.equ TF_SIZE, 128
6+
/*
7+
* Must save t3–t6: GCC keeps lui bases for .bss/.data in temps across
8+
* ecall; leaving them live lets the callee (or IRQ C path) clobber them
9+
* and userspace reloads as `lw rd, %lo(sym)(zero)` → mtval=lo12.
10+
*/
11+
.equ TF_SIZE, 144
712
.equ TF_RA, 0
813
.equ TF_SP, 4
914
.equ TF_GP, 8
@@ -33,6 +38,10 @@
3338
.equ TF_S11, 104
3439
.equ TF_MEPC, 108
3540
.equ TF_MSTATUS, 112
41+
.equ TF_T3, 116
42+
.equ TF_T4, 120
43+
.equ TF_T5, 124
44+
.equ TF_T6, 128
3645

3746
.extern _ulmk_trap_dispatch
3847
.extern g_trap_sp
@@ -51,6 +60,10 @@ _trap_handler:
5160
sw t0, TF_T0(sp)
5261
sw t1, TF_T1(sp)
5362
sw t2, TF_T2(sp)
63+
sw t3, TF_T3(sp)
64+
sw t4, TF_T4(sp)
65+
sw t5, TF_T5(sp)
66+
sw t6, TF_T6(sp)
5467
sw s0, TF_S0(sp)
5568
sw s1, TF_S1(sp)
5669
sw a0, TF_A0(sp)
@@ -91,6 +104,10 @@ _trap_handler:
91104
lw t0, TF_T0(sp)
92105
lw t1, TF_T1(sp)
93106
lw t2, TF_T2(sp)
107+
lw t3, TF_T3(sp)
108+
lw t4, TF_T4(sp)
109+
lw t5, TF_T5(sp)
110+
lw t6, TF_T6(sp)
94111
lw s0, TF_S0(sp)
95112
lw s1, TF_S1(sp)
96113
lw a0, TF_A0(sp)

0 commit comments

Comments
 (0)