Skip to content

Commit c8d31dd

Browse files
authored
Use saved mstatus for FPU/VPU state determination (#1330)
According to the RISC-V Privileged Architecture Specification (20211203), writing Initial or Clean to the FS field of mstatus may result in the FS value getting set to Dirty in some implementations. This means we cannot rely on reading back the same FS value after writing to mstatus. Previously, the context restore code would: 1. Write an FS value to mstatus 2. Read mstatus again at a later point 3. Use the read FS value to determine FPU status This change updates the context restore code to use the mstatus value from the saved context instead of re-reading mstatus after writing to it. This required chaning the location of the mstatus slot in the context. Fixes: #1327 Signed-off-by: Gaurav Aggarwal <[email protected]>
1 parent 8b63f94 commit c8d31dd

File tree

3 files changed

+35
-34
lines changed

3 files changed

+35
-34
lines changed

portable/GCC/RISC-V/chip_specific_extensions/Pulpino_Vega_RV32M1RM/freertos_risc_v_chip_specific_extensions.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,22 +80,22 @@ csrr t2, lpcount0
8080
csrr t3, lpstart1
8181
csrr t4, lpend1
8282
csrr t5, lpcount1
83-
sw t0, 2 * portWORD_SIZE( sp )
84-
sw t1, 3 * portWORD_SIZE( sp )
85-
sw t2, 4 * portWORD_SIZE( sp )
86-
sw t3, 5 * portWORD_SIZE( sp )
87-
sw t4, 6 * portWORD_SIZE( sp )
88-
sw t5, 7 * portWORD_SIZE( sp )
83+
sw t0, 1 * portWORD_SIZE( sp )
84+
sw t1, 2 * portWORD_SIZE( sp )
85+
sw t2, 3 * portWORD_SIZE( sp )
86+
sw t3, 4 * portWORD_SIZE( sp )
87+
sw t4, 5 * portWORD_SIZE( sp )
88+
sw t5, 6 * portWORD_SIZE( sp )
8989
.endm
9090

9191
/* Restore the additional registers found on the Pulpino. */
9292
.macro portasmRESTORE_ADDITIONAL_REGISTERS
93-
lw t0, 2 * portWORD_SIZE( sp ) /* Load additional registers into accessible temporary registers. */
94-
lw t1, 3 * portWORD_SIZE( sp )
95-
lw t2, 4 * portWORD_SIZE( sp )
96-
lw t3, 5 * portWORD_SIZE( sp )
97-
lw t4, 6 * portWORD_SIZE( sp )
98-
lw t5, 7 * portWORD_SIZE( sp )
93+
lw t0, 1 * portWORD_SIZE( sp ) /* Load additional registers into accessible temporary registers. */
94+
lw t1, 2 * portWORD_SIZE( sp )
95+
lw t2, 3 * portWORD_SIZE( sp )
96+
lw t3, 4 * portWORD_SIZE( sp )
97+
lw t4, 5 * portWORD_SIZE( sp )
98+
lw t5, 6 * portWORD_SIZE( sp )
9999
csrw lpstart0, t0
100100
csrw lpend0, t1
101101
csrw lpcount0, t2

portable/GCC/RISC-V/portASM.S

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ definitions. */
193193
* portTASK_RETURN_ADDRESS
194194
* [FPU registers (when enabled/available) go here]
195195
* [VPU registers (when enabled/available) go here]
196-
* [chip specific registers go here]
197196
* mstatus
197+
* [chip specific registers go here]
198198
* pxCode
199199
*/
200200
pxPortInitialiseStack:
@@ -212,14 +212,6 @@ pxPortInitialiseStack:
212212
load_x t0, xTaskReturnAddress
213213
store_x t0, 0(a0) /* Return address onto the stack. */
214214

215-
addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */
216-
chip_specific_stack_frame: /* First add any chip specific registers to the stack frame being created. */
217-
beq t0, x0, 1f /* No more chip specific registers to save. */
218-
addi a0, a0, -portWORD_SIZE /* Make space for chip specific register. */
219-
store_x x0, 0(a0) /* Give the chip specific register an initial value of zero. */
220-
addi t0, t0, -1 /* Decrement the count of chip specific registers remaining. */
221-
j chip_specific_stack_frame /* Until no more chip specific registers. */
222-
1:
223215
csrr t0, mstatus /* Obtain current mstatus value. */
224216
andi t0, t0, ~0x8 /* Ensure interrupts are disabled when the stack is restored within an ISR. Required when a task is created after the scheduler has been started, otherwise interrupts would be disabled anyway. */
225217
addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE=1 and MPP=M_Mode in mstatus. */
@@ -245,6 +237,15 @@ chip_specific_stack_frame: /* First add any chip specific registers
245237
addi a0, a0, -portWORD_SIZE
246238
store_x t0, 0(a0) /* mstatus onto the stack. */
247239

240+
addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */
241+
chip_specific_stack_frame: /* First add any chip specific registers to the stack frame being created. */
242+
beq t0, x0, 1f /* No more chip specific registers to save. */
243+
addi a0, a0, -portWORD_SIZE /* Make space for chip specific register. */
244+
store_x x0, 0(a0) /* Give the chip specific register an initial value of zero. */
245+
addi t0, t0, -1 /* Decrement the count of chip specific registers remaining. */
246+
j chip_specific_stack_frame /* Until no more chip specific registers. */
247+
1:
248+
248249
addi a0, a0, -portWORD_SIZE
249250
store_x a1, 0(a0) /* mret value (pxCode parameter) onto the stack. */
250251
ret
@@ -256,12 +257,12 @@ xPortStartFirstTask:
256257

257258
load_x x1, 0( sp ) /* Note for starting the scheduler the exception return address is used as the function return address. */
258259

260+
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
261+
259262
load_x x5, 1 * portWORD_SIZE( sp ) /* Initial mstatus into x5 (t0). */
260263
addi x5, x5, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
261264
csrw mstatus, x5 /* Interrupts enabled from here! */
262265

263-
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
264-
265266
load_x x7, 5 * portWORD_SIZE( sp ) /* t2 */
266267
load_x x8, 6 * portWORD_SIZE( sp ) /* s0/fp */
267268
load_x x9, 7 * portWORD_SIZE( sp ) /* s1 */

portable/GCC/RISC-V/portContext.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -322,17 +322,17 @@ store_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Store the criti
322322
srl t1, t0, MSTATUS_VS_OFFSET
323323
andi t1, t1, 3
324324
addi t2, x0, 3
325-
bne t1, t2, 2f /* If VPU status is not dirty, do not save FPU registers. */
325+
bne t1, t2, 2f /* If VPU status is not dirty, do not save VPU registers. */
326326

327327
portcontexSAVE_VPU_CONTEXT
328328
2:
329329
#endif
330330

331-
portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
332-
333331
csrr t0, mstatus
334332
store_x t0, 1 * portWORD_SIZE( sp )
335333

334+
portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
335+
336336
#if( configENABLE_FPU == 1 )
337337
/* Mark the FPU as clean, if it was dirty and we saved FPU registers. */
338338
srl t1, t0, MSTATUS_FS_OFFSET
@@ -396,16 +396,17 @@ load_x sp, 0 ( t1 ) /* Read sp from first TCB member. */
396396
load_x t0, 0 ( sp )
397397
csrw mepc, t0
398398

399-
/* Restore mstatus register. */
400-
load_x t0, 1 * portWORD_SIZE( sp )
401-
csrw mstatus, t0
402-
403399
/* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
404400
portasmRESTORE_ADDITIONAL_REGISTERS
405401

402+
/* Restore mstatus register. It is important to use t3 (and not t0) here as t3
403+
* is not clobbered by portcontextRESTORE_VPU_CONTEXT and
404+
* portcontextRESTORE_FPU_CONTEXT. */
405+
load_x t3, 1 * portWORD_SIZE( sp )
406+
csrw mstatus, t3
407+
406408
#if( configENABLE_VPU == 1 )
407-
csrr t0, mstatus
408-
srl t1, t0, MSTATUS_VS_OFFSET
409+
srl t1, t3, MSTATUS_VS_OFFSET
409410
andi t1, t1, 3
410411
addi t2, x0, 3
411412
bne t1, t2, 5f /* If VPU status is not dirty, do not restore VPU registers. */
@@ -415,8 +416,7 @@ portasmRESTORE_ADDITIONAL_REGISTERS
415416
#endif /* ifdef portasmSTORE_VPU_CONTEXT */
416417

417418
#if( configENABLE_FPU == 1 )
418-
csrr t0, mstatus
419-
srl t1, t0, MSTATUS_FS_OFFSET
419+
srl t1, t3, MSTATUS_FS_OFFSET
420420
andi t1, t1, 3
421421
addi t2, x0, 3
422422
bne t1, t2, 6f /* If FPU status is not dirty, do not restore FPU registers. */

0 commit comments

Comments
 (0)