aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Wilson <jimw@sifive.com>2018-10-17 20:59:05 -0400
committerPalmer Dabbelt <palmer@sifive.com>2018-10-22 20:38:04 -0400
commitb8c8a9590e4fde82f8c3ee06a521763e6f21e9c8 (patch)
treec87efbb682f18144e651ecdfd79d95c71bf26087
parent86e581e310785782e2025a076dc9a3f5138e5bf3 (diff)
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 <jimw@sifive.com> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
-rw-r--r--arch/riscv/include/uapi/asm/elf.h3
-rw-r--r--arch/riscv/kernel/ptrace.c52
2 files changed, 55 insertions, 0 deletions
diff --git a/arch/riscv/include/uapi/asm/elf.h b/arch/riscv/include/uapi/asm/elf.h
index 1e0dfc36aab9..644a00ce6e2e 100644
--- a/arch/riscv/include/uapi/asm/elf.h
+++ b/arch/riscv/include/uapi/asm/elf.h
@@ -19,7 +19,10 @@ typedef unsigned long elf_greg_t;
19typedef struct user_regs_struct elf_gregset_t; 19typedef struct user_regs_struct elf_gregset_t;
20#define ELF_NGREG (sizeof(elf_gregset_t) / sizeof(elf_greg_t)) 20#define ELF_NGREG (sizeof(elf_gregset_t) / sizeof(elf_greg_t))
21 21
22/* We don't support f without d, or q. */
23typedef __u64 elf_fpreg_t;
22typedef union __riscv_fp_state elf_fpregset_t; 24typedef union __riscv_fp_state elf_fpregset_t;
25#define ELF_NFPREG (sizeof(struct __riscv_d_ext_state) / sizeof(elf_fpreg_t))
23 26
24#if __riscv_xlen == 64 27#if __riscv_xlen == 64
25#define ELF_RISCV_R_SYM(r_info) ELF64_R_SYM(r_info) 28#define ELF_RISCV_R_SYM(r_info) ELF64_R_SYM(r_info)
diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
index 9f82a7e34c64..60f1e02eed36 100644
--- a/arch/riscv/kernel/ptrace.c
+++ b/arch/riscv/kernel/ptrace.c
@@ -28,6 +28,9 @@
28 28
29enum riscv_regset { 29enum riscv_regset {
30 REGSET_X, 30 REGSET_X,
31#ifdef CONFIG_FPU
32 REGSET_F,
33#endif
31}; 34};
32 35
33static int riscv_gpr_get(struct task_struct *target, 36static int riscv_gpr_get(struct task_struct *target,
@@ -54,6 +57,45 @@ static int riscv_gpr_set(struct task_struct *target,
54 return ret; 57 return ret;
55} 58}
56 59
60#ifdef CONFIG_FPU
61static 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
80static 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
57 99
58static const struct user_regset riscv_user_regset[] = { 100static const struct user_regset riscv_user_regset[] = {
59 [REGSET_X] = { 101 [REGSET_X] = {
@@ -64,6 +106,16 @@ static const struct user_regset riscv_user_regset[] = {
64 .get = &riscv_gpr_get, 106 .get = &riscv_gpr_get,
65 .set = &riscv_gpr_set, 107 .set = &riscv_gpr_set,
66 }, 108 },
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
67}; 119};
68 120
69static const struct user_regset_view riscv_user_native_view = { 121static const struct user_regset_view riscv_user_native_view = {