150acfb2bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e2c0cdfbSPalmer Dabbelt /*
3e2c0cdfbSPalmer Dabbelt * Copyright 2010 Tilera Corporation. All Rights Reserved.
4e2c0cdfbSPalmer Dabbelt * Copyright 2015 Regents of the University of California
5e2c0cdfbSPalmer Dabbelt * Copyright 2017 SiFive
6e2c0cdfbSPalmer Dabbelt *
7e2c0cdfbSPalmer Dabbelt * Copied from arch/tile/kernel/ptrace.c
8e2c0cdfbSPalmer Dabbelt */
9e2c0cdfbSPalmer Dabbelt
100c59922cSGreentime Hu #include <asm/vector.h>
11e2c0cdfbSPalmer Dabbelt #include <asm/ptrace.h>
12e2c0cdfbSPalmer Dabbelt #include <asm/syscall.h>
13e2c0cdfbSPalmer Dabbelt #include <asm/thread_info.h>
14379eb01cSVincent Chen #include <asm/switch_to.h>
150aea8943SDavid Abdurachmanov #include <linux/audit.h>
164608c159SGuo Ren #include <linux/compat.h>
17e2c0cdfbSPalmer Dabbelt #include <linux/ptrace.h>
18e2c0cdfbSPalmer Dabbelt #include <linux/elf.h>
19e2c0cdfbSPalmer Dabbelt #include <linux/regset.h>
20e2c0cdfbSPalmer Dabbelt #include <linux/sched.h>
21e2c0cdfbSPalmer Dabbelt #include <linux/sched/task_stack.h>
22008e901bSDavid Abdurachmanov
23e2c0cdfbSPalmer Dabbelt enum riscv_regset {
24e2c0cdfbSPalmer Dabbelt REGSET_X,
25b8c8a959SJim Wilson #ifdef CONFIG_FPU
26b8c8a959SJim Wilson REGSET_F,
27b8c8a959SJim Wilson #endif
289300f004SAndy Chiu #ifdef CONFIG_RISCV_ISA_V
299300f004SAndy Chiu REGSET_V,
309300f004SAndy Chiu #endif
31e2c0cdfbSPalmer Dabbelt };
32e2c0cdfbSPalmer Dabbelt
riscv_gpr_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)33e2c0cdfbSPalmer Dabbelt static int riscv_gpr_get(struct task_struct *target,
34e2c0cdfbSPalmer Dabbelt const struct user_regset *regset,
352cb6cd49SAl Viro struct membuf to)
36e2c0cdfbSPalmer Dabbelt {
372cb6cd49SAl Viro return membuf_write(&to, task_pt_regs(target),
382cb6cd49SAl Viro sizeof(struct user_regs_struct));
39e2c0cdfbSPalmer Dabbelt }
40e2c0cdfbSPalmer Dabbelt
riscv_gpr_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)41e2c0cdfbSPalmer Dabbelt static int riscv_gpr_set(struct task_struct *target,
42e2c0cdfbSPalmer Dabbelt const struct user_regset *regset,
43e2c0cdfbSPalmer Dabbelt unsigned int pos, unsigned int count,
44e2c0cdfbSPalmer Dabbelt const void *kbuf, const void __user *ubuf)
45e2c0cdfbSPalmer Dabbelt {
46e2c0cdfbSPalmer Dabbelt struct pt_regs *regs;
47e2c0cdfbSPalmer Dabbelt
48e2c0cdfbSPalmer Dabbelt regs = task_pt_regs(target);
498da46c0fSMinghao Chi return user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
50e2c0cdfbSPalmer Dabbelt }
51e2c0cdfbSPalmer Dabbelt
52b8c8a959SJim Wilson #ifdef CONFIG_FPU
riscv_fpr_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)53b8c8a959SJim Wilson static int riscv_fpr_get(struct task_struct *target,
54b8c8a959SJim Wilson const struct user_regset *regset,
552cb6cd49SAl Viro struct membuf to)
56b8c8a959SJim Wilson {
57b8c8a959SJim Wilson struct __riscv_d_ext_state *fstate = &target->thread.fstate;
58b8c8a959SJim Wilson
59379eb01cSVincent Chen if (target == current)
60379eb01cSVincent Chen fstate_save(current, task_pt_regs(current));
61379eb01cSVincent Chen
622cb6cd49SAl Viro membuf_write(&to, fstate, offsetof(struct __riscv_d_ext_state, fcsr));
632cb6cd49SAl Viro membuf_store(&to, fstate->fcsr);
642cb6cd49SAl Viro return membuf_zero(&to, 4); // explicitly pad
65b8c8a959SJim Wilson }
66b8c8a959SJim Wilson
riscv_fpr_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)67b8c8a959SJim Wilson static int riscv_fpr_set(struct task_struct *target,
68b8c8a959SJim Wilson const struct user_regset *regset,
69b8c8a959SJim Wilson unsigned int pos, unsigned int count,
70b8c8a959SJim Wilson const void *kbuf, const void __user *ubuf)
71b8c8a959SJim Wilson {
72b8c8a959SJim Wilson int ret;
73b8c8a959SJim Wilson struct __riscv_d_ext_state *fstate = &target->thread.fstate;
74b8c8a959SJim Wilson
75b8c8a959SJim Wilson ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0,
76b8c8a959SJim Wilson offsetof(struct __riscv_d_ext_state, fcsr));
77b8c8a959SJim Wilson if (!ret) {
78b8c8a959SJim Wilson ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0,
79b8c8a959SJim Wilson offsetof(struct __riscv_d_ext_state, fcsr) +
80b8c8a959SJim Wilson sizeof(fstate->fcsr));
81b8c8a959SJim Wilson }
82b8c8a959SJim Wilson
83b8c8a959SJim Wilson return ret;
84b8c8a959SJim Wilson }
85b8c8a959SJim Wilson #endif
86e2c0cdfbSPalmer Dabbelt
879300f004SAndy Chiu #ifdef CONFIG_RISCV_ISA_V
riscv_vr_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)889300f004SAndy Chiu static int riscv_vr_get(struct task_struct *target,
899300f004SAndy Chiu const struct user_regset *regset,
909300f004SAndy Chiu struct membuf to)
919300f004SAndy Chiu {
929300f004SAndy Chiu struct __riscv_v_ext_state *vstate = &target->thread.vstate;
939300f004SAndy Chiu struct __riscv_v_regset_state ptrace_vstate;
949300f004SAndy Chiu
959300f004SAndy Chiu if (!riscv_v_vstate_query(task_pt_regs(target)))
969300f004SAndy Chiu return -EINVAL;
979300f004SAndy Chiu
989300f004SAndy Chiu /*
999300f004SAndy Chiu * Ensure the vector registers have been saved to the memory before
1009300f004SAndy Chiu * copying them to membuf.
1019300f004SAndy Chiu */
1027df56cbcSAndy Chiu if (target == current) {
1037df56cbcSAndy Chiu get_cpu_vector_context();
104d6c78f1cSAndy Chiu riscv_v_vstate_save(¤t->thread.vstate, task_pt_regs(current));
1057df56cbcSAndy Chiu put_cpu_vector_context();
1067df56cbcSAndy Chiu }
1079300f004SAndy Chiu
1089300f004SAndy Chiu ptrace_vstate.vstart = vstate->vstart;
1099300f004SAndy Chiu ptrace_vstate.vl = vstate->vl;
1109300f004SAndy Chiu ptrace_vstate.vtype = vstate->vtype;
1119300f004SAndy Chiu ptrace_vstate.vcsr = vstate->vcsr;
1129300f004SAndy Chiu ptrace_vstate.vlenb = vstate->vlenb;
1139300f004SAndy Chiu
1149300f004SAndy Chiu /* Copy vector header from vstate. */
1159300f004SAndy Chiu membuf_write(&to, &ptrace_vstate, sizeof(struct __riscv_v_regset_state));
1169300f004SAndy Chiu
1179300f004SAndy Chiu /* Copy all the vector registers from vstate. */
1189300f004SAndy Chiu return membuf_write(&to, vstate->datap, riscv_v_vsize);
1199300f004SAndy Chiu }
1209300f004SAndy Chiu
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)1219300f004SAndy Chiu static int riscv_vr_set(struct task_struct *target,
1229300f004SAndy Chiu const struct user_regset *regset,
1239300f004SAndy Chiu unsigned int pos, unsigned int count,
1249300f004SAndy Chiu const void *kbuf, const void __user *ubuf)
1259300f004SAndy Chiu {
1269300f004SAndy Chiu int ret;
1279300f004SAndy Chiu struct __riscv_v_ext_state *vstate = &target->thread.vstate;
1289300f004SAndy Chiu struct __riscv_v_regset_state ptrace_vstate;
1299300f004SAndy Chiu
1309300f004SAndy Chiu if (!riscv_v_vstate_query(task_pt_regs(target)))
1319300f004SAndy Chiu return -EINVAL;
1329300f004SAndy Chiu
1339300f004SAndy Chiu /* Copy rest of the vstate except datap */
1349300f004SAndy Chiu ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ptrace_vstate, 0,
1359300f004SAndy Chiu sizeof(struct __riscv_v_regset_state));
1369300f004SAndy Chiu if (unlikely(ret))
1379300f004SAndy Chiu return ret;
1389300f004SAndy Chiu
1399300f004SAndy Chiu if (vstate->vlenb != ptrace_vstate.vlenb)
1409300f004SAndy Chiu return -EINVAL;
1419300f004SAndy Chiu
1429300f004SAndy Chiu vstate->vstart = ptrace_vstate.vstart;
1439300f004SAndy Chiu vstate->vl = ptrace_vstate.vl;
1449300f004SAndy Chiu vstate->vtype = ptrace_vstate.vtype;
1459300f004SAndy Chiu vstate->vcsr = ptrace_vstate.vcsr;
1469300f004SAndy Chiu
1479300f004SAndy Chiu /* Copy all the vector registers. */
1489300f004SAndy Chiu pos = 0;
1499300f004SAndy Chiu ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vstate->datap,
1509300f004SAndy Chiu 0, riscv_v_vsize);
1519300f004SAndy Chiu return ret;
1529300f004SAndy Chiu }
1539300f004SAndy Chiu #endif
1549300f004SAndy Chiu
155e2c0cdfbSPalmer Dabbelt static const struct user_regset riscv_user_regset[] = {
156e2c0cdfbSPalmer Dabbelt [REGSET_X] = {
157e2c0cdfbSPalmer Dabbelt .core_note_type = NT_PRSTATUS,
158e2c0cdfbSPalmer Dabbelt .n = ELF_NGREG,
159e2c0cdfbSPalmer Dabbelt .size = sizeof(elf_greg_t),
160e2c0cdfbSPalmer Dabbelt .align = sizeof(elf_greg_t),
1612cb6cd49SAl Viro .regset_get = riscv_gpr_get,
1622cb6cd49SAl Viro .set = riscv_gpr_set,
163e2c0cdfbSPalmer Dabbelt },
164b8c8a959SJim Wilson #ifdef CONFIG_FPU
165b8c8a959SJim Wilson [REGSET_F] = {
166b8c8a959SJim Wilson .core_note_type = NT_PRFPREG,
167b8c8a959SJim Wilson .n = ELF_NFPREG,
168b8c8a959SJim Wilson .size = sizeof(elf_fpreg_t),
169b8c8a959SJim Wilson .align = sizeof(elf_fpreg_t),
1702cb6cd49SAl Viro .regset_get = riscv_fpr_get,
1712cb6cd49SAl Viro .set = riscv_fpr_set,
172b8c8a959SJim Wilson },
173b8c8a959SJim Wilson #endif
1749300f004SAndy Chiu #ifdef CONFIG_RISCV_ISA_V
1759300f004SAndy Chiu [REGSET_V] = {
1769300f004SAndy Chiu .core_note_type = NT_RISCV_VECTOR,
1779300f004SAndy Chiu .align = 16,
1789300f004SAndy Chiu .n = ((32 * RISCV_MAX_VLENB) +
1799300f004SAndy Chiu sizeof(struct __riscv_v_regset_state)) / sizeof(__u32),
1809300f004SAndy Chiu .size = sizeof(__u32),
1819300f004SAndy Chiu .regset_get = riscv_vr_get,
1829300f004SAndy Chiu .set = riscv_vr_set,
1839300f004SAndy Chiu },
1849300f004SAndy Chiu #endif
185e2c0cdfbSPalmer Dabbelt };
186e2c0cdfbSPalmer Dabbelt
187e2c0cdfbSPalmer Dabbelt static const struct user_regset_view riscv_user_native_view = {
188e2c0cdfbSPalmer Dabbelt .name = "riscv",
189e2c0cdfbSPalmer Dabbelt .e_machine = EM_RISCV,
190e2c0cdfbSPalmer Dabbelt .regsets = riscv_user_regset,
191e2c0cdfbSPalmer Dabbelt .n = ARRAY_SIZE(riscv_user_regset),
192e2c0cdfbSPalmer Dabbelt };
193e2c0cdfbSPalmer Dabbelt
194dcdc7a53SPatrick Stählin struct pt_regs_offset {
195dcdc7a53SPatrick Stählin const char *name;
196dcdc7a53SPatrick Stählin int offset;
197dcdc7a53SPatrick Stählin };
198dcdc7a53SPatrick Stählin
199dcdc7a53SPatrick Stählin #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
200dcdc7a53SPatrick Stählin #define REG_OFFSET_END {.name = NULL, .offset = 0}
201dcdc7a53SPatrick Stählin
202dcdc7a53SPatrick Stählin static const struct pt_regs_offset regoffset_table[] = {
203dcdc7a53SPatrick Stählin REG_OFFSET_NAME(epc),
204dcdc7a53SPatrick Stählin REG_OFFSET_NAME(ra),
205dcdc7a53SPatrick Stählin REG_OFFSET_NAME(sp),
206dcdc7a53SPatrick Stählin REG_OFFSET_NAME(gp),
207dcdc7a53SPatrick Stählin REG_OFFSET_NAME(tp),
208dcdc7a53SPatrick Stählin REG_OFFSET_NAME(t0),
209dcdc7a53SPatrick Stählin REG_OFFSET_NAME(t1),
210dcdc7a53SPatrick Stählin REG_OFFSET_NAME(t2),
211dcdc7a53SPatrick Stählin REG_OFFSET_NAME(s0),
212dcdc7a53SPatrick Stählin REG_OFFSET_NAME(s1),
213dcdc7a53SPatrick Stählin REG_OFFSET_NAME(a0),
214dcdc7a53SPatrick Stählin REG_OFFSET_NAME(a1),
215dcdc7a53SPatrick Stählin REG_OFFSET_NAME(a2),
216dcdc7a53SPatrick Stählin REG_OFFSET_NAME(a3),
217dcdc7a53SPatrick Stählin REG_OFFSET_NAME(a4),
218dcdc7a53SPatrick Stählin REG_OFFSET_NAME(a5),
219dcdc7a53SPatrick Stählin REG_OFFSET_NAME(a6),
220dcdc7a53SPatrick Stählin REG_OFFSET_NAME(a7),
221dcdc7a53SPatrick Stählin REG_OFFSET_NAME(s2),
222dcdc7a53SPatrick Stählin REG_OFFSET_NAME(s3),
223dcdc7a53SPatrick Stählin REG_OFFSET_NAME(s4),
224dcdc7a53SPatrick Stählin REG_OFFSET_NAME(s5),
225dcdc7a53SPatrick Stählin REG_OFFSET_NAME(s6),
226dcdc7a53SPatrick Stählin REG_OFFSET_NAME(s7),
227dcdc7a53SPatrick Stählin REG_OFFSET_NAME(s8),
228dcdc7a53SPatrick Stählin REG_OFFSET_NAME(s9),
229dcdc7a53SPatrick Stählin REG_OFFSET_NAME(s10),
230dcdc7a53SPatrick Stählin REG_OFFSET_NAME(s11),
231dcdc7a53SPatrick Stählin REG_OFFSET_NAME(t3),
232dcdc7a53SPatrick Stählin REG_OFFSET_NAME(t4),
233dcdc7a53SPatrick Stählin REG_OFFSET_NAME(t5),
234dcdc7a53SPatrick Stählin REG_OFFSET_NAME(t6),
235dcdc7a53SPatrick Stählin REG_OFFSET_NAME(status),
236dcdc7a53SPatrick Stählin REG_OFFSET_NAME(badaddr),
237dcdc7a53SPatrick Stählin REG_OFFSET_NAME(cause),
238dcdc7a53SPatrick Stählin REG_OFFSET_NAME(orig_a0),
239dcdc7a53SPatrick Stählin REG_OFFSET_END,
240dcdc7a53SPatrick Stählin };
241dcdc7a53SPatrick Stählin
242dcdc7a53SPatrick Stählin /**
243dcdc7a53SPatrick Stählin * regs_query_register_offset() - query register offset from its name
244dcdc7a53SPatrick Stählin * @name: the name of a register
245dcdc7a53SPatrick Stählin *
246dcdc7a53SPatrick Stählin * regs_query_register_offset() returns the offset of a register in struct
247dcdc7a53SPatrick Stählin * pt_regs from its name. If the name is invalid, this returns -EINVAL;
248dcdc7a53SPatrick Stählin */
regs_query_register_offset(const char * name)249dcdc7a53SPatrick Stählin int regs_query_register_offset(const char *name)
250dcdc7a53SPatrick Stählin {
251dcdc7a53SPatrick Stählin const struct pt_regs_offset *roff;
252dcdc7a53SPatrick Stählin
253dcdc7a53SPatrick Stählin for (roff = regoffset_table; roff->name != NULL; roff++)
254dcdc7a53SPatrick Stählin if (!strcmp(roff->name, name))
255dcdc7a53SPatrick Stählin return roff->offset;
256dcdc7a53SPatrick Stählin return -EINVAL;
257dcdc7a53SPatrick Stählin }
258dcdc7a53SPatrick Stählin
259dcdc7a53SPatrick Stählin /**
260dcdc7a53SPatrick Stählin * regs_within_kernel_stack() - check the address in the stack
261dcdc7a53SPatrick Stählin * @regs: pt_regs which contains kernel stack pointer.
262dcdc7a53SPatrick Stählin * @addr: address which is checked.
263dcdc7a53SPatrick Stählin *
264dcdc7a53SPatrick Stählin * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
265dcdc7a53SPatrick Stählin * If @addr is within the kernel stack, it returns true. If not, returns false.
266dcdc7a53SPatrick Stählin */
regs_within_kernel_stack(struct pt_regs * regs,unsigned long addr)267dcdc7a53SPatrick Stählin static bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
268dcdc7a53SPatrick Stählin {
269dcdc7a53SPatrick Stählin return (addr & ~(THREAD_SIZE - 1)) ==
270dcdc7a53SPatrick Stählin (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1));
271dcdc7a53SPatrick Stählin }
272dcdc7a53SPatrick Stählin
273dcdc7a53SPatrick Stählin /**
274dcdc7a53SPatrick Stählin * regs_get_kernel_stack_nth() - get Nth entry of the stack
275dcdc7a53SPatrick Stählin * @regs: pt_regs which contains kernel stack pointer.
276dcdc7a53SPatrick Stählin * @n: stack entry number.
277dcdc7a53SPatrick Stählin *
278dcdc7a53SPatrick Stählin * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
279dcdc7a53SPatrick Stählin * is specified by @regs. If the @n th entry is NOT in the kernel stack,
280dcdc7a53SPatrick Stählin * this returns 0.
281dcdc7a53SPatrick Stählin */
regs_get_kernel_stack_nth(struct pt_regs * regs,unsigned int n)282dcdc7a53SPatrick Stählin unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
283dcdc7a53SPatrick Stählin {
284dcdc7a53SPatrick Stählin unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
285dcdc7a53SPatrick Stählin
286dcdc7a53SPatrick Stählin addr += n;
287dcdc7a53SPatrick Stählin if (regs_within_kernel_stack(regs, (unsigned long)addr))
288dcdc7a53SPatrick Stählin return *addr;
289dcdc7a53SPatrick Stählin else
290dcdc7a53SPatrick Stählin return 0;
291dcdc7a53SPatrick Stählin }
292dcdc7a53SPatrick Stählin
ptrace_disable(struct task_struct * child)293e2c0cdfbSPalmer Dabbelt void ptrace_disable(struct task_struct *child)
294e2c0cdfbSPalmer Dabbelt {
295e2c0cdfbSPalmer Dabbelt }
296e2c0cdfbSPalmer Dabbelt
arch_ptrace(struct task_struct * child,long request,unsigned long addr,unsigned long data)297e2c0cdfbSPalmer Dabbelt long arch_ptrace(struct task_struct *child, long request,
298e2c0cdfbSPalmer Dabbelt unsigned long addr, unsigned long data)
299e2c0cdfbSPalmer Dabbelt {
300e2c0cdfbSPalmer Dabbelt long ret = -EIO;
301e2c0cdfbSPalmer Dabbelt
302e2c0cdfbSPalmer Dabbelt switch (request) {
303e2c0cdfbSPalmer Dabbelt default:
304e2c0cdfbSPalmer Dabbelt ret = ptrace_request(child, request, addr, data);
305e2c0cdfbSPalmer Dabbelt break;
306e2c0cdfbSPalmer Dabbelt }
307e2c0cdfbSPalmer Dabbelt
308e2c0cdfbSPalmer Dabbelt return ret;
309e2c0cdfbSPalmer Dabbelt }
310e2c0cdfbSPalmer Dabbelt
3114608c159SGuo Ren #ifdef CONFIG_COMPAT
compat_riscv_gpr_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)3124608c159SGuo Ren static int compat_riscv_gpr_get(struct task_struct *target,
3134608c159SGuo Ren const struct user_regset *regset,
3144608c159SGuo Ren struct membuf to)
3154608c159SGuo Ren {
3164608c159SGuo Ren struct compat_user_regs_struct cregs;
3174608c159SGuo Ren
3184608c159SGuo Ren regs_to_cregs(&cregs, task_pt_regs(target));
3194608c159SGuo Ren
3204608c159SGuo Ren return membuf_write(&to, &cregs,
3214608c159SGuo Ren sizeof(struct compat_user_regs_struct));
3224608c159SGuo Ren }
3234608c159SGuo Ren
compat_riscv_gpr_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)3244608c159SGuo Ren static int compat_riscv_gpr_set(struct task_struct *target,
3254608c159SGuo Ren const struct user_regset *regset,
3264608c159SGuo Ren unsigned int pos, unsigned int count,
3274608c159SGuo Ren const void *kbuf, const void __user *ubuf)
3284608c159SGuo Ren {
3294608c159SGuo Ren int ret;
3304608c159SGuo Ren struct compat_user_regs_struct cregs;
3314608c159SGuo Ren
3324608c159SGuo Ren ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &cregs, 0, -1);
3334608c159SGuo Ren
3344608c159SGuo Ren cregs_to_regs(&cregs, task_pt_regs(target));
3354608c159SGuo Ren
3364608c159SGuo Ren return ret;
3374608c159SGuo Ren }
3384608c159SGuo Ren
3394608c159SGuo Ren static const struct user_regset compat_riscv_user_regset[] = {
3404608c159SGuo Ren [REGSET_X] = {
3414608c159SGuo Ren .core_note_type = NT_PRSTATUS,
3424608c159SGuo Ren .n = ELF_NGREG,
3434608c159SGuo Ren .size = sizeof(compat_elf_greg_t),
3444608c159SGuo Ren .align = sizeof(compat_elf_greg_t),
3454608c159SGuo Ren .regset_get = compat_riscv_gpr_get,
3464608c159SGuo Ren .set = compat_riscv_gpr_set,
3474608c159SGuo Ren },
3484608c159SGuo Ren #ifdef CONFIG_FPU
3494608c159SGuo Ren [REGSET_F] = {
3504608c159SGuo Ren .core_note_type = NT_PRFPREG,
3514608c159SGuo Ren .n = ELF_NFPREG,
3524608c159SGuo Ren .size = sizeof(elf_fpreg_t),
3534608c159SGuo Ren .align = sizeof(elf_fpreg_t),
3544608c159SGuo Ren .regset_get = riscv_fpr_get,
3554608c159SGuo Ren .set = riscv_fpr_set,
3564608c159SGuo Ren },
3574608c159SGuo Ren #endif
3584608c159SGuo Ren };
3594608c159SGuo Ren
3604608c159SGuo Ren static const struct user_regset_view compat_riscv_user_native_view = {
3614608c159SGuo Ren .name = "riscv",
3624608c159SGuo Ren .e_machine = EM_RISCV,
3634608c159SGuo Ren .regsets = compat_riscv_user_regset,
3644608c159SGuo Ren .n = ARRAY_SIZE(compat_riscv_user_regset),
3654608c159SGuo Ren };
3664608c159SGuo Ren
compat_arch_ptrace(struct task_struct * child,compat_long_t request,compat_ulong_t caddr,compat_ulong_t cdata)3674608c159SGuo Ren long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
3684608c159SGuo Ren compat_ulong_t caddr, compat_ulong_t cdata)
3694608c159SGuo Ren {
3704608c159SGuo Ren long ret = -EIO;
3714608c159SGuo Ren
3724608c159SGuo Ren switch (request) {
3734608c159SGuo Ren default:
3744608c159SGuo Ren ret = compat_ptrace_request(child, request, caddr, cdata);
3754608c159SGuo Ren break;
3764608c159SGuo Ren }
3774608c159SGuo Ren
3784608c159SGuo Ren return ret;
3794608c159SGuo Ren }
380*5917ea17SLeonardo Bras #else
381*5917ea17SLeonardo Bras static const struct user_regset_view compat_riscv_user_native_view = {};
3824608c159SGuo Ren #endif /* CONFIG_COMPAT */
3834608c159SGuo Ren
task_user_regset_view(struct task_struct * task)3844608c159SGuo Ren const struct user_regset_view *task_user_regset_view(struct task_struct *task)
3854608c159SGuo Ren {
386*5917ea17SLeonardo Bras if (is_compat_thread(&task->thread_info))
3874608c159SGuo Ren return &compat_riscv_user_native_view;
3884608c159SGuo Ren else
3894608c159SGuo Ren return &riscv_user_native_view;
3904608c159SGuo Ren }
391