@@ -8,6 +8,7 @@
#include <asm/ptrace.h>
+#define RVV_MAGIC 0x53465457
/*
* Signal context structure
*
@@ -17,6 +18,7 @@
struct sigcontext {
struct user_regs_struct sc_regs;
union __riscv_fp_state sc_fpregs;
+ struct __riscv_v_state sc_vregs;
};
#endif /* _UAPI_ASM_RISCV_SIGCONTEXT_H */
@@ -83,6 +83,80 @@ static long save_fp_state(struct pt_regs *regs,
#define restore_fp_state(task, regs) (0)
#endif
+#ifdef CONFIG_VECTOR
+static long restore_v_state(struct pt_regs *regs, struct sigcontext *sc)
+{
+ long err;
+ struct __riscv_v_state __user *state = &sc->sc_vregs;
+ void *datap;
+ __u32 magic;
+
+ /* Get magic number and check it. */
+ err = __get_user(magic, &state->magic);
+ if (unlikely(err))
+ return err;
+
+ if (magic != RVV_MAGIC)
+ return -EINVAL;
+
+ /* Copy everything of __riscv_v_state except datap. */
+ err = __copy_from_user(¤t->thread.vstate, state,
+ RISCV_V_STATE_DATAP);
+ if (unlikely(err))
+ return err;
+
+ /* Copy the pointer datap itself. */
+ err = __get_user(datap, &state->datap);
+ if (unlikely(err))
+ return err;
+
+
+ /* Copy the whole vector content from user space datap. */
+ err = __copy_from_user(current->thread.vstate.datap, datap,
+ current->thread.vstate.size);
+ if (unlikely(err))
+ return err;
+
+ vstate_restore(current, regs);
+
+ return err;
+}
+
+static long save_v_state(struct pt_regs *regs, struct sigcontext *sc)
+{
+ long err;
+ struct __riscv_v_state __user *state = &sc->sc_vregs;
+ /* Set the datap right after the sigcntext structure. */
+ void *datap = sc + 1;
+
+ vstate_save(current, regs);
+ /* Copy everything of vstate but datap. */
+ err = __copy_to_user(state, ¤t->thread.vstate,
+ RISCV_V_STATE_DATAP);
+ if (unlikely(err))
+ return err;
+
+ /* Copy the magic number. */
+ err = __put_user(RVV_MAGIC, &state->magic);
+ if (unlikely(err))
+ return err;
+
+ /* Copy the pointer datap itself. */
+ err = __put_user(datap, &state->datap);
+ if (unlikely(err))
+ return err;
+
+ /* Copy the whole vector content to user space datap. */
+ err = __copy_to_user(datap, current->thread.vstate.datap,
+ current->thread.vstate.size);
+
+ return err;
+}
+#else
+#define save_v_state(task, regs) (0)
+#define restore_v_state(task, regs) (0)
+#endif
+
static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
{
@@ -92,6 +166,9 @@ static long restore_sigcontext(struct pt_regs *regs,
/* Restore the floating-point state. */
if (has_fpu)
err |= restore_fp_state(regs, &sc->sc_fpregs);
+ /* Restore the vector state. */
+ if (has_vector)
+ err |= restore_v_state(regs, sc);
return err;
}
@@ -101,13 +178,16 @@ SYSCALL_DEFINE0(rt_sigreturn)
struct rt_sigframe __user *frame;
struct task_struct *task;
sigset_t set;
+ size_t frame_size = sizeof(*frame);
/* Always make any pending restarted system calls return -EINTR */
current->restart_block.fn = do_no_restart_syscall;
frame = (struct rt_sigframe __user *)regs->sp;
- if (!access_ok(frame, sizeof(*frame)))
+ if (has_vector)
+ frame_size += current->thread.vstate.size;
+ if (!access_ok(frame, frame_size))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
@@ -145,6 +225,9 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,
/* Save the floating-point state. */
if (has_fpu)
err |= save_fp_state(regs, &sc->sc_fpregs);
+ /* Save the vector state. */
+ if (has_vector)
+ err |= save_v_state(regs, sc);
return err;
}
@@ -176,9 +259,12 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
{
struct rt_sigframe __user *frame;
long err = 0;
+ size_t frame_size = sizeof(*frame);
- frame = get_sigframe(ksig, regs, sizeof(*frame));
- if (!access_ok(frame, sizeof(*frame)))
+ if (has_vector)
+ frame_size += current->thread.vstate.size;
+ frame = get_sigframe(ksig, regs, frame_size);
+ if (!access_ok(frame, frame_size))
return -EFAULT;
err |= copy_siginfo_to_user(&frame->info, &ksig->info);