Commit f0936363 authored by Palmer Dabbelt's avatar Palmer Dabbelt

Merge patch "RISC-V: Add ptrace support for vectors"

This resurrects the vector ptrace() support that was removed for 6.5 due
to some bugs cropping up as part of the GDB review process.

* b4-shazam-merge:
  RISC-V: Add ptrace support for vectors

Link: https://lore.kernel.org/r/20230825050248.32681-1-andy.chiu@sifive.comSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parents c23be918 9300f004
...@@ -108,13 +108,18 @@ struct __riscv_v_ext_state { ...@@ -108,13 +108,18 @@ struct __riscv_v_ext_state {
* In signal handler, datap will be set a correct user stack offset * In signal handler, datap will be set a correct user stack offset
* and vector registers will be copied to the address of datap * and vector registers will be copied to the address of datap
* pointer. * pointer.
*
* In ptrace syscall, datap will be set to zero and the vector
* registers will be copied to the address right after this
* structure.
*/ */
}; };
struct __riscv_v_regset_state {
unsigned long vstart;
unsigned long vl;
unsigned long vtype;
unsigned long vcsr;
unsigned long vlenb;
char vreg[];
};
/* /*
* According to spec: The number of bits in a single vector register, * According to spec: The number of bits in a single vector register,
* VLEN >= ELEN, which must be a power of 2, and must be no greater than * VLEN >= ELEN, which must be a power of 2, and must be no greater than
......
...@@ -25,6 +25,9 @@ enum riscv_regset { ...@@ -25,6 +25,9 @@ enum riscv_regset {
#ifdef CONFIG_FPU #ifdef CONFIG_FPU
REGSET_F, REGSET_F,
#endif #endif
#ifdef CONFIG_RISCV_ISA_V
REGSET_V,
#endif
}; };
static int riscv_gpr_get(struct task_struct *target, static int riscv_gpr_get(struct task_struct *target,
...@@ -81,6 +84,71 @@ static int riscv_fpr_set(struct task_struct *target, ...@@ -81,6 +84,71 @@ static int riscv_fpr_set(struct task_struct *target,
} }
#endif #endif
#ifdef CONFIG_RISCV_ISA_V
static int riscv_vr_get(struct task_struct *target,
const struct user_regset *regset,
struct membuf to)
{
struct __riscv_v_ext_state *vstate = &target->thread.vstate;
struct __riscv_v_regset_state ptrace_vstate;
if (!riscv_v_vstate_query(task_pt_regs(target)))
return -EINVAL;
/*
* Ensure the vector registers have been saved to the memory before
* copying them to membuf.
*/
if (target == current)
riscv_v_vstate_save(current, task_pt_regs(current));
ptrace_vstate.vstart = vstate->vstart;
ptrace_vstate.vl = vstate->vl;
ptrace_vstate.vtype = vstate->vtype;
ptrace_vstate.vcsr = vstate->vcsr;
ptrace_vstate.vlenb = vstate->vlenb;
/* Copy vector header from vstate. */
membuf_write(&to, &ptrace_vstate, sizeof(struct __riscv_v_regset_state));
/* Copy all the vector registers from vstate. */
return membuf_write(&to, vstate->datap, riscv_v_vsize);
}
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;
struct __riscv_v_ext_state *vstate = &target->thread.vstate;
struct __riscv_v_regset_state ptrace_vstate;
if (!riscv_v_vstate_query(task_pt_regs(target)))
return -EINVAL;
/* Copy rest of the vstate except datap */
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ptrace_vstate, 0,
sizeof(struct __riscv_v_regset_state));
if (unlikely(ret))
return ret;
if (vstate->vlenb != ptrace_vstate.vlenb)
return -EINVAL;
vstate->vstart = ptrace_vstate.vstart;
vstate->vl = ptrace_vstate.vl;
vstate->vtype = ptrace_vstate.vtype;
vstate->vcsr = ptrace_vstate.vcsr;
/* Copy all the vector registers. */
pos = 0;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vstate->datap,
0, riscv_v_vsize);
return ret;
}
#endif
static const struct user_regset riscv_user_regset[] = { static const struct user_regset riscv_user_regset[] = {
[REGSET_X] = { [REGSET_X] = {
.core_note_type = NT_PRSTATUS, .core_note_type = NT_PRSTATUS,
...@@ -100,6 +168,17 @@ static const struct user_regset riscv_user_regset[] = { ...@@ -100,6 +168,17 @@ static const struct user_regset riscv_user_regset[] = {
.set = riscv_fpr_set, .set = riscv_fpr_set,
}, },
#endif #endif
#ifdef CONFIG_RISCV_ISA_V
[REGSET_V] = {
.core_note_type = NT_RISCV_VECTOR,
.align = 16,
.n = ((32 * RISCV_MAX_VLENB) +
sizeof(struct __riscv_v_regset_state)) / sizeof(__u32),
.size = sizeof(__u32),
.regset_get = riscv_vr_get,
.set = riscv_vr_set,
},
#endif
}; };
static const struct user_regset_view riscv_user_native_view = { static const struct user_regset_view riscv_user_native_view = {
......
...@@ -445,6 +445,8 @@ typedef struct elf64_shdr { ...@@ -445,6 +445,8 @@ typedef struct elf64_shdr {
#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */ #define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */
#define NT_MIPS_FP_MODE 0x801 /* MIPS floating-point mode */ #define NT_MIPS_FP_MODE 0x801 /* MIPS floating-point mode */
#define NT_MIPS_MSA 0x802 /* MIPS SIMD registers */ #define NT_MIPS_MSA 0x802 /* MIPS SIMD registers */
#define NT_RISCV_CSR 0x900 /* RISC-V Control and Status Registers */
#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */
#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers */ #define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers */
#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and status registers */ #define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and status registers */
#define NT_LOONGARCH_LSX 0xa02 /* LoongArch Loongson SIMD Extension registers */ #define NT_LOONGARCH_LSX 0xa02 /* LoongArch Loongson SIMD Extension registers */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment