From ef308b3f7cdac10af24e4165e5ab8217513ccf90 Mon Sep 17 00:00:00 2001 From: zhouzhou_code <2031145985@qq.com> Date: Wed, 26 Aug 2026 01:57:40 +0800 Subject: [PATCH] perf(riscv): defer callee save on no-switch timer IRQ Signed-off-by: zhouzhou_code <2031145985@qq.com> --- portable/GCC/RISC-V/portASM.S | 9 ++- portable/GCC/RISC-V/portContext.h | 114 ++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 3 deletions(-) diff --git a/portable/GCC/RISC-V/portASM.S b/portable/GCC/RISC-V/portASM.S index 9d36d78f9..577d69dc9 100644 --- a/portable/GCC/RISC-V/portASM.S +++ b/portable/GCC/RISC-V/portASM.S @@ -338,13 +338,16 @@ freertos_risc_v_interrupt_handler: /*-----------------------------------------------------------*/ .section .text.freertos_risc_v_mtimer_interrupt_handler +.align 2 freertos_risc_v_mtimer_interrupt_handler: - portcontextSAVE_INTERRUPT_CONTEXT + portcontextSAVE_TIMER_CALLER_CONTEXT portUPDATE_MTIMER_COMPARE_REGISTER call xTaskIncrementTick - beqz a0, exit_without_context_switch /* Don't switch context if incrementing tick didn't unblock a task. */ + bnez a0, mtimer_context_switch + portcontextRESTORE_TIMER_CALLER_CONTEXT +mtimer_context_switch: + portcontextSAVE_DEFERRED_TASK_STATE call vTaskSwitchContext -exit_without_context_switch: portcontextRESTORE_CONTEXT /*-----------------------------------------------------------*/ diff --git a/portable/GCC/RISC-V/portContext.h b/portable/GCC/RISC-V/portContext.h index 0ccca69a3..a0642135d 100644 --- a/portable/GCC/RISC-V/portContext.h +++ b/portable/GCC/RISC-V/portContext.h @@ -64,6 +64,10 @@ #define portCRITICAL_NESTING_OFFSET 30 #endif +/* Keep the ISR stack aligned to the RISC-V ABI while reserving metadata used + * by the machine-timer fast path. */ +#define portISR_STACK_METADATA_SIZE 16 + #if ( configENABLE_FPU == 1 ) /* Bit [14:13] in the mstatus encode the status of FPU state which is one of * the following values: @@ -379,6 +383,116 @@ store_x sp, 0 ( t0 ) /* Write sp to first TCB member. */ .endm /*-----------------------------------------------------------*/ + .macro portcontextSAVE_TIMER_CALLER_CONTEXT +addi sp, sp, -portCONTEXT_SIZE +portcontextSAVE_CALLER_REGISTERS sp + +/* Keep the fixed integer frame base available after variable-length optional + * contexts have been saved by recording it in per-hart ISR stack metadata. */ +load_x t0, xISRStackTop +addi t0, t0, -portISR_STACK_METADATA_SIZE +store_x sp, 0( t0 ) + +#if( configENABLE_FPU == 1 ) + csrr t0, mstatus + srl t1, t0, MSTATUS_FS_OFFSET + andi t1, t1, 3 + addi t2, x0, 3 + bne t1, t2, 7f + portcontexSAVE_FPU_CONTEXT +7: +#endif + +#if( configENABLE_VPU == 1 ) + csrr t0, mstatus + srl t1, t0, MSTATUS_VS_OFFSET + andi t1, t1, 3 + addi t2, x0, 3 + bne t1, t2, 8f + portcontexSAVE_VPU_CONTEXT +8: +#endif + +csrr t0, mstatus +store_x t0, 1 * portWORD_SIZE( sp ) +portasmSAVE_ADDITIONAL_REGISTERS + +#if( configENABLE_FPU == 1 ) + srl t1, t0, MSTATUS_FS_OFFSET + andi t1, t1, 3 + addi t2, x0, 3 + bne t1, t2, 9f + li t1, ~MSTATUS_FS_MASK + and t0, t0, t1 + li t1, MSTATUS_FS_CLEAN + or t0, t0, t1 + csrw mstatus, t0 +9: +#endif + +#if( configENABLE_VPU == 1 ) + srl t1, t0, MSTATUS_VS_OFFSET + andi t1, t1, 3 + addi t2, x0, 3 + bne t1, t2, 10f + li t1, ~MSTATUS_VS_MASK + and t0, t0, t1 + li t1, MSTATUS_VS_CLEAN + or t0, t0, t1 + csrw mstatus, t0 +10: +#endif + +csrr t0, mepc +store_x t0, 0 * portWORD_SIZE( sp ) +load_x t0, pxCurrentTCB +store_x sp, 0( t0 ) +load_x sp, xISRStackTop +addi sp, sp, -portISR_STACK_METADATA_SIZE + .endm + + .macro portcontextSAVE_DEFERRED_TASK_STATE +load_x t1, 0( sp ) +portcontextSAVE_CALLEE_REGISTERS t1 +load_x t0, xCriticalNesting +store_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( t1 ) + .endm + + .macro portcontextRESTORE_TIMER_CALLER_CONTEXT +load_x t1, pxCurrentTCB +load_x sp, 0( t1 ) +load_x t0, 0 * portWORD_SIZE( sp ) +csrw mepc, t0 + +portasmRESTORE_ADDITIONAL_REGISTERS + +load_x t3, 1 * portWORD_SIZE( sp ) +csrw mstatus, t3 + +#if( configENABLE_VPU == 1 ) + srl t1, t3, MSTATUS_VS_OFFSET + andi t1, t1, 3 + addi t2, x0, 3 + bne t1, t2, 11f + portcontextRESTORE_VPU_CONTEXT +11: +#endif + +#if( configENABLE_FPU == 1 ) + srl t1, t3, MSTATUS_FS_OFFSET + andi t1, t1, 3 + addi t2, x0, 3 + bne t1, t2, 12f + portcontextRESTORE_FPU_CONTEXT +12: +#endif + +portcontextRESTORE_CALLER_REGISTERS sp +addi sp, sp, portCONTEXT_SIZE +mret + .endm +/*-----------------------------------------------------------*/ + .macro portcontextSAVE_EXCEPTION_CONTEXT portcontextSAVE_CONTEXT_INTERNAL csrr a0, mcause