diff options
Diffstat (limited to 'ports/risc-v64/gnu/src')
| -rw-r--r-- | ports/risc-v64/gnu/src/tx_initialize_low_level.S | 16 | ||||
| -rw-r--r-- | ports/risc-v64/gnu/src/tx_thread_context_restore.S | 142 | ||||
| -rw-r--r-- | ports/risc-v64/gnu/src/tx_thread_context_save.S | 90 | ||||
| -rw-r--r-- | ports/risc-v64/gnu/src/tx_thread_interrupt_control.S | 32 | ||||
| -rw-r--r-- | ports/risc-v64/gnu/src/tx_thread_schedule.S | 47 | ||||
| -rw-r--r-- | ports/risc-v64/gnu/src/tx_thread_stack_build.S | 19 | ||||
| -rw-r--r-- | ports/risc-v64/gnu/src/tx_thread_system_return.S | 12 | ||||
| -rw-r--r-- | ports/risc-v64/gnu/src/tx_timer_interrupt.S | 4 |
8 files changed, 232 insertions, 130 deletions
diff --git a/ports/risc-v64/gnu/src/tx_initialize_low_level.S b/ports/risc-v64/gnu/src/tx_initialize_low_level.S index 6a35272f..952be957 100644 --- a/ports/risc-v64/gnu/src/tx_initialize_low_level.S +++ b/ports/risc-v64/gnu/src/tx_initialize_low_level.S @@ -79,10 +79,26 @@ _tx_initialize_low_level: /* Initialize floating point control/status register if floating point is enabled. */ #ifdef __riscv_flen +#ifdef TX_RISCV_SMODE + li t0, 0x2000 // Set sstatus.FS to Initial (bits 14:13 = 01) so the fcsr write cannot trap + csrrs zero, sstatus, t0 +#else + li t0, 0x2000 // Set mstatus.FS to Initial (bits 14:13 = 01) so the fcsr write cannot trap + csrrs zero, mstatus, t0 +#endif li t0, 0 csrw fcsr, t0 // Clear FP control/status register #endif +#ifdef __riscv_vector + li t0, 0x200 // Set VS=Initial before a vector restore +#ifdef TX_RISCV_SMODE + csrrs zero, sstatus, t0 +#else + csrrs zero, mstatus, t0 +#endif +#endif + ret /* Timer Interrupt Handler Note: diff --git a/ports/risc-v64/gnu/src/tx_thread_context_restore.S b/ports/risc-v64/gnu/src/tx_thread_context_restore.S index cebc8a06..f5a68d2e 100644 --- a/ports/risc-v64/gnu/src/tx_thread_context_restore.S +++ b/ports/risc-v64/gnu/src/tx_thread_context_restore.S @@ -58,6 +58,8 @@ /**************************************************************************/ /* VOID _tx_thread_context_restore(VOID) { */ +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE .global _tx_thread_context_restore _tx_thread_context_restore: @@ -88,8 +90,18 @@ _tx_thread_context_restore: /* Just recover the saved registers and return to the point of interrupt. */ + /* Recover the FP state only when the saved mstatus.FS was not Off. The + save side skips the FP stores for a thread that has not touched the + unit, so those slots hold nothing worth loading back. */ +#if (__riscv_flen == 32) || (__riscv_flen == 64) + ld t1, 29*8(sp) // Pickup saved mstatus + srli t1, t1, 13 + andi t1, t1, 0x3 + beqz t1, _tx_thread_skip_fp_restore // Skip if FS was Off +#endif + /* Recover floating point registers. */ -#if defined(__riscv_float_abi_single) +#if (__riscv_flen == 32) flw f0, 31*8(sp) // Recover ft0 flw f1, 32*8(sp) // Recover ft1 flw f2, 33*8(sp) // Recover ft2 @@ -112,7 +124,7 @@ _tx_thread_context_restore: flw f31,62*8(sp) // Recover ft11 ld t0, 63*8(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fld f0, 31*8(sp) // Recover ft0 fld f1, 32*8(sp) // Recover ft1 fld f2, 33*8(sp) // Recover ft2 @@ -121,6 +133,20 @@ _tx_thread_context_restore: fld f5, 36*8(sp) // Recover ft5 fld f6, 37*8(sp) // Recover ft6 fld f7, 38*8(sp) // Recover ft7 +#if defined(__riscv_float_abi_single) + fld f8, 39*8(sp) // Recover fs0 + fld f9, 40*8(sp) // Recover fs1 + fld f18, 49*8(sp) // Recover fs2 + fld f19, 50*8(sp) // Recover fs3 + fld f20, 51*8(sp) // Recover fs4 + fld f21, 52*8(sp) // Recover fs5 + fld f22, 53*8(sp) // Recover fs6 + fld f23, 54*8(sp) // Recover fs7 + fld f24, 55*8(sp) // Recover fs8 + fld f25, 56*8(sp) // Recover fs9 + fld f26, 57*8(sp) // Recover fs10 + fld f27, 58*8(sp) // Recover fs11 +#endif fld f10,41*8(sp) // Recover fa0 fld f11,42*8(sp) // Recover fa1 fld f12,43*8(sp) // Recover fa2 @@ -136,6 +162,7 @@ _tx_thread_context_restore: ld t0, 63*8(sp) // Recover fcsr csrw fcsr, t0 #endif +_tx_thread_skip_fp_restore: #if defined(__riscv_vector) /* Recover vector registers v0-v31 */ @@ -189,6 +216,10 @@ _tx_thread_context_restore: li t0, 0x6000 // Set FS=Dirty (bits 14:13) for FP state or t1, t1, t0 #endif +#if defined(__riscv_vector) + li t0, 0x0600 + or t1, t1, t0 +#endif csrw sstatus, t1 // Update sstatus safely #else csrw mepc, t0 // Setup mepc @@ -203,11 +234,11 @@ _tx_thread_context_restore: andi t1, t1, ~0x8 // Clear MIE, Hardware will restore it from MPIE #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - li t0, 0x2000 // Set FS bits (bits 14:13 to 01) for FP state + li t0, 0x6000 or t1, t1, t0 #endif #if defined(__riscv_vector) - li t0, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state + li t0, 0x0600 or t1, t1, t0 #endif csrw mstatus, t1 // Update mstatus safely @@ -231,18 +262,10 @@ _tx_thread_context_restore: ld t5, 14*8(sp) // Recover t5 ld t6, 13*8(sp) // Recover t6 -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*8 // Recover stack frame - with floating point enabled -#else - addi sp, sp, 32*8 // Recover stack frame - without floating point enabled -#endif + addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame - with floating point enabled (65*8 data + 8 pad) #if defined(__riscv_vector) -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t0, sp, -65*8 -#else - addi t0, sp, -32*8 -#endif + addi t0, sp, -TX_TRAP_FRAME_SIZE csrr t1, vlenb // Get vector register byte length slli t1, t1, 5 // Multiply by 32 (number of vector registers) addi t1, t1, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr @@ -270,7 +293,7 @@ _tx_thread_not_nested_restore: la t0, _tx_thread_preempt_disable // Pickup preempt disable flag address lw t2, 0(t0) // Pickup preempt disable flag (UINT) - bgtz t2, _tx_thread_no_preempt_restore // If set, restore interrupted thread + bnez t2, _tx_thread_no_preempt_restore // If set (nonzero), restore interrupted thread la t0, _tx_thread_execute_ptr // Pickup thread execute pointer address ld t2, 0(t0) // Pickup thread execute pointer @@ -285,8 +308,18 @@ _tx_thread_no_preempt_restore: ld sp, 8(t1) // Switch back to thread's stack + /* Recover the FP state only when the saved mstatus.FS was not Off. The + save side skips the FP stores for a thread that has not touched the + unit, so those slots hold nothing worth loading back. */ +#if (__riscv_flen == 32) || (__riscv_flen == 64) + ld t3, 29*8(sp) // Pickup saved mstatus + srli t3, t3, 13 + andi t3, t3, 0x3 + beqz t3, _tx_thread_no_preempt_skip_fp_restore // Skip if FS was Off +#endif + /* Recover floating point registers. */ -#if defined(__riscv_float_abi_single) +#if (__riscv_flen == 32) flw f0, 31*8(sp) // Recover ft0 flw f1, 32*8(sp) // Recover ft1 flw f2, 33*8(sp) // Recover ft2 @@ -309,7 +342,7 @@ _tx_thread_no_preempt_restore: flw f31,62*8(sp) // Recover ft11 ld t0, 63*8(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fld f0, 31*8(sp) // Recover ft0 fld f1, 32*8(sp) // Recover ft1 fld f2, 33*8(sp) // Recover ft2 @@ -318,6 +351,20 @@ _tx_thread_no_preempt_restore: fld f5, 36*8(sp) // Recover ft5 fld f6, 37*8(sp) // Recover ft6 fld f7, 38*8(sp) // Recover ft7 +#if defined(__riscv_float_abi_single) + fld f8, 39*8(sp) // Recover fs0 + fld f9, 40*8(sp) // Recover fs1 + fld f18, 49*8(sp) // Recover fs2 + fld f19, 50*8(sp) // Recover fs3 + fld f20, 51*8(sp) // Recover fs4 + fld f21, 52*8(sp) // Recover fs5 + fld f22, 53*8(sp) // Recover fs6 + fld f23, 54*8(sp) // Recover fs7 + fld f24, 55*8(sp) // Recover fs8 + fld f25, 56*8(sp) // Recover fs9 + fld f26, 57*8(sp) // Recover fs10 + fld f27, 58*8(sp) // Recover fs11 +#endif fld f10,41*8(sp) // Recover fa0 fld f11,42*8(sp) // Recover fa1 fld f12,43*8(sp) // Recover fa2 @@ -333,6 +380,7 @@ _tx_thread_no_preempt_restore: ld t0, 63*8(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif +_tx_thread_no_preempt_skip_fp_restore: #if defined(__riscv_vector) /* Recover vector registers v0-v31 */ @@ -384,6 +432,10 @@ _tx_thread_no_preempt_restore: li t0, 0x6000 // Set FS=Dirty (bits 14:13) for FP state or t1, t1, t0 #endif +#if defined(__riscv_vector) + li t0, 0x0600 // Set VS bits (bits 10:9 to 11, Dirty) for restored vector state + or t1, t1, t0 +#endif csrw sstatus, t1 // Update sstatus safely #else csrw mepc, t0 // Setup mepc @@ -399,11 +451,11 @@ _tx_thread_no_preempt_restore: andi t1, t1, ~0x8 // Clear MIE, Hardware will restore it from MPIE #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - li t0, 0x2000 // Set FS bits for FP state + li t0, 0x6000 or t1, t1, t0 #endif #if defined(__riscv_vector) - li t0, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state + li t0, 0x0600 or t1, t1, t0 #endif csrw mstatus, t1 // Update mstatus safely @@ -427,18 +479,10 @@ _tx_thread_no_preempt_restore: ld t5, 14*8(sp) // Recover t5 ld t6, 13*8(sp) // Recover t6 -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*8 // Recover stack frame - with floating point enabled -#else - addi sp, sp, 32*8 // Recover stack frame - without floating point enabled -#endif + addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame #if defined(__riscv_vector) -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t0, sp, -65*8 -#else - addi t0, sp, -32*8 -#endif + addi t0, sp, -TX_TRAP_FRAME_SIZE csrr t1, vlenb // Get vector register byte length slli t1, t1, 5 // Multiply by 32 (number of vector registers) addi t1, t1, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr @@ -464,8 +508,10 @@ _tx_thread_preempt_restore: ori t3, zero, 1 // Build interrupt stack type sd t3, 0(t0) // Store stack type - /* Store floating point preserved registers. */ -#ifdef __riscv_float_abi_single + /* Store floating point preserved registers. LP64F saved the complete + FLEN=64 state before the C interrupt handler ran. */ +#if !defined(__riscv_float_abi_single) || (__riscv_flen != 64) +#if (__riscv_flen == 32) fsw f8, 39*8(t0) // Store fs0 fsw f9, 40*8(t0) // Store fs1 fsw f18, 49*8(t0) // Store fs2 @@ -478,7 +524,7 @@ _tx_thread_preempt_restore: fsw f25, 56*8(t0) // Store fs9 fsw f26, 57*8(t0) // Store fs10 fsw f27, 58*8(t0) // Store fs11 -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fsd f8, 39*8(t0) // Store fs0 fsd f9, 40*8(t0) // Store fs1 fsd f18, 49*8(t0) // Store fs2 @@ -492,36 +538,12 @@ _tx_thread_preempt_restore: fsd f26, 57*8(t0) // Store fs10 fsd f27, 58*8(t0) // Store fs11 #endif - -#if defined(__riscv_vector) - /* Store vector registers and CSRs */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t1, t0, 64*8 -#else - addi t1, t0, 31*8 #endif - /* Store vector CSRs */ - csrr t2, vstart // Store vstart - sd t2, 0*8(t1) - csrr t2, vtype // Store vtype - sd t2, 1*8(t1) - csrr t2, vl // Store vl - sd t2, 2*8(t1) - csrr t2, vcsr // Store vcsr - sd t2, 3*8(t1) - /* Store vector registers v0-v31 */ - addi t2, t1, 4*8 - vsetvli t3, zero, e8, m8, ta, ma - vse8.v v0, 0(t2) // Store v0 ~ v7 - add t2, t2, t3 - vse8.v v8, 0(t2) // Store v8 ~ v15 - add t2, t2, t3 - vse8.v v16, 0(t2) // Store v16 ~ v23 - add t2, t2, t3 - vse8.v v24, 0(t2) // Store v24 ~ v31 - add t2, t2, t3 -#endif + /* No vector save here. _tx_thread_context_save stored v0-v31 and the + vector CSRs before the C handler ran. The psABI treats v0-v31, vl and + vtype as caller-saved, so the handler may have changed them; a second + store here would overwrite the good copy with the handler's state. */ /* Store standard preserved registers. */ diff --git a/ports/risc-v64/gnu/src/tx_thread_context_save.S b/ports/risc-v64/gnu/src/tx_thread_context_save.S index 7935bfee..1924bd6e 100644 --- a/ports/risc-v64/gnu/src/tx_thread_context_save.S +++ b/ports/risc-v64/gnu/src/tx_thread_context_save.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -21,6 +22,8 @@ /**************************************************************************/ .section .text +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -30,6 +33,7 @@ /* AUTHOR */ /* */ /* Scott Larson, Microsoft Corporation */ +/* Wei-Chen Lai, National Cheng Kung University */ /* */ /* DESCRIPTION */ /* */ @@ -67,14 +71,14 @@ _tx_thread_context_save: sd t1, 18*8(sp) la t0, _tx_thread_system_state // Pickup address of system state - ld t1, 0(t0) // Pickup system state + lw t1, 0(t0) // Pickup system state /* Check for a nested interrupt condition. */ /* if (_tx_thread_system_state++) { */ beqz t1, _tx_thread_not_nested_save // If 0, first interrupt condition addi t1, t1, 1 // Increment the interrupt counter - sd t1, 0(t0) // Store the interrupt counter + sw t1, 0(t0) // Store the interrupt counter /* Nested interrupt condition. Save the rest of the scratch registers on the stack and return to the @@ -101,8 +105,17 @@ _tx_thread_context_save: #endif sd t0, 30*8(sp) // Save it on the stack + /* Save mstatus and skip FP state if FS is Off. */ + csrr t0, mstatus + sd t0, 29*8(sp) // Save mstatus +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + srli t1, t0, 13 + andi t1, t1, 0x3 + beqz t1, _tx_thread_skip_nested_fpu_save // Skip if FS was Off +#endif + /* Save floating point scratch registers if floating point is enabled. */ -#ifdef __riscv_float_abi_single +#if (__riscv_flen == 32) fsw f0, 31*8(sp) // Store ft0 fsw f1, 32*8(sp) // Store ft1 fsw f2, 33*8(sp) // Store ft2 @@ -125,7 +138,7 @@ _tx_thread_context_save: fsw f31,62*8(sp) // Store ft11 csrr t0, fcsr sd t0, 63*8(sp) // Store fcsr -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fsd f0, 31*8(sp) // Store ft0 fsd f1, 32*8(sp) // Store ft1 fsd f2, 33*8(sp) // Store ft2 @@ -134,6 +147,20 @@ _tx_thread_context_save: fsd f5, 36*8(sp) // Store ft5 fsd f6, 37*8(sp) // Store ft6 fsd f7, 38*8(sp) // Store ft7 +#if defined(__riscv_float_abi_single) + fsd f8, 39*8(sp) // Store fs0 + fsd f9, 40*8(sp) // Store fs1 + fsd f18, 49*8(sp) // Store fs2 + fsd f19, 50*8(sp) // Store fs3 + fsd f20, 51*8(sp) // Store fs4 + fsd f21, 52*8(sp) // Store fs5 + fsd f22, 53*8(sp) // Store fs6 + fsd f23, 54*8(sp) // Store fs7 + fsd f24, 55*8(sp) // Store fs8 + fsd f25, 56*8(sp) // Store fs9 + fsd f26, 57*8(sp) // Store fs10 + fsd f27, 58*8(sp) // Store fs11 +#endif fsd f10,41*8(sp) // Store fa0 fsd f11,42*8(sp) // Store fa1 fsd f12,43*8(sp) // Store fa2 @@ -149,6 +176,7 @@ _tx_thread_context_save: csrr t0, fcsr sd t0, 63*8(sp) // Store fcsr #endif +_tx_thread_skip_nested_fpu_save: #if defined(__riscv_vector) /* Store vector registers and CSRs */ @@ -181,7 +209,11 @@ _tx_thread_context_save: #endif #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + addi sp, sp, -16 // Reserve space to save the return address + sd ra, 0(sp) // Save the return address call _tx_execution_isr_enter // Call the ISR execution enter function + ld ra, 0(sp) // Recover the return address + addi sp, sp, 16 // Recover the reserved stack space #endif ret // Return to calling ISR @@ -193,7 +225,7 @@ _tx_thread_not_nested_save: /* else if (_tx_thread_current_ptr) { */ addi t1, t1, 1 // Increment the interrupt counter - sd t1, 0(t0) // Store the interrupt counter + sw t1, 0(t0) // Store the interrupt counter /* Not nested: Find the user thread that was running and load our SP */ @@ -225,8 +257,17 @@ _tx_thread_not_nested_save: #endif sd t1, 30*8(sp) // Save it on the stack + /* Save mstatus and skip FP state if FS is Off. */ + csrr t1, mstatus + sd t1, 29*8(sp) // Save mstatus +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + srli t2, t1, 13 + andi t2, t2, 0x3 + beqz t2, _tx_thread_skip_fpu_save // Skip if FS was Off +#endif + /* Save floating point scratch registers if floating point is enabled. */ -#ifdef __riscv_float_abi_single +#if (__riscv_flen == 32) fsw f0, 31*8(sp) // Store ft0 fsw f1, 32*8(sp) // Store ft1 fsw f2, 33*8(sp) // Store ft2 @@ -249,7 +290,7 @@ _tx_thread_not_nested_save: fsw f31,62*8(sp) // Store ft11 csrr t0, fcsr sd t0, 63*8(sp) // Store fcsr -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fsd f0, 31*8(sp) // Store ft0 fsd f1, 32*8(sp) // Store ft1 fsd f2, 33*8(sp) // Store ft2 @@ -258,6 +299,20 @@ _tx_thread_not_nested_save: fsd f5, 36*8(sp) // Store ft5 fsd f6, 37*8(sp) // Store ft6 fsd f7, 38*8(sp) // Store ft7 +#if defined(__riscv_float_abi_single) + fsd f8, 39*8(sp) // Store fs0 + fsd f9, 40*8(sp) // Store fs1 + fsd f18, 49*8(sp) // Store fs2 + fsd f19, 50*8(sp) // Store fs3 + fsd f20, 51*8(sp) // Store fs4 + fsd f21, 52*8(sp) // Store fs5 + fsd f22, 53*8(sp) // Store fs6 + fsd f23, 54*8(sp) // Store fs7 + fsd f24, 55*8(sp) // Store fs8 + fsd f25, 56*8(sp) // Store fs9 + fsd f26, 57*8(sp) // Store fs10 + fsd f27, 58*8(sp) // Store fs11 +#endif fsd f10,41*8(sp) // Store fa0 fsd f11,42*8(sp) // Store fa1 fsd f12,43*8(sp) // Store fa2 @@ -273,6 +328,7 @@ _tx_thread_not_nested_save: csrr t0, fcsr sd t0, 63*8(sp) // Store fcsr #endif +_tx_thread_skip_fpu_save: #if defined(__riscv_vector) /* Store vector registers and CSRs */ @@ -316,7 +372,11 @@ _tx_thread_not_nested_save: #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY /* _tx_execution_isr_enter is called with thread stack pointer */ + addi sp, sp, -16 // Reserve space to save the return address + sd ra, 0(sp) // Save the return address call _tx_execution_isr_enter // Call the ISR execution enter function + ld ra, 0(sp) // Recover the return address + addi sp, sp, 16 // Recover the reserved stack space #endif la t0, _tx_thread_system_stack_ptr // Pickup system stack pointer address @@ -331,25 +391,21 @@ _tx_thread_idle_system_save: #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + addi sp, sp, -16 // Reserve space to save the return address + sd ra, 0(sp) // Save the return address call _tx_execution_isr_enter // Call the ISR execution enter function + ld ra, 0(sp) // Recover the return address + addi sp, sp, 16 // Recover the reserved stack space #endif /* Interrupt occurred in the scheduling loop. */ /* } } */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*8 // Recover stack frame - with floating point enabled -#else - addi sp, sp, 32*8 // Recover the reserved stack space -#endif + addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame - with floating point enabled (65*8 data + 8 pad) #if defined(__riscv_vector) -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t0, sp, -65*8 -#else - addi t0, sp, -32*8 -#endif + addi t0, sp, -TX_TRAP_FRAME_SIZE csrr t1, vlenb // Get vector register byte length slli t1, t1, 5 // Multiply by 32 (number of vector registers) addi t1, t1, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr diff --git a/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S b/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S index b43d9558..d791e508 100644 --- a/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S +++ b/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S @@ -27,7 +27,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_interrupt_control RISC-V64/GNU */ -/* 6.2.1 */ +/* 6.5.1.202602a */ /* AUTHOR */ /* */ /* Scott Larson, Microsoft Corporation */ @@ -61,23 +61,25 @@ _tx_thread_interrupt_control: /* Pickup current interrupt lockout posture. */ #ifdef TX_RISCV_SMODE - csrr t0, sstatus - mv t1, t0 // Save original sstatus for return - li t2, ~0x02 // Build mask to clear SIE (bit 1) - and t0, t0, t2 // Clear SIE bit + li t1, 0x02 // Build SIE bit mask (bit 1) andi a0, a0, 0x02 // Mask incoming to only SIE bit - or t0, t0, a0 // Set requested SIE state - csrw sstatus, t0 - andi a0, t1, 0x02 // Return original SIE bit + bnez a0, 1f // If set, enable interrupts + csrrc t0, sstatus, t1 // Atomically clear SIE, read old sstatus + j 2f +1: + csrrs t0, sstatus, t1 // Atomically set SIE, read old sstatus +2: + andi a0, t0, 0x02 // Return original SIE bit #else - csrr t0, mstatus - mv t1, t0 // Save original mstatus for return - li t2, ~0x08 // Build mask to clear MIE - and t0, t0, t2 // Clear MIE bit + li t1, 0x08 // Build MIE bit mask (bit 3) andi a0, a0, 0x08 // Mask incoming to only MIE bit - or t0, t0, a0 // Set requested MIE state - csrw mstatus, t0 - andi a0, t1, 0x08 // Return original MIE bit + bnez a0, 1f // If set, enable interrupts + csrrc t0, mstatus, t1 // Atomically clear MIE, read old mstatus + j 2f +1: + csrrs t0, mstatus, t1 // Atomically set MIE, read old mstatus +2: + andi a0, t0, 0x08 // Return original MIE bit #endif ret /* } */ diff --git a/ports/risc-v64/gnu/src/tx_thread_schedule.S b/ports/risc-v64/gnu/src/tx_thread_schedule.S index 860adf0b..26220726 100644 --- a/ports/risc-v64/gnu/src/tx_thread_schedule.S +++ b/ports/risc-v64/gnu/src/tx_thread_schedule.S @@ -58,6 +58,9 @@ /**************************************************************************/ /* VOID _tx_thread_schedule(VOID) { */ +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE + .equ TX_SOL_FRAME_SIZE, TX_RISCV_SOL_FRAME_SIZE .global _tx_thread_schedule _tx_thread_schedule: @@ -140,9 +143,18 @@ _tx_thread_schedule_loop: ld t2, 0(sp) // Pickup stack type beqz t2, _tx_thread_synch_return // If 0, solicited thread return - /* Determine if floating point registers need to be recovered. */ + /* Determine if floating point registers need to be recovered. This is an + interrupt frame, so _tx_thread_context_save built it and may have + skipped the FP stores when mstatus.FS was Off. Read back the same slot + it wrote rather than reloading whatever those slots happen to hold. */ +#if (__riscv_flen == 32) || (__riscv_flen == 64) + ld t1, 29*8(sp) // Pickup saved mstatus + srli t1, t1, 13 + andi t1, t1, 0x3 + beqz t1, _tx_thread_schedule_skip_fp_restore // Skip if FS was Off +#endif -#if defined(__riscv_float_abi_single) +#if (__riscv_flen == 32) flw f0, 31*8(sp) // Recover ft0 flw f1, 32*8(sp) // Recover ft1 flw f2, 33*8(sp) // Recover ft2 @@ -177,7 +189,7 @@ _tx_thread_schedule_loop: flw f31,62*8(sp) // Recover ft11 ld t0, 63*8(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fld f0, 31*8(sp) // Recover ft0 fld f1, 32*8(sp) // Recover ft1 fld f2, 33*8(sp) // Recover ft2 @@ -213,6 +225,7 @@ _tx_thread_schedule_loop: ld t0, 63*8(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif +_tx_thread_schedule_skip_fp_restore: #if defined(__riscv_vector) /* Recover vector registers v0-v31 */ @@ -259,6 +272,10 @@ _tx_thread_schedule_loop: li t1, 0x6000 // Set FS=Dirty (bits 14:13) or t0, t0, t1 #endif +#if defined(__riscv_vector) + li t1, 0x0600 + or t0, t0, t1 +#endif csrw sstatus, t0 // Update sstatus safely #else csrw mepc, t0 // Store mepc @@ -274,7 +291,7 @@ _tx_thread_schedule_loop: or t0, t0, t1 #endif #if defined(__riscv_vector) - li t1, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state + li t1, 0x0600 or t0, t0, t1 #endif csrw mstatus, t0 // Set mstatus @@ -309,17 +326,9 @@ _tx_thread_schedule_loop: ld t5, 14*8(sp) // Recover t5 ld t6, 13*8(sp) // Recover t6 -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*8 // Recover stack frame - with floating point registers -#else - addi sp, sp, 32*8 // Recover stack frame - without floating point registers -#endif + addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame - with floating point registers (65*8 data + 8 pad) #if defined(__riscv_vector) -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t0, sp, -65*8 -#else - addi t0, sp, -32*8 -#endif + addi t0, sp, -TX_TRAP_FRAME_SIZE csrr t1, vlenb // Get vector register byte length slli t1, t1, 5 // Multiply by 32 (number of vector registers) addi t1, t1, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr @@ -336,7 +345,7 @@ _tx_thread_schedule_loop: _tx_thread_synch_return: -#if defined(__riscv_float_abi_single) +#if (__riscv_flen == 32) flw f8, 15*8(sp) // Recover fs0 flw f9, 16*8(sp) // Recover fs1 flw f18,17*8(sp) // Recover fs2 @@ -351,7 +360,7 @@ _tx_thread_synch_return: flw f27,26*8(sp) // Recover fs11 ld t0, 27*8(sp) // Recover fcsr csrw fcsr, t0 // -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fld f8, 15*8(sp) // Recover fs0 fld f9, 16*8(sp) // Recover fs1 fld f18,17*8(sp) // Recover fs2 @@ -418,11 +427,7 @@ _tx_thread_synch_return: #else csrw mstatus, t0 // Store mstatus, enables interrupt #endif -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 29*8 // Recover stack frame -#else - addi sp, sp, 16*8 // Recover stack frame -#endif + addi sp, sp, TX_SOL_FRAME_SIZE // Recover stack frame (29*8 data + 8 pad) #if defined(__riscv_vector) csrr t1, vlenb // Get vector register byte length slli t1, t1, 5 // Multiply by 32 (number of vector registers) diff --git a/ports/risc-v64/gnu/src/tx_thread_stack_build.S b/ports/risc-v64/gnu/src/tx_thread_stack_build.S index 86cab4f0..47e5c995 100644 --- a/ports/risc-v64/gnu/src/tx_thread_stack_build.S +++ b/ports/risc-v64/gnu/src/tx_thread_stack_build.S @@ -21,6 +21,8 @@ /**************************************************************************/ .section .text +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -30,6 +32,7 @@ /* AUTHOR */ /* */ /* Scott Larson, Microsoft Corporation */ +/* Wei-Chen Lai, National Cheng Kung University */ /* */ /* DESCRIPTION */ /* */ @@ -92,7 +95,7 @@ _tx_thread_stack_build: x11 26 Initial a1 x10 27 Initial a0 x1 28 Initial ra - -- 29 reserved + mstatus 29 Initial mstatus mepc 30 Initial mepc If floating point support: f0 31 Inital ft0 @@ -138,6 +141,9 @@ If vector extension support: ... v31 99 Initial v31 + With floating point enabled, 8 pad bytes sit at the top of the frame + (bytes 520-527) so the 528-byte total keeps sp 16-byte aligned. + Stack Bottom: (higher memory address) */ ld t0, 24(a0) // Pickup end of stack area @@ -146,11 +152,7 @@ If vector extension support: /* Actually build the stack frame. */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t0, t0, -65*8 -#else - addi t0, t0, -32*8 // Allocate space for the stack frame -#endif + addi t0, t0, -TX_TRAP_FRAME_SIZE #if defined(__riscv_vector) /* Vector extension support: calculate space based on vlenb */ @@ -192,6 +194,8 @@ If vector extension support: sd zero, 26*8(t0) // Initial a1 sd zero, 27*8(t0) // Initial a0 sd zero, 28*8(t0) // Initial ra + li t1, 0x2000 // mstatus.FS = Initial + sd t1, 29*8(t0) // Initial mstatus sd a1, 30*8(t0) // Initial mepc/sepc (thread entry point) #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) sd zero, 31*8(t0) // Initial ft0 @@ -226,8 +230,7 @@ If vector extension support: sd zero, 60*8(t0) // Initial ft9 sd zero, 61*8(t0) // Initial ft10 sd zero, 62*8(t0) // Initial ft11 - csrr a1, fcsr // Read fcsr for initial value - sd a1, 63*8(t0) // Initial fcsr + sd zero, 63*8(t0) // Initial fcsr (0: no sticky flags, round-to-nearest) #endif #if defined(__riscv_vector) diff --git a/ports/risc-v64/gnu/src/tx_thread_system_return.S b/ports/risc-v64/gnu/src/tx_thread_system_return.S index 583b3f3e..2f4daeed 100644 --- a/ports/risc-v64/gnu/src/tx_thread_system_return.S +++ b/ports/risc-v64/gnu/src/tx_thread_system_return.S @@ -57,17 +57,15 @@ /**************************************************************************/ /* VOID _tx_thread_system_return(VOID) { */ +#include "tx_port.h" + .equ TX_SOL_FRAME_SIZE, TX_RISCV_SOL_FRAME_SIZE .global _tx_thread_system_return _tx_thread_system_return: /* Save minimal context on the stack. */ /* sp -= sizeof(stack_frame); */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, -29*8 // Allocate space on the stack - with floating point enabled -#else - addi sp, sp, -16*8 // Allocate space on the stack - without floating point enabled -#endif + addi sp, sp, -TX_SOL_FRAME_SIZE // Allocate space on the stack #if defined(__riscv_vector) csrr t1, vlenb // Get vector register byte length slli t1, t1, 5 // Multiply by 32 (number of vector registers) @@ -76,7 +74,7 @@ _tx_thread_system_return: #endif /* Store floating point preserved registers. */ -#if defined(__riscv_float_abi_single) +#if (__riscv_flen == 32) fsw f8, 15*8(sp) // Store fs0 fsw f9, 16*8(sp) // Store fs1 fsw f18, 17*8(sp) // Store fs2 @@ -91,7 +89,7 @@ _tx_thread_system_return: fsw f27, 26*8(sp) // Store fs11 csrr t0, fcsr sd t0, 27*8(sp) // Store fcsr -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fsd f8, 15*8(sp) // Store fs0 fsd f9, 16*8(sp) // Store fs1 fsd f18, 17*8(sp) // Store fs2 diff --git a/ports/risc-v64/gnu/src/tx_timer_interrupt.S b/ports/risc-v64/gnu/src/tx_timer_interrupt.S index 53e572f3..207d6677 100644 --- a/ports/risc-v64/gnu/src/tx_timer_interrupt.S +++ b/ports/risc-v64/gnu/src/tx_timer_interrupt.S @@ -88,7 +88,7 @@ _tx_timer_interrupt: /* Check for expiration. */ /* if (_tx_timer_time_slice == 0) */ - bgtz t3, _tx_timer_no_time_slice // If not 0, has not expired yet + bnez t3, _tx_timer_no_time_slice // If not 0, has not expired yet li t1, 1 // Build expired flag /* Set the time-slice expired flag. */ @@ -181,7 +181,7 @@ _tx_timer_dont_activate: /* if (_tx_timer_expired_time_slice) { */ - andi t2, t6, 1 // Is the timer expired bit set? + andi t2, t6, 1 // Is the time-slice expired bit set? beqz t2, _tx_timer_not_ts_expiration // If not, skip time slice processing /* Time slice interrupted thread. */ |
