@@ -23,6 +23,7 @@ typedef struct user_regs_struct elf_gregset_t;
typedef __u64 elf_fpreg_t;
typedef union __riscv_fp_state elf_fpregset_t;
#define ELF_NFPREG (sizeof(struct __riscv_d_ext_state) / sizeof(elf_fpreg_t))
+#define ELF_NVREG (sizeof(struct __riscv_v_state) / sizeof(elf_greg_t))
#if __riscv_xlen == 64
#define ELF_RISCV_R_SYM(r_info) ELF64_R_SYM(r_info)
@@ -10,6 +10,7 @@
#include <asm/ptrace.h>
#include <asm/syscall.h>
#include <asm/thread_info.h>
+#include <asm/switch_to.h>
#include <linux/audit.h>
#include <linux/ptrace.h>
#include <linux/elf.h>
@@ -26,6 +27,9 @@ enum riscv_regset {
#ifdef CONFIG_FPU
REGSET_F,
#endif
+#ifdef CONFIG_VECTOR
+ REGSET_V,
+#endif
};
static int riscv_gpr_get(struct task_struct *target,
@@ -92,6 +96,107 @@ static int riscv_fpr_set(struct task_struct *target,
}
#endif
+#ifdef CONFIG_VECTOR
+static int riscv_vr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+ struct __riscv_v_state *vstate = &target->thread.vstate;
+ /* Set the datap right after the address of vstate. */
+ void *datap = ubuf + sizeof(struct __riscv_v_state);
+ u32 magic = RVV_MAGIC;
+
+ /* Copy the magic number. */
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &magic, 0,
+ sizeof(u32));
+ if (unlikely(ret))
+ return ret;
+
+ /* Copy rest of vstate except datap. */
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, vstate, 0,
+ RISCV_V_STATE_DATAP);
+ if (unlikely(ret))
+ return ret;
+
+ /* Copy the pointer datap itself. */
+ pos = 0;
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &datap, 0,
+ sizeof(vstate->datap));
+ if (unlikely(ret))
+ return ret;
+
+#if __riscv_xlen == 32
+ /* Skip copy _padding. */
+ size = sizeof(vstate->__padding);
+ count -= size;
+ ubuf += size;
+#endif
+
+ /* Copy all the vector registers. */
+ pos = 0;
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ vstate->datap, 0, vstate->size);
+ return ret;
+}
+
+static int riscv_vr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret, size;
+ struct __riscv_v_state *vstate = &target->thread.vstate;
+ const void *datap = ubuf + sizeof(struct __riscv_v_state);
+ const void *datap_addr = ubuf + RISCV_V_STATE_DATAP;
+ long val_datap;
+
+ /* Skip copy magic because kernel doesn't need to use it. */
+ size = sizeof(vstate->magic);
+ pos += size;
+ count -= size;
+ ubuf += size;
+
+ /* Copy rest of the vstate except datap and __padding. */
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vstate, 0,
+ RISCV_V_STATE_DATAP);
+ if (unlikely(ret))
+ return ret;
+
+ /* Check if the datap is correct address of ubuf. */
+ __get_user(val_datap, (long *)datap_addr);
+ if (val_datap != (long)datap)
+ return -EFAULT;
+
+ /* Skip copy datap. */
+ size = sizeof(vstate->datap);
+ count -= size;
+ ubuf += size;
+
+#if __riscv_xlen == 32
+ /* Skip copy _padding. */
+ size = sizeof(vstate->__padding);
+ count -= size;
+ ubuf += size;
+#endif
+
+ /* Copy all the vector registers. */
+ pos = 0;
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vstate->datap,
+ 0, vstate->size);
+ return ret;
+}
+static unsigned int riscv_vr_get_size(struct task_struct *target,
+ const struct user_regset *regset)
+{
+ if (!has_vector)
+ return 0;
+
+ return sizeof(struct __riscv_v_state) + riscv_vsize;
+}
+#endif
+
static const struct user_regset riscv_user_regset[] = {
[REGSET_X] = {
.core_note_type = NT_PRSTATUS,
@@ -111,6 +216,16 @@ static const struct user_regset riscv_user_regset[] = {
.set = &riscv_fpr_set,
},
#endif
+#ifdef CONFIG_VECTOR
+ [REGSET_V] = {
+ .core_note_type = NT_RISCV_VECTOR,
+ .align = 16,
+ .size = sizeof(unsigned long),
+ .get = riscv_vr_get,
+ .set = riscv_vr_set,
+ .get_size = riscv_vr_get_size,
+ },
+#endif
};
static const struct user_regset_view riscv_user_native_view = {
@@ -428,6 +428,7 @@ typedef struct elf64_shdr {
#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */
#define NT_MIPS_FP_MODE 0x801 /* MIPS floating-point mode */
#define NT_MIPS_MSA 0x802 /* MIPS SIMD registers */
+#define NT_RISCV_VECTOR 0x900 /* RISC-V vector registers */
/* Note header in a PT_NOTE section */
typedef struct elf32_note {