mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 06:33:34 +00:00
RISC-V: Add ptrace support for vectors
This patch add back the ptrace support with the following fix:
- Define NT_RISCV_CSR and re-number NT_RISCV_VECTOR to prevent
conflicting with gdb's NT_RISCV_CSR.
- Use struct __riscv_v_regset_state to handle ptrace requests
Since gdb does not directly include the note description header in
Linux and has already defined NT_RISCV_CSR as 0x900, we decide to
sync with gdb and renumber NT_RISCV_VECTOR to solve and prevent future
conflicts.
Fixes: 0c59922c76
("riscv: Add ptrace vector support")
Signed-off-by: Andy Chiu <andy.chiu@sifive.com>
Link: https://lore.kernel.org/r/20230825050248.32681-1-andy.chiu@sifive.com
[Palmer: Drop the unused "size" variable in riscv_vr_set().]
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
parent
c35f3aa345
commit
9300f00439
@ -103,13 +103,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 {
|
|||||||
#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,
|
|||||||
}
|
}
|
||||||
#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[] = {
|
|||||||
.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 = {
|
||||||
|
@ -443,6 +443,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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user