[RFC PATCH] riscv: clarify vector state semantics on syscall and context switch

Andy Chiu tchiu at tenstorrent.com
Wed May 20 23:48:55 PDT 2026


On Thu, Mar 19, 2026 at 03:37:09PM +0800, daichengrong wrote:
> The RISC-V vector specification states that executing a system call
> causes all caller-saved vector registers (v0-v31, vl, vtype) and vstart
> to become unspecified.
> 
> Currently, after calling riscv_v_vstate_discard(), the vector state 
> may still be marked as DIRTY, which can mislead the context switch 
> logic into treating the registers as containing valid user data.
> 
> This patch clarifies and tightens the kernel-side semantics:
> 
> 1. On syscall entry, the kernel checks the vector state via mstatus
>    and discards it if necessary. After discard, the state is explicitly
>    set to INIT instead of DIRTY, indicating that the vector registers
>    no longer contain meaningful user data.
> 
> 2. During context switch, the vector state is interpreted as follows:
>    - INIT: no valid user data is present, so vector register data does
>      not need to be saved.
>    - non-INIT (e.g. DIRTY): vector register data must be saved.
> 
> 3. On restore, if the state is INIT, the vector registers are treated
>    as invalid and are not restored from memory. Instead, they are
>    overwritten with a known initial value to avoid potential data
>    leakage from a previous task.
> 
> This aligns the kernel's vector state tracking with the architectural
> "unspecified" semantics while ensuring correct lazy context switching
> and preventing cross-task data leakage.
Hi daichengrong,

Good catch on spotting this optimization opportunity!

I have a patch series[1] that happens to be very similar as yours, but I
think your coding style make the code more readable (I like the way you
use _vstate_check for CLEAN on restore path).

Here are some issues where this patch breaks:
- first-use trap returns discarded vregs instead of zero'ed.
- ptrace gets stale vregs in PTRACE_SYSCALL
- context modifications through signal handler are dropped at syscall
  stops.

I will merge your patch into my v3 with all the above fixed. Hope that
sounds good to you!

[1]: https://lore.kernel.org/linux-riscv/20260402043414.2421916-2-andybnac@gmail.com/

> 
> Signed-off-by: daichengrong <daichengrong at iscas.ac.cn>
> ---
>  arch/riscv/include/asm/vector.h | 15 +++++++--------
>  1 file changed, 7 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h
> index 00cb9c0982b1..93c68a549b72 100644
> --- a/arch/riscv/include/asm/vector.h
> +++ b/arch/riscv/include/asm/vector.h
> @@ -298,8 +298,9 @@ 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);
We can skip discarding vstate here as it will be done in the restore path
> +		if (!__riscv_v_vstate_check(regs->status, INITIAL))
> +			__riscv_v_vstate_discard();
> +		riscv_v_vstate_on(regs);
>  	}
>  }
>  
> @@ -315,19 +316,17 @@ 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_check(regs->status, CLEAN))
>  		__riscv_v_vstate_restore(vstate, vstate->datap);
> -		__riscv_v_vstate_clean(regs);
> -	}
>  }
>  
>  static inline void riscv_v_vstate_set_restore(struct task_struct *task,
>  					      struct pt_regs *regs)
>  {
> -	if (riscv_v_vstate_query(regs)) {
> +	if (riscv_v_vstate_query(regs))
>  		set_tsk_thread_flag(task, TIF_RISCV_V_DEFER_RESTORE);
> -		riscv_v_vstate_on(regs);
> -	}
>  }
>  
>  #ifdef CONFIG_RISCV_ISA_V_PREEMPTIVE
> -- 
> 2.25.1
> 
> 
> _______________________________________________
> linux-riscv mailing list
> linux-riscv at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
> 

Cheers,
Andy



More information about the linux-riscv mailing list