xref: /openbmc/linux/arch/riscv/kernel/ptrace.c (revision b38269ec)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2010 Tilera Corporation. All Rights Reserved.
4  * Copyright 2015 Regents of the University of California
5  * Copyright 2017 SiFive
6  *
7  * Copied from arch/tile/kernel/ptrace.c
8  */
9 
10 #include <asm/ptrace.h>
11 #include <asm/syscall.h>
12 #include <asm/thread_info.h>
13 #include <asm/switch_to.h>
14 #include <linux/audit.h>
15 #include <linux/ptrace.h>
16 #include <linux/elf.h>
17 #include <linux/regset.h>
18 #include <linux/sched.h>
19 #include <linux/sched/task_stack.h>
20 #include <linux/tracehook.h>
21 
22 #define CREATE_TRACE_POINTS
23 #include <trace/events/syscalls.h>
24 
25 enum riscv_regset {
26 	REGSET_X,
27 #ifdef CONFIG_FPU
28 	REGSET_F,
29 #endif
30 };
31 
32 static int riscv_gpr_get(struct task_struct *target,
33 			 const struct user_regset *regset,
34 			 struct membuf to)
35 {
36 	return membuf_write(&to, task_pt_regs(target),
37 			    sizeof(struct user_regs_struct));
38 }
39 
40 static int riscv_gpr_set(struct task_struct *target,
41 			 const struct user_regset *regset,
42 			 unsigned int pos, unsigned int count,
43 			 const void *kbuf, const void __user *ubuf)
44 {
45 	int ret;
46 	struct pt_regs *regs;
47 
48 	regs = task_pt_regs(target);
49 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
50 	return ret;
51 }
52 
53 #ifdef CONFIG_FPU
54 static int riscv_fpr_get(struct task_struct *target,
55 			 const struct user_regset *regset,
56 			 struct membuf to)
57 {
58 	struct __riscv_d_ext_state *fstate = &target->thread.fstate;
59 
60 	if (target == current)
61 		fstate_save(current, task_pt_regs(current));
62 
63 	membuf_write(&to, fstate, offsetof(struct __riscv_d_ext_state, fcsr));
64 	membuf_store(&to, fstate->fcsr);
65 	return membuf_zero(&to, 4);	// explicitly pad
66 }
67 
68 static int riscv_fpr_set(struct task_struct *target,
69 			 const struct user_regset *regset,
70 			 unsigned int pos, unsigned int count,
71 			 const void *kbuf, const void __user *ubuf)
72 {
73 	int ret;
74 	struct __riscv_d_ext_state *fstate = &target->thread.fstate;
75 
76 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0,
77 				 offsetof(struct __riscv_d_ext_state, fcsr));
78 	if (!ret) {
79 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0,
80 					 offsetof(struct __riscv_d_ext_state, fcsr) +
81 					 sizeof(fstate->fcsr));
82 	}
83 
84 	return ret;
85 }
86 #endif
87 
88 static const struct user_regset riscv_user_regset[] = {
89 	[REGSET_X] = {
90 		.core_note_type = NT_PRSTATUS,
91 		.n = ELF_NGREG,
92 		.size = sizeof(elf_greg_t),
93 		.align = sizeof(elf_greg_t),
94 		.regset_get = riscv_gpr_get,
95 		.set = riscv_gpr_set,
96 	},
97 #ifdef CONFIG_FPU
98 	[REGSET_F] = {
99 		.core_note_type = NT_PRFPREG,
100 		.n = ELF_NFPREG,
101 		.size = sizeof(elf_fpreg_t),
102 		.align = sizeof(elf_fpreg_t),
103 		.regset_get = riscv_fpr_get,
104 		.set = riscv_fpr_set,
105 	},
106 #endif
107 };
108 
109 static const struct user_regset_view riscv_user_native_view = {
110 	.name = "riscv",
111 	.e_machine = EM_RISCV,
112 	.regsets = riscv_user_regset,
113 	.n = ARRAY_SIZE(riscv_user_regset),
114 };
115 
116 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
117 {
118 	return &riscv_user_native_view;
119 }
120 
121 struct pt_regs_offset {
122 	const char *name;
123 	int offset;
124 };
125 
126 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
127 #define REG_OFFSET_END {.name = NULL, .offset = 0}
128 
129 static const struct pt_regs_offset regoffset_table[] = {
130 	REG_OFFSET_NAME(epc),
131 	REG_OFFSET_NAME(ra),
132 	REG_OFFSET_NAME(sp),
133 	REG_OFFSET_NAME(gp),
134 	REG_OFFSET_NAME(tp),
135 	REG_OFFSET_NAME(t0),
136 	REG_OFFSET_NAME(t1),
137 	REG_OFFSET_NAME(t2),
138 	REG_OFFSET_NAME(s0),
139 	REG_OFFSET_NAME(s1),
140 	REG_OFFSET_NAME(a0),
141 	REG_OFFSET_NAME(a1),
142 	REG_OFFSET_NAME(a2),
143 	REG_OFFSET_NAME(a3),
144 	REG_OFFSET_NAME(a4),
145 	REG_OFFSET_NAME(a5),
146 	REG_OFFSET_NAME(a6),
147 	REG_OFFSET_NAME(a7),
148 	REG_OFFSET_NAME(s2),
149 	REG_OFFSET_NAME(s3),
150 	REG_OFFSET_NAME(s4),
151 	REG_OFFSET_NAME(s5),
152 	REG_OFFSET_NAME(s6),
153 	REG_OFFSET_NAME(s7),
154 	REG_OFFSET_NAME(s8),
155 	REG_OFFSET_NAME(s9),
156 	REG_OFFSET_NAME(s10),
157 	REG_OFFSET_NAME(s11),
158 	REG_OFFSET_NAME(t3),
159 	REG_OFFSET_NAME(t4),
160 	REG_OFFSET_NAME(t5),
161 	REG_OFFSET_NAME(t6),
162 	REG_OFFSET_NAME(status),
163 	REG_OFFSET_NAME(badaddr),
164 	REG_OFFSET_NAME(cause),
165 	REG_OFFSET_NAME(orig_a0),
166 	REG_OFFSET_END,
167 };
168 
169 /**
170  * regs_query_register_offset() - query register offset from its name
171  * @name:	the name of a register
172  *
173  * regs_query_register_offset() returns the offset of a register in struct
174  * pt_regs from its name. If the name is invalid, this returns -EINVAL;
175  */
176 int regs_query_register_offset(const char *name)
177 {
178 	const struct pt_regs_offset *roff;
179 
180 	for (roff = regoffset_table; roff->name != NULL; roff++)
181 		if (!strcmp(roff->name, name))
182 			return roff->offset;
183 	return -EINVAL;
184 }
185 
186 /**
187  * regs_within_kernel_stack() - check the address in the stack
188  * @regs:      pt_regs which contains kernel stack pointer.
189  * @addr:      address which is checked.
190  *
191  * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
192  * If @addr is within the kernel stack, it returns true. If not, returns false.
193  */
194 static bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
195 {
196 	return (addr & ~(THREAD_SIZE - 1))  ==
197 		(kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1));
198 }
199 
200 /**
201  * regs_get_kernel_stack_nth() - get Nth entry of the stack
202  * @regs:	pt_regs which contains kernel stack pointer.
203  * @n:		stack entry number.
204  *
205  * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
206  * is specified by @regs. If the @n th entry is NOT in the kernel stack,
207  * this returns 0.
208  */
209 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
210 {
211 	unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
212 
213 	addr += n;
214 	if (regs_within_kernel_stack(regs, (unsigned long)addr))
215 		return *addr;
216 	else
217 		return 0;
218 }
219 
220 void ptrace_disable(struct task_struct *child)
221 {
222 	clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
223 }
224 
225 long arch_ptrace(struct task_struct *child, long request,
226 		 unsigned long addr, unsigned long data)
227 {
228 	long ret = -EIO;
229 
230 	switch (request) {
231 	default:
232 		ret = ptrace_request(child, request, addr, data);
233 		break;
234 	}
235 
236 	return ret;
237 }
238 
239 /*
240  * Allows PTRACE_SYSCALL to work.  These are called from entry.S in
241  * {handle,ret_from}_syscall.
242  */
243 __visible int do_syscall_trace_enter(struct pt_regs *regs)
244 {
245 	if (test_thread_flag(TIF_SYSCALL_TRACE))
246 		if (tracehook_report_syscall_entry(regs))
247 			return -1;
248 
249 	/*
250 	 * Do the secure computing after ptrace; failures should be fast.
251 	 * If this fails we might have return value in a0 from seccomp
252 	 * (via SECCOMP_RET_ERRNO/TRACE).
253 	 */
254 	if (secure_computing() == -1)
255 		return -1;
256 
257 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
258 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
259 		trace_sys_enter(regs, syscall_get_nr(current, regs));
260 #endif
261 
262 	audit_syscall_entry(regs->a7, regs->a0, regs->a1, regs->a2, regs->a3);
263 	return 0;
264 }
265 
266 __visible void do_syscall_trace_exit(struct pt_regs *regs)
267 {
268 	audit_syscall_exit(regs);
269 
270 	if (test_thread_flag(TIF_SYSCALL_TRACE))
271 		tracehook_report_syscall_exit(regs, 0);
272 
273 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
274 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
275 		trace_sys_exit(regs, regs_return_value(regs));
276 #endif
277 }
278