[PATCH] RISC-V: Clobber V registers on syscalls
Andy Chiu
andy.chiu at sifive.com
Thu Jun 22 08:47:38 PDT 2023
On Thu, Jun 22, 2023 at 5:40 AM Björn Töpel <bjorn at kernel.org> wrote:
>
> Andy Chiu <andy.chiu at sifive.com> writes:
>
> >> +static inline void riscv_v_vstate_discard(struct pt_regs *regs)
> >> +{
> >> + unsigned long vl;
> >> +
> >> + if (!riscv_v_vstate_query(regs))
> >> + return;
> >> +
> >> + riscv_v_vstate_on(regs);
> >
> > Do we need this riscv_v_vstate_on()? If it is not on we'd return
> > early in the previous "if" statement, right?
>
> riscv_v_vstate_on() just set the state to Initial, right? Or do you mean
> that riscv_v_vstate_query() is too much, and we should only check if the
> state is dirty?
>
> >> +
> >> + riscv_v_enable();
> >> + asm volatile (
> >> + ".option push\n\t"
> >> + ".option arch, +v\n\t"
> >> + "vsetvli %0, x0, e8, m8, ta, ma\n\t"
> >> + "vmv.v.i v0, 0\n\t"
> >> + "vmv.v.i v8, 0\n\t"
> >> + "vmv.v.i v16, 0\n\t"
> >> + "vmv.v.i v24, 0\n\t"
> >> + ".option pop\n\t"
> >> + : "=&r" (vl) : : "memory");
> >> + riscv_v_disable();
> >
> > Maybe consider cleaning the vstate (status.vs) here. As such we don't
> > have to save V during context switch.
>
> It's late, and I'm slower than usual. The regs are cleared, and the
> state is Initial. No save on context switch, but restore, right?
Yes, it's my bad, you are right. I sometime messed around the "real"
status.VS with the one in the userspace context :P
>
> > Or, maybe we could set vstate as off during syscall and discard V-reg
> > + restore status.VS when returning back to userspace?
>
> Hmm, interesting. We need to track the status.VS to restore somewhere...
Maybe something like this?
diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h
index 04c0b07bf6cd..79de9ca83391 100644
--- a/arch/riscv/include/asm/vector.h
+++ b/arch/riscv/include/asm/vector.h
@@ -43,6 +43,11 @@ static inline void riscv_v_vstate_on(struct pt_regs *regs)
regs->status = (regs->status & ~SR_VS) | SR_VS_INITIAL;
}
+static inline void riscv_v_vstate_dirty(struct pt_regs *regs)
+{
+ regs->status = (regs->status & ~SR_VS) | SR_VS_DIRTY;
+}
+
static inline bool riscv_v_vstate_query(struct pt_regs *regs)
{
return (regs->status & SR_VS) != 0;
@@ -163,6 +168,24 @@ static inline void __switch_to_vector(struct task_struct *prev,
void riscv_v_vstate_ctrl_init(struct task_struct *tsk);
bool riscv_v_vstate_ctrl_user_allowed(void);
+static inline void riscv_v_vstate_discard(struct pt_regs *regs)
+{
+ unsigned long vl;
+
+ riscv_v_enable();
+ asm volatile (
+ ".option push\n\t"
+ ".option arch, +v\n\t"
+ "vsetvli %0, x0, e8, m8, ta, ma\n\t"
+ "vmv.v.i v0, 0\n\t"
+ "vmv.v.i v8, 0\n\t"
+ "vmv.v.i v16, 0\n\t"
+ "vmv.v.i v24, 0\n\t"
+ ".option pop\n\t"
+ : "=&r" (vl) : : "memory");
+ riscv_v_disable();
+}
+
#else /* ! CONFIG_RISCV_ISA_V */
struct pt_regs;
@@ -178,6 +201,8 @@ static inline bool riscv_v_vstate_ctrl_user_allowed(void) { return false; }
#define __switch_to_vector(__prev, __next) do {} while (0)
#define riscv_v_vstate_off(regs) do {} while (0)
#define riscv_v_vstate_on(regs) do {} while (0)
+#define riscv_v_vstate_dirty(regs) do {} while (0)
+#define riscv_v_vstate_discard(regs) do {} while (0)
#endif /* CONFIG_RISCV_ISA_V */
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 24d309c6ab8d..e36b69c9b07f 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -291,10 +291,14 @@ asmlinkage __visible __trap_section void do_trap_ecall_u(struct pt_regs *regs)
{
if (user_mode(regs)) {
ulong syscall = regs->a7;
+ bool v_is_on;
regs->epc += 4;
regs->orig_a0 = regs->a0;
+ v_is_on = riscv_v_vstate_query(regs);
+ riscv_v_vstate_off(regs);
+
syscall = syscall_enter_from_user_mode(regs, syscall);
if (syscall < NR_syscalls)
@@ -303,6 +307,10 @@ asmlinkage __visible __trap_section void do_trap_ecall_u(struct pt_regs *regs)
regs->a0 = -ENOSYS;
syscall_exit_to_user_mode(regs);
+ if (v_is_on) {
+ riscv_v_vstate_discard(regs);
+ riscv_v_vstate_dirty(regs);
+ }
} else {
irqentry_state_t state = irqentry_nmi_enter(regs);
>
>
> Björn
Thanks,
Andy
More information about the linux-riscv
mailing list