1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <asm/ptrace.h>
19#include <asm/syscall.h>
20#include <asm/thread_info.h>
21#include <linux/ptrace.h>
22#include <linux/elf.h>
23#include <linux/regset.h>
24#include <linux/sched.h>
25#include <linux/sched/task_stack.h>
26#include <linux/tracehook.h>
27#include <trace/events/syscalls.h>
28
29enum riscv_regset {
30 REGSET_X,
31#ifdef CONFIG_FPU
32 REGSET_F,
33#endif
34};
35
36static int riscv_gpr_get(struct task_struct *target,
37 const struct user_regset *regset,
38 unsigned int pos, unsigned int count,
39 void *kbuf, void __user *ubuf)
40{
41 struct pt_regs *regs;
42
43 regs = task_pt_regs(target);
44 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
45}
46
47static int riscv_gpr_set(struct task_struct *target,
48 const struct user_regset *regset,
49 unsigned int pos, unsigned int count,
50 const void *kbuf, const void __user *ubuf)
51{
52 int ret;
53 struct pt_regs *regs;
54
55 regs = task_pt_regs(target);
56 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
57 return ret;
58}
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
99
100static const struct user_regset riscv_user_regset[] = {
101 [REGSET_X] = {
102 .core_note_type = NT_PRSTATUS,
103 .n = ELF_NGREG,
104 .size = sizeof(elf_greg_t),
105 .align = sizeof(elf_greg_t),
106 .get = &riscv_gpr_get,
107 .set = &riscv_gpr_set,
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
119};
120
121static const struct user_regset_view riscv_user_native_view = {
122 .name = "riscv",
123 .e_machine = EM_RISCV,
124 .regsets = riscv_user_regset,
125 .n = ARRAY_SIZE(riscv_user_regset),
126};
127
128const struct user_regset_view *task_user_regset_view(struct task_struct *task)
129{
130 return &riscv_user_native_view;
131}
132
133void ptrace_disable(struct task_struct *child)
134{
135 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
136}
137
138long arch_ptrace(struct task_struct *child, long request,
139 unsigned long addr, unsigned long data)
140{
141 long ret = -EIO;
142
143 switch (request) {
144 default:
145 ret = ptrace_request(child, request, addr, data);
146 break;
147 }
148
149 return ret;
150}
151
152
153
154
155
156void do_syscall_trace_enter(struct pt_regs *regs)
157{
158 if (test_thread_flag(TIF_SYSCALL_TRACE))
159 if (tracehook_report_syscall_entry(regs))
160 syscall_set_nr(current, regs, -1);
161
162#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
163 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
164 trace_sys_enter(regs, syscall_get_nr(current, regs));
165#endif
166}
167
168void do_syscall_trace_exit(struct pt_regs *regs)
169{
170 if (test_thread_flag(TIF_SYSCALL_TRACE))
171 tracehook_report_syscall_exit(regs, 0);
172
173#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
174 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
175 trace_sys_exit(regs, regs->regs[0]);
176#endif
177}
178