Skip to content

Commit b8c8a95

Browse files
Jim Wilsonpalmer-dabbelt
authored andcommitted
RISC-V: Add FP register ptrace support for gdb.
Add a variable and a macro to describe FP registers, assuming only D is supported. FP code is conditional on CONFIG_FPU. The FP regs and FCSR are copied separately to avoid copying struct padding. Tested by hand and with the gdb testsuite. Signed-off-by: Jim Wilson <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 86e581e commit b8c8a95

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ typedef unsigned long elf_greg_t;
1919
typedef struct user_regs_struct elf_gregset_t;
2020
#define ELF_NGREG (sizeof(elf_gregset_t) / sizeof(elf_greg_t))
2121

22+
/* We don't support f without d, or q. */
23+
typedef __u64 elf_fpreg_t;
2224
typedef union __riscv_fp_state elf_fpregset_t;
25+
#define ELF_NFPREG (sizeof(struct __riscv_d_ext_state) / sizeof(elf_fpreg_t))
2326

2427
#if __riscv_xlen == 64
2528
#define ELF_RISCV_R_SYM(r_info) ELF64_R_SYM(r_info)

arch/riscv/kernel/ptrace.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828

2929
enum riscv_regset {
3030
REGSET_X,
31+
#ifdef CONFIG_FPU
32+
REGSET_F,
33+
#endif
3134
};
3235

3336
static int riscv_gpr_get(struct task_struct *target,
@@ -54,6 +57,45 @@ static int riscv_gpr_set(struct task_struct *target,
5457
return ret;
5558
}
5659

60+
#ifdef CONFIG_FPU
61+
static int riscv_fpr_get(struct task_struct *target,
62+
const struct user_regset *regset,
63+
unsigned int pos, unsigned int count,
64+
void *kbuf, void __user *ubuf)
65+
{
66+
int ret;
67+
struct __riscv_d_ext_state *fstate = &target->thread.fstate;
68+
69+
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, fstate, 0,
70+
offsetof(struct __riscv_d_ext_state, fcsr));
71+
if (!ret) {
72+
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, fstate, 0,
73+
offsetof(struct __riscv_d_ext_state, fcsr) +
74+
sizeof(fstate->fcsr));
75+
}
76+
77+
return ret;
78+
}
79+
80+
static int riscv_fpr_set(struct task_struct *target,
81+
const struct user_regset *regset,
82+
unsigned int pos, unsigned int count,
83+
const void *kbuf, const void __user *ubuf)
84+
{
85+
int ret;
86+
struct __riscv_d_ext_state *fstate = &target->thread.fstate;
87+
88+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0,
89+
offsetof(struct __riscv_d_ext_state, fcsr));
90+
if (!ret) {
91+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0,
92+
offsetof(struct __riscv_d_ext_state, fcsr) +
93+
sizeof(fstate->fcsr));
94+
}
95+
96+
return ret;
97+
}
98+
#endif
5799

58100
static const struct user_regset riscv_user_regset[] = {
59101
[REGSET_X] = {
@@ -64,6 +106,16 @@ static const struct user_regset riscv_user_regset[] = {
64106
.get = &riscv_gpr_get,
65107
.set = &riscv_gpr_set,
66108
},
109+
#ifdef CONFIG_FPU
110+
[REGSET_F] = {
111+
.core_note_type = NT_PRFPREG,
112+
.n = ELF_NFPREG,
113+
.size = sizeof(elf_fpreg_t),
114+
.align = sizeof(elf_fpreg_t),
115+
.get = &riscv_fpr_get,
116+
.set = &riscv_fpr_set,
117+
},
118+
#endif
67119
};
68120

69121
static const struct user_regset_view riscv_user_native_view = {

0 commit comments

Comments
 (0)