Skip to content

Commit 9300f00

Browse files
AndybnACTpalmer-dabbelt
authored andcommitted
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: 0c59922 ("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>
1 parent c35f3aa commit 9300f00

File tree

3 files changed

+90
-4
lines changed

3 files changed

+90
-4
lines changed

arch/riscv/include/uapi/asm/ptrace.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,18 @@ struct __riscv_v_ext_state {
103103
* In signal handler, datap will be set a correct user stack offset
104104
* and vector registers will be copied to the address of datap
105105
* pointer.
106-
*
107-
* In ptrace syscall, datap will be set to zero and the vector
108-
* registers will be copied to the address right after this
109-
* structure.
110106
*/
111107
};
112108

109+
struct __riscv_v_regset_state {
110+
unsigned long vstart;
111+
unsigned long vl;
112+
unsigned long vtype;
113+
unsigned long vcsr;
114+
unsigned long vlenb;
115+
char vreg[];
116+
};
117+
113118
/*
114119
* According to spec: The number of bits in a single vector register,
115120
* VLEN >= ELEN, which must be a power of 2, and must be no greater than

arch/riscv/kernel/ptrace.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ enum riscv_regset {
2525
#ifdef CONFIG_FPU
2626
REGSET_F,
2727
#endif
28+
#ifdef CONFIG_RISCV_ISA_V
29+
REGSET_V,
30+
#endif
2831
};
2932

3033
static int riscv_gpr_get(struct task_struct *target,
@@ -81,6 +84,71 @@ static int riscv_fpr_set(struct task_struct *target,
8184
}
8285
#endif
8386

87+
#ifdef CONFIG_RISCV_ISA_V
88+
static int riscv_vr_get(struct task_struct *target,
89+
const struct user_regset *regset,
90+
struct membuf to)
91+
{
92+
struct __riscv_v_ext_state *vstate = &target->thread.vstate;
93+
struct __riscv_v_regset_state ptrace_vstate;
94+
95+
if (!riscv_v_vstate_query(task_pt_regs(target)))
96+
return -EINVAL;
97+
98+
/*
99+
* Ensure the vector registers have been saved to the memory before
100+
* copying them to membuf.
101+
*/
102+
if (target == current)
103+
riscv_v_vstate_save(current, task_pt_regs(current));
104+
105+
ptrace_vstate.vstart = vstate->vstart;
106+
ptrace_vstate.vl = vstate->vl;
107+
ptrace_vstate.vtype = vstate->vtype;
108+
ptrace_vstate.vcsr = vstate->vcsr;
109+
ptrace_vstate.vlenb = vstate->vlenb;
110+
111+
/* Copy vector header from vstate. */
112+
membuf_write(&to, &ptrace_vstate, sizeof(struct __riscv_v_regset_state));
113+
114+
/* Copy all the vector registers from vstate. */
115+
return membuf_write(&to, vstate->datap, riscv_v_vsize);
116+
}
117+
118+
static int riscv_vr_set(struct task_struct *target,
119+
const struct user_regset *regset,
120+
unsigned int pos, unsigned int count,
121+
const void *kbuf, const void __user *ubuf)
122+
{
123+
int ret;
124+
struct __riscv_v_ext_state *vstate = &target->thread.vstate;
125+
struct __riscv_v_regset_state ptrace_vstate;
126+
127+
if (!riscv_v_vstate_query(task_pt_regs(target)))
128+
return -EINVAL;
129+
130+
/* Copy rest of the vstate except datap */
131+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ptrace_vstate, 0,
132+
sizeof(struct __riscv_v_regset_state));
133+
if (unlikely(ret))
134+
return ret;
135+
136+
if (vstate->vlenb != ptrace_vstate.vlenb)
137+
return -EINVAL;
138+
139+
vstate->vstart = ptrace_vstate.vstart;
140+
vstate->vl = ptrace_vstate.vl;
141+
vstate->vtype = ptrace_vstate.vtype;
142+
vstate->vcsr = ptrace_vstate.vcsr;
143+
144+
/* Copy all the vector registers. */
145+
pos = 0;
146+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vstate->datap,
147+
0, riscv_v_vsize);
148+
return ret;
149+
}
150+
#endif
151+
84152
static const struct user_regset riscv_user_regset[] = {
85153
[REGSET_X] = {
86154
.core_note_type = NT_PRSTATUS,
@@ -100,6 +168,17 @@ static const struct user_regset riscv_user_regset[] = {
100168
.set = riscv_fpr_set,
101169
},
102170
#endif
171+
#ifdef CONFIG_RISCV_ISA_V
172+
[REGSET_V] = {
173+
.core_note_type = NT_RISCV_VECTOR,
174+
.align = 16,
175+
.n = ((32 * RISCV_MAX_VLENB) +
176+
sizeof(struct __riscv_v_regset_state)) / sizeof(__u32),
177+
.size = sizeof(__u32),
178+
.regset_get = riscv_vr_get,
179+
.set = riscv_vr_set,
180+
},
181+
#endif
103182
};
104183

105184
static const struct user_regset_view riscv_user_native_view = {

include/uapi/linux/elf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,8 @@ typedef struct elf64_shdr {
443443
#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */
444444
#define NT_MIPS_FP_MODE 0x801 /* MIPS floating-point mode */
445445
#define NT_MIPS_MSA 0x802 /* MIPS SIMD registers */
446+
#define NT_RISCV_CSR 0x900 /* RISC-V Control and Status Registers */
447+
#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */
446448
#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers */
447449
#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and status registers */
448450
#define NT_LOONGARCH_LSX 0xa02 /* LoongArch Loongson SIMD Extension registers */

0 commit comments

Comments
 (0)