xref: /openbmc/linux/arch/xtensa/kernel/ptrace.c (revision d003c346bf75f01d240c80000baf2fbf28e53782)
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2001 - 2007  Tensilica Inc.
7  *
8  * Joe Taylor	<joe@tensilica.com, joetylr@yahoo.com>
9  * Chris Zankel <chris@zankel.net>
10  * Scott Foehner<sfoehner@yahoo.com>,
11  * Kevin Chea
12  * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
13  */
14 
15 #include <linux/errno.h>
16 #include <linux/hw_breakpoint.h>
17 #include <linux/kernel.h>
18 #include <linux/mm.h>
19 #include <linux/perf_event.h>
20 #include <linux/ptrace.h>
21 #include <linux/sched.h>
22 #include <linux/sched/task_stack.h>
23 #include <linux/security.h>
24 #include <linux/signal.h>
25 #include <linux/smp.h>
26 #include <linux/tracehook.h>
27 #include <linux/uaccess.h>
28 
29 #include <asm/coprocessor.h>
30 #include <asm/elf.h>
31 #include <asm/page.h>
32 #include <asm/pgtable.h>
33 #include <asm/ptrace.h>
34 
35 
36 void user_enable_single_step(struct task_struct *child)
37 {
38 	child->ptrace |= PT_SINGLESTEP;
39 }
40 
41 void user_disable_single_step(struct task_struct *child)
42 {
43 	child->ptrace &= ~PT_SINGLESTEP;
44 }
45 
46 /*
47  * Called by kernel/ptrace.c when detaching to disable single stepping.
48  */
49 
50 void ptrace_disable(struct task_struct *child)
51 {
52 	/* Nothing to do.. */
53 }
54 
55 static int ptrace_getregs(struct task_struct *child, void __user *uregs)
56 {
57 	struct pt_regs *regs = task_pt_regs(child);
58 	xtensa_gregset_t __user *gregset = uregs;
59 	unsigned long wb = regs->windowbase;
60 	int i;
61 
62 	if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t)))
63 		return -EIO;
64 
65 	__put_user(regs->pc, &gregset->pc);
66 	__put_user(regs->ps & ~(1 << PS_EXCM_BIT), &gregset->ps);
67 	__put_user(regs->lbeg, &gregset->lbeg);
68 	__put_user(regs->lend, &gregset->lend);
69 	__put_user(regs->lcount, &gregset->lcount);
70 	__put_user(regs->windowstart, &gregset->windowstart);
71 	__put_user(regs->windowbase, &gregset->windowbase);
72 	__put_user(regs->threadptr, &gregset->threadptr);
73 
74 	for (i = 0; i < XCHAL_NUM_AREGS; i++)
75 		__put_user(regs->areg[i],
76 			   gregset->a + ((wb * 4 + i) % XCHAL_NUM_AREGS));
77 
78 	return 0;
79 }
80 
81 static int ptrace_setregs(struct task_struct *child, void __user *uregs)
82 {
83 	struct pt_regs *regs = task_pt_regs(child);
84 	xtensa_gregset_t *gregset = uregs;
85 	const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK;
86 	unsigned long ps;
87 	unsigned long wb, ws;
88 
89 	if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t)))
90 		return -EIO;
91 
92 	__get_user(regs->pc, &gregset->pc);
93 	__get_user(ps, &gregset->ps);
94 	__get_user(regs->lbeg, &gregset->lbeg);
95 	__get_user(regs->lend, &gregset->lend);
96 	__get_user(regs->lcount, &gregset->lcount);
97 	__get_user(ws, &gregset->windowstart);
98 	__get_user(wb, &gregset->windowbase);
99 	__get_user(regs->threadptr, &gregset->threadptr);
100 
101 	regs->ps = (regs->ps & ~ps_mask) | (ps & ps_mask) | (1 << PS_EXCM_BIT);
102 
103 	if (wb >= XCHAL_NUM_AREGS / 4)
104 		return -EFAULT;
105 
106 	if (wb != regs->windowbase || ws != regs->windowstart) {
107 		unsigned long rotws, wmask;
108 
109 		rotws = (((ws | (ws << WSBITS)) >> wb) &
110 			 ((1 << WSBITS) - 1)) & ~1;
111 		wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) |
112 			(rotws & 0xF) | 1;
113 		regs->windowbase = wb;
114 		regs->windowstart = ws;
115 		regs->wmask = wmask;
116 	}
117 
118 	if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4,
119 					gregset->a, wb * 16))
120 		return -EFAULT;
121 
122 	if (__copy_from_user(regs->areg, gregset->a + wb * 4,
123 			     (WSBITS - wb) * 16))
124 		return -EFAULT;
125 
126 	return 0;
127 }
128 
129 
130 #if XTENSA_HAVE_COPROCESSORS
131 #define CP_OFFSETS(cp) \
132 	{ \
133 		.elf_xtregs_offset = offsetof(elf_xtregs_t, cp), \
134 		.ti_offset = offsetof(struct thread_info, xtregs_cp.cp), \
135 		.sz = sizeof(xtregs_ ## cp ## _t), \
136 	}
137 
138 static const struct {
139 	size_t elf_xtregs_offset;
140 	size_t ti_offset;
141 	size_t sz;
142 } cp_offsets[] = {
143 	CP_OFFSETS(cp0),
144 	CP_OFFSETS(cp1),
145 	CP_OFFSETS(cp2),
146 	CP_OFFSETS(cp3),
147 	CP_OFFSETS(cp4),
148 	CP_OFFSETS(cp5),
149 	CP_OFFSETS(cp6),
150 	CP_OFFSETS(cp7),
151 };
152 #endif
153 
154 static int ptrace_getxregs(struct task_struct *child, void __user *uregs)
155 {
156 	struct pt_regs *regs = task_pt_regs(child);
157 	struct thread_info *ti = task_thread_info(child);
158 	elf_xtregs_t __user *xtregs = uregs;
159 	int ret = 0;
160 	int i __maybe_unused;
161 
162 	if (!access_ok(VERIFY_WRITE, uregs, sizeof(elf_xtregs_t)))
163 		return -EIO;
164 
165 #if XTENSA_HAVE_COPROCESSORS
166 	/* Flush all coprocessor registers to memory. */
167 	coprocessor_flush_all(ti);
168 
169 	for (i = 0; i < ARRAY_SIZE(cp_offsets); ++i)
170 		ret |= __copy_to_user((char __user *)xtregs +
171 				      cp_offsets[i].elf_xtregs_offset,
172 				      (const char *)ti +
173 				      cp_offsets[i].ti_offset,
174 				      cp_offsets[i].sz);
175 #endif
176 	ret |= __copy_to_user(&xtregs->opt, &regs->xtregs_opt,
177 			      sizeof(xtregs->opt));
178 	ret |= __copy_to_user(&xtregs->user,&ti->xtregs_user,
179 			      sizeof(xtregs->user));
180 
181 	return ret ? -EFAULT : 0;
182 }
183 
184 static int ptrace_setxregs(struct task_struct *child, void __user *uregs)
185 {
186 	struct thread_info *ti = task_thread_info(child);
187 	struct pt_regs *regs = task_pt_regs(child);
188 	elf_xtregs_t *xtregs = uregs;
189 	int ret = 0;
190 	int i __maybe_unused;
191 
192 	if (!access_ok(VERIFY_READ, uregs, sizeof(elf_xtregs_t)))
193 		return -EFAULT;
194 
195 #if XTENSA_HAVE_COPROCESSORS
196 	/* Flush all coprocessors before we overwrite them. */
197 	coprocessor_flush_all(ti);
198 	coprocessor_release_all(ti);
199 
200 	for (i = 0; i < ARRAY_SIZE(cp_offsets); ++i)
201 		ret |= __copy_from_user((char *)ti + cp_offsets[i].ti_offset,
202 					(const char __user *)xtregs +
203 					cp_offsets[i].elf_xtregs_offset,
204 					cp_offsets[i].sz);
205 #endif
206 	ret |= __copy_from_user(&regs->xtregs_opt, &xtregs->opt,
207 				sizeof(xtregs->opt));
208 	ret |= __copy_from_user(&ti->xtregs_user, &xtregs->user,
209 				sizeof(xtregs->user));
210 
211 	return ret ? -EFAULT : 0;
212 }
213 
214 static int ptrace_peekusr(struct task_struct *child, long regno,
215 			  long __user *ret)
216 {
217 	struct pt_regs *regs;
218 	unsigned long tmp;
219 
220 	regs = task_pt_regs(child);
221 	tmp = 0;  /* Default return value. */
222 
223 	switch(regno) {
224 	case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
225 		tmp = regs->areg[regno - REG_AR_BASE];
226 		break;
227 
228 	case REG_A_BASE ... REG_A_BASE + 15:
229 		tmp = regs->areg[regno - REG_A_BASE];
230 		break;
231 
232 	case REG_PC:
233 		tmp = regs->pc;
234 		break;
235 
236 	case REG_PS:
237 		/* Note: PS.EXCM is not set while user task is running;
238 		 * its being set in regs is for exception handling
239 		 * convenience.
240 		 */
241 		tmp = (regs->ps & ~(1 << PS_EXCM_BIT));
242 		break;
243 
244 	case REG_WB:
245 		break;		/* tmp = 0 */
246 
247 	case REG_WS:
248 		{
249 			unsigned long wb = regs->windowbase;
250 			unsigned long ws = regs->windowstart;
251 			tmp = ((ws >> wb) | (ws << (WSBITS - wb))) &
252 				((1 << WSBITS) - 1);
253 			break;
254 		}
255 	case REG_LBEG:
256 		tmp = regs->lbeg;
257 		break;
258 
259 	case REG_LEND:
260 		tmp = regs->lend;
261 		break;
262 
263 	case REG_LCOUNT:
264 		tmp = regs->lcount;
265 		break;
266 
267 	case REG_SAR:
268 		tmp = regs->sar;
269 		break;
270 
271 	case SYSCALL_NR:
272 		tmp = regs->syscall;
273 		break;
274 
275 	default:
276 		return -EIO;
277 	}
278 	return put_user(tmp, ret);
279 }
280 
281 static int ptrace_pokeusr(struct task_struct *child, long regno, long val)
282 {
283 	struct pt_regs *regs;
284 	regs = task_pt_regs(child);
285 
286 	switch (regno) {
287 	case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
288 		regs->areg[regno - REG_AR_BASE] = val;
289 		break;
290 
291 	case REG_A_BASE ... REG_A_BASE + 15:
292 		regs->areg[regno - REG_A_BASE] = val;
293 		break;
294 
295 	case REG_PC:
296 		regs->pc = val;
297 		break;
298 
299 	case SYSCALL_NR:
300 		regs->syscall = val;
301 		break;
302 
303 	default:
304 		return -EIO;
305 	}
306 	return 0;
307 }
308 
309 #ifdef CONFIG_HAVE_HW_BREAKPOINT
310 static void ptrace_hbptriggered(struct perf_event *bp,
311 				struct perf_sample_data *data,
312 				struct pt_regs *regs)
313 {
314 	int i;
315 	struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
316 
317 	if (bp->attr.bp_type & HW_BREAKPOINT_X) {
318 		for (i = 0; i < XCHAL_NUM_IBREAK; ++i)
319 			if (current->thread.ptrace_bp[i] == bp)
320 				break;
321 		i <<= 1;
322 	} else {
323 		for (i = 0; i < XCHAL_NUM_DBREAK; ++i)
324 			if (current->thread.ptrace_wp[i] == bp)
325 				break;
326 		i = (i << 1) | 1;
327 	}
328 
329 	force_sig_ptrace_errno_trap(i, (void __user *)bkpt->address);
330 }
331 
332 static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type)
333 {
334 	struct perf_event_attr attr;
335 
336 	ptrace_breakpoint_init(&attr);
337 
338 	/* Initialise fields to sane defaults. */
339 	attr.bp_addr	= 0;
340 	attr.bp_len	= 1;
341 	attr.bp_type	= type;
342 	attr.disabled	= 1;
343 
344 	return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL,
345 					   tsk);
346 }
347 
348 /*
349  * Address bit 0 choose instruction (0) or data (1) break register, bits
350  * 31..1 are the register number.
351  * Both PTRACE_GETHBPREGS and PTRACE_SETHBPREGS transfer two 32-bit words:
352  * address (0) and control (1).
353  * Instruction breakpoint contorl word is 0 to clear breakpoint, 1 to set.
354  * Data breakpoint control word bit 31 is 'trigger on store', bit 30 is
355  * 'trigger on load, bits 29..0 are length. Length 0 is used to clear a
356  * breakpoint. To set a breakpoint length must be a power of 2 in the range
357  * 1..64 and the address must be length-aligned.
358  */
359 
360 static long ptrace_gethbpregs(struct task_struct *child, long addr,
361 			      long __user *datap)
362 {
363 	struct perf_event *bp;
364 	u32 user_data[2] = {0};
365 	bool dbreak = addr & 1;
366 	unsigned idx = addr >> 1;
367 
368 	if ((!dbreak && idx >= XCHAL_NUM_IBREAK) ||
369 	    (dbreak && idx >= XCHAL_NUM_DBREAK))
370 		return -EINVAL;
371 
372 	if (dbreak)
373 		bp = child->thread.ptrace_wp[idx];
374 	else
375 		bp = child->thread.ptrace_bp[idx];
376 
377 	if (bp) {
378 		user_data[0] = bp->attr.bp_addr;
379 		user_data[1] = bp->attr.disabled ? 0 : bp->attr.bp_len;
380 		if (dbreak) {
381 			if (bp->attr.bp_type & HW_BREAKPOINT_R)
382 				user_data[1] |= DBREAKC_LOAD_MASK;
383 			if (bp->attr.bp_type & HW_BREAKPOINT_W)
384 				user_data[1] |= DBREAKC_STOR_MASK;
385 		}
386 	}
387 
388 	if (copy_to_user(datap, user_data, sizeof(user_data)))
389 		return -EFAULT;
390 
391 	return 0;
392 }
393 
394 static long ptrace_sethbpregs(struct task_struct *child, long addr,
395 			      long __user *datap)
396 {
397 	struct perf_event *bp;
398 	struct perf_event_attr attr;
399 	u32 user_data[2];
400 	bool dbreak = addr & 1;
401 	unsigned idx = addr >> 1;
402 	int bp_type = 0;
403 
404 	if ((!dbreak && idx >= XCHAL_NUM_IBREAK) ||
405 	    (dbreak && idx >= XCHAL_NUM_DBREAK))
406 		return -EINVAL;
407 
408 	if (copy_from_user(user_data, datap, sizeof(user_data)))
409 		return -EFAULT;
410 
411 	if (dbreak) {
412 		bp = child->thread.ptrace_wp[idx];
413 		if (user_data[1] & DBREAKC_LOAD_MASK)
414 			bp_type |= HW_BREAKPOINT_R;
415 		if (user_data[1] & DBREAKC_STOR_MASK)
416 			bp_type |= HW_BREAKPOINT_W;
417 	} else {
418 		bp = child->thread.ptrace_bp[idx];
419 		bp_type = HW_BREAKPOINT_X;
420 	}
421 
422 	if (!bp) {
423 		bp = ptrace_hbp_create(child,
424 				       bp_type ? bp_type : HW_BREAKPOINT_RW);
425 		if (IS_ERR(bp))
426 			return PTR_ERR(bp);
427 		if (dbreak)
428 			child->thread.ptrace_wp[idx] = bp;
429 		else
430 			child->thread.ptrace_bp[idx] = bp;
431 	}
432 
433 	attr = bp->attr;
434 	attr.bp_addr = user_data[0];
435 	attr.bp_len = user_data[1] & ~(DBREAKC_LOAD_MASK | DBREAKC_STOR_MASK);
436 	attr.bp_type = bp_type;
437 	attr.disabled = !attr.bp_len;
438 
439 	return modify_user_hw_breakpoint(bp, &attr);
440 }
441 #endif
442 
443 long arch_ptrace(struct task_struct *child, long request,
444 		 unsigned long addr, unsigned long data)
445 {
446 	int ret = -EPERM;
447 	void __user *datap = (void __user *) data;
448 
449 	switch (request) {
450 	case PTRACE_PEEKTEXT:	/* read word at location addr. */
451 	case PTRACE_PEEKDATA:
452 		ret = generic_ptrace_peekdata(child, addr, data);
453 		break;
454 
455 	case PTRACE_PEEKUSR:	/* read register specified by addr. */
456 		ret = ptrace_peekusr(child, addr, datap);
457 		break;
458 
459 	case PTRACE_POKETEXT:	/* write the word at location addr. */
460 	case PTRACE_POKEDATA:
461 		ret = generic_ptrace_pokedata(child, addr, data);
462 		break;
463 
464 	case PTRACE_POKEUSR:	/* write register specified by addr. */
465 		ret = ptrace_pokeusr(child, addr, data);
466 		break;
467 
468 	case PTRACE_GETREGS:
469 		ret = ptrace_getregs(child, datap);
470 		break;
471 
472 	case PTRACE_SETREGS:
473 		ret = ptrace_setregs(child, datap);
474 		break;
475 
476 	case PTRACE_GETXTREGS:
477 		ret = ptrace_getxregs(child, datap);
478 		break;
479 
480 	case PTRACE_SETXTREGS:
481 		ret = ptrace_setxregs(child, datap);
482 		break;
483 #ifdef CONFIG_HAVE_HW_BREAKPOINT
484 	case PTRACE_GETHBPREGS:
485 		ret = ptrace_gethbpregs(child, addr, datap);
486 		break;
487 
488 	case PTRACE_SETHBPREGS:
489 		ret = ptrace_sethbpregs(child, addr, datap);
490 		break;
491 #endif
492 	default:
493 		ret = ptrace_request(child, request, addr, data);
494 		break;
495 	}
496 
497 	return ret;
498 }
499 
500 unsigned long do_syscall_trace_enter(struct pt_regs *regs)
501 {
502 	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
503 	    tracehook_report_syscall_entry(regs))
504 		return -1;
505 
506 	return regs->areg[2];
507 }
508 
509 void do_syscall_trace_leave(struct pt_regs *regs)
510 {
511 	int step;
512 
513 	step = test_thread_flag(TIF_SINGLESTEP);
514 
515 	if (step || test_thread_flag(TIF_SYSCALL_TRACE))
516 		tracehook_report_syscall_exit(regs, step);
517 }
518