From 779806fd13c2c430dece37996e1e6c4cd1714afd Mon Sep 17 00:00:00 2001 From: Andy Chiu Date: Wed, 1 Apr 2026 23:34:14 -0500 Subject: [PATCH] riscv: vector: treat VS_INITIAL as discard The purpose of riscv_v_vstate_discard() is to invalidate v context at entries of syscalls. So users happen to use v after a syscall without re-configuring would see a failure. It was achieved by setting vector registers and CSRs to -1 and marking the context busy. However, this results in redundant saving of v-context if the process is scheduled out in a syscall. Moreover, restoring the invalidated context from memory is a costly operation. In fact, all can be prevented if we can delay vstate_discard before returning back to the user space. To be more specific, the kernel can mark v-context as INITIAL and set the restore flag at syscall entries. This is the indication for the vstate_restore, so it awares that the vstate has to be invalidated before returning back to the user space. After applying this patch, the context switch performance has improved 6.78% on vector enabled lmbench running on a FPGA with VLEN=512. The result was obtained by averaging the output from the following command. $ lat_ctx 2 Before the patch: 599.8357692 After the patch: 559.1748148 Signed-off-by: Andy Chiu Signed-off-by: Andy Chiu Signed-off-by: Linux RISC-V bot --- arch/riscv/include/asm/vector.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h index 00cb9c0982b1ae..90f77e511cad29 100644 --- a/arch/riscv/include/asm/vector.h +++ b/arch/riscv/include/asm/vector.h @@ -298,8 +298,8 @@ static inline void __riscv_v_vstate_discard(void) static inline void riscv_v_vstate_discard(struct pt_regs *regs) { if (riscv_v_vstate_query(regs)) { - __riscv_v_vstate_discard(); - __riscv_v_vstate_dirty(regs); + set_tsk_thread_flag(current, TIF_RISCV_V_DEFER_RESTORE); + riscv_v_vstate_on(regs); } } @@ -315,7 +315,9 @@ static inline void riscv_v_vstate_save(struct __riscv_v_ext_state *vstate, static inline void riscv_v_vstate_restore(struct __riscv_v_ext_state *vstate, struct pt_regs *regs) { - if (riscv_v_vstate_query(regs)) { + if (__riscv_v_vstate_check(regs->status, INITIAL)) { + __riscv_v_vstate_discard(); + } else if (riscv_v_vstate_query(regs)) { __riscv_v_vstate_restore(vstate, vstate->datap); __riscv_v_vstate_clean(regs); } @@ -326,7 +328,7 @@ static inline void riscv_v_vstate_set_restore(struct task_struct *task, { if (riscv_v_vstate_query(regs)) { set_tsk_thread_flag(task, TIF_RISCV_V_DEFER_RESTORE); - riscv_v_vstate_on(regs); + __riscv_v_vstate_clean(regs); } }