xref: /openbmc/linux/arch/arm64/kernel/ptrace.c (revision 12eb4683)
1 /*
2  * Based on arch/arm/kernel/ptrace.c
3  *
4  * By Ross Biro 1/23/92
5  * edited by Linus Torvalds
6  * ARM modifications Copyright (C) 2000 Russell King
7  * Copyright (C) 2012 ARM Ltd.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <linux/kernel.h>
23 #include <linux/sched.h>
24 #include <linux/mm.h>
25 #include <linux/smp.h>
26 #include <linux/ptrace.h>
27 #include <linux/user.h>
28 #include <linux/security.h>
29 #include <linux/init.h>
30 #include <linux/signal.h>
31 #include <linux/uaccess.h>
32 #include <linux/perf_event.h>
33 #include <linux/hw_breakpoint.h>
34 #include <linux/regset.h>
35 #include <linux/tracehook.h>
36 #include <linux/elf.h>
37 
38 #include <asm/compat.h>
39 #include <asm/debug-monitors.h>
40 #include <asm/pgtable.h>
41 #include <asm/traps.h>
42 #include <asm/system_misc.h>
43 
44 /*
45  * TODO: does not yet catch signals sent when the child dies.
46  * in exit.c or in signal.c.
47  */
48 
49 /*
50  * Called by kernel/ptrace.c when detaching..
51  */
52 void ptrace_disable(struct task_struct *child)
53 {
54 }
55 
56 #ifdef CONFIG_HAVE_HW_BREAKPOINT
57 /*
58  * Handle hitting a HW-breakpoint.
59  */
60 static void ptrace_hbptriggered(struct perf_event *bp,
61 				struct perf_sample_data *data,
62 				struct pt_regs *regs)
63 {
64 	struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
65 	siginfo_t info = {
66 		.si_signo	= SIGTRAP,
67 		.si_errno	= 0,
68 		.si_code	= TRAP_HWBKPT,
69 		.si_addr	= (void __user *)(bkpt->trigger),
70 	};
71 
72 #ifdef CONFIG_COMPAT
73 	int i;
74 
75 	if (!is_compat_task())
76 		goto send_sig;
77 
78 	for (i = 0; i < ARM_MAX_BRP; ++i) {
79 		if (current->thread.debug.hbp_break[i] == bp) {
80 			info.si_errno = (i << 1) + 1;
81 			break;
82 		}
83 	}
84 	for (i = ARM_MAX_BRP; i < ARM_MAX_HBP_SLOTS && !bp; ++i) {
85 		if (current->thread.debug.hbp_watch[i] == bp) {
86 			info.si_errno = -((i << 1) + 1);
87 			break;
88 		}
89 	}
90 
91 send_sig:
92 #endif
93 	force_sig_info(SIGTRAP, &info, current);
94 }
95 
96 /*
97  * Unregister breakpoints from this task and reset the pointers in
98  * the thread_struct.
99  */
100 void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
101 {
102 	int i;
103 	struct thread_struct *t = &tsk->thread;
104 
105 	for (i = 0; i < ARM_MAX_BRP; i++) {
106 		if (t->debug.hbp_break[i]) {
107 			unregister_hw_breakpoint(t->debug.hbp_break[i]);
108 			t->debug.hbp_break[i] = NULL;
109 		}
110 	}
111 
112 	for (i = 0; i < ARM_MAX_WRP; i++) {
113 		if (t->debug.hbp_watch[i]) {
114 			unregister_hw_breakpoint(t->debug.hbp_watch[i]);
115 			t->debug.hbp_watch[i] = NULL;
116 		}
117 	}
118 }
119 
120 void ptrace_hw_copy_thread(struct task_struct *tsk)
121 {
122 	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
123 }
124 
125 static struct perf_event *ptrace_hbp_get_event(unsigned int note_type,
126 					       struct task_struct *tsk,
127 					       unsigned long idx)
128 {
129 	struct perf_event *bp = ERR_PTR(-EINVAL);
130 
131 	switch (note_type) {
132 	case NT_ARM_HW_BREAK:
133 		if (idx < ARM_MAX_BRP)
134 			bp = tsk->thread.debug.hbp_break[idx];
135 		break;
136 	case NT_ARM_HW_WATCH:
137 		if (idx < ARM_MAX_WRP)
138 			bp = tsk->thread.debug.hbp_watch[idx];
139 		break;
140 	}
141 
142 	return bp;
143 }
144 
145 static int ptrace_hbp_set_event(unsigned int note_type,
146 				struct task_struct *tsk,
147 				unsigned long idx,
148 				struct perf_event *bp)
149 {
150 	int err = -EINVAL;
151 
152 	switch (note_type) {
153 	case NT_ARM_HW_BREAK:
154 		if (idx < ARM_MAX_BRP) {
155 			tsk->thread.debug.hbp_break[idx] = bp;
156 			err = 0;
157 		}
158 		break;
159 	case NT_ARM_HW_WATCH:
160 		if (idx < ARM_MAX_WRP) {
161 			tsk->thread.debug.hbp_watch[idx] = bp;
162 			err = 0;
163 		}
164 		break;
165 	}
166 
167 	return err;
168 }
169 
170 static struct perf_event *ptrace_hbp_create(unsigned int note_type,
171 					    struct task_struct *tsk,
172 					    unsigned long idx)
173 {
174 	struct perf_event *bp;
175 	struct perf_event_attr attr;
176 	int err, type;
177 
178 	switch (note_type) {
179 	case NT_ARM_HW_BREAK:
180 		type = HW_BREAKPOINT_X;
181 		break;
182 	case NT_ARM_HW_WATCH:
183 		type = HW_BREAKPOINT_RW;
184 		break;
185 	default:
186 		return ERR_PTR(-EINVAL);
187 	}
188 
189 	ptrace_breakpoint_init(&attr);
190 
191 	/*
192 	 * Initialise fields to sane defaults
193 	 * (i.e. values that will pass validation).
194 	 */
195 	attr.bp_addr	= 0;
196 	attr.bp_len	= HW_BREAKPOINT_LEN_4;
197 	attr.bp_type	= type;
198 	attr.disabled	= 1;
199 
200 	bp = register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL, tsk);
201 	if (IS_ERR(bp))
202 		return bp;
203 
204 	err = ptrace_hbp_set_event(note_type, tsk, idx, bp);
205 	if (err)
206 		return ERR_PTR(err);
207 
208 	return bp;
209 }
210 
211 static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
212 				     struct arch_hw_breakpoint_ctrl ctrl,
213 				     struct perf_event_attr *attr)
214 {
215 	int err, len, type, disabled = !ctrl.enabled;
216 
217 	if (disabled) {
218 		len = 0;
219 		type = HW_BREAKPOINT_EMPTY;
220 	} else {
221 		err = arch_bp_generic_fields(ctrl, &len, &type);
222 		if (err)
223 			return err;
224 
225 		switch (note_type) {
226 		case NT_ARM_HW_BREAK:
227 			if ((type & HW_BREAKPOINT_X) != type)
228 				return -EINVAL;
229 			break;
230 		case NT_ARM_HW_WATCH:
231 			if ((type & HW_BREAKPOINT_RW) != type)
232 				return -EINVAL;
233 			break;
234 		default:
235 			return -EINVAL;
236 		}
237 	}
238 
239 	attr->bp_len	= len;
240 	attr->bp_type	= type;
241 	attr->disabled	= disabled;
242 
243 	return 0;
244 }
245 
246 static int ptrace_hbp_get_resource_info(unsigned int note_type, u32 *info)
247 {
248 	u8 num;
249 	u32 reg = 0;
250 
251 	switch (note_type) {
252 	case NT_ARM_HW_BREAK:
253 		num = hw_breakpoint_slots(TYPE_INST);
254 		break;
255 	case NT_ARM_HW_WATCH:
256 		num = hw_breakpoint_slots(TYPE_DATA);
257 		break;
258 	default:
259 		return -EINVAL;
260 	}
261 
262 	reg |= debug_monitors_arch();
263 	reg <<= 8;
264 	reg |= num;
265 
266 	*info = reg;
267 	return 0;
268 }
269 
270 static int ptrace_hbp_get_ctrl(unsigned int note_type,
271 			       struct task_struct *tsk,
272 			       unsigned long idx,
273 			       u32 *ctrl)
274 {
275 	struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
276 
277 	if (IS_ERR(bp))
278 		return PTR_ERR(bp);
279 
280 	*ctrl = bp ? encode_ctrl_reg(counter_arch_bp(bp)->ctrl) : 0;
281 	return 0;
282 }
283 
284 static int ptrace_hbp_get_addr(unsigned int note_type,
285 			       struct task_struct *tsk,
286 			       unsigned long idx,
287 			       u64 *addr)
288 {
289 	struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
290 
291 	if (IS_ERR(bp))
292 		return PTR_ERR(bp);
293 
294 	*addr = bp ? bp->attr.bp_addr : 0;
295 	return 0;
296 }
297 
298 static struct perf_event *ptrace_hbp_get_initialised_bp(unsigned int note_type,
299 							struct task_struct *tsk,
300 							unsigned long idx)
301 {
302 	struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
303 
304 	if (!bp)
305 		bp = ptrace_hbp_create(note_type, tsk, idx);
306 
307 	return bp;
308 }
309 
310 static int ptrace_hbp_set_ctrl(unsigned int note_type,
311 			       struct task_struct *tsk,
312 			       unsigned long idx,
313 			       u32 uctrl)
314 {
315 	int err;
316 	struct perf_event *bp;
317 	struct perf_event_attr attr;
318 	struct arch_hw_breakpoint_ctrl ctrl;
319 
320 	bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx);
321 	if (IS_ERR(bp)) {
322 		err = PTR_ERR(bp);
323 		return err;
324 	}
325 
326 	attr = bp->attr;
327 	decode_ctrl_reg(uctrl, &ctrl);
328 	err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr);
329 	if (err)
330 		return err;
331 
332 	return modify_user_hw_breakpoint(bp, &attr);
333 }
334 
335 static int ptrace_hbp_set_addr(unsigned int note_type,
336 			       struct task_struct *tsk,
337 			       unsigned long idx,
338 			       u64 addr)
339 {
340 	int err;
341 	struct perf_event *bp;
342 	struct perf_event_attr attr;
343 
344 	bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx);
345 	if (IS_ERR(bp)) {
346 		err = PTR_ERR(bp);
347 		return err;
348 	}
349 
350 	attr = bp->attr;
351 	attr.bp_addr = addr;
352 	err = modify_user_hw_breakpoint(bp, &attr);
353 	return err;
354 }
355 
356 #define PTRACE_HBP_ADDR_SZ	sizeof(u64)
357 #define PTRACE_HBP_CTRL_SZ	sizeof(u32)
358 #define PTRACE_HBP_PAD_SZ	sizeof(u32)
359 
360 static int hw_break_get(struct task_struct *target,
361 			const struct user_regset *regset,
362 			unsigned int pos, unsigned int count,
363 			void *kbuf, void __user *ubuf)
364 {
365 	unsigned int note_type = regset->core_note_type;
366 	int ret, idx = 0, offset, limit;
367 	u32 info, ctrl;
368 	u64 addr;
369 
370 	/* Resource info */
371 	ret = ptrace_hbp_get_resource_info(note_type, &info);
372 	if (ret)
373 		return ret;
374 
375 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0,
376 				  sizeof(info));
377 	if (ret)
378 		return ret;
379 
380 	/* Pad */
381 	offset = offsetof(struct user_hwdebug_state, pad);
382 	ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, offset,
383 				       offset + PTRACE_HBP_PAD_SZ);
384 	if (ret)
385 		return ret;
386 
387 	/* (address, ctrl) registers */
388 	offset = offsetof(struct user_hwdebug_state, dbg_regs);
389 	limit = regset->n * regset->size;
390 	while (count && offset < limit) {
391 		ret = ptrace_hbp_get_addr(note_type, target, idx, &addr);
392 		if (ret)
393 			return ret;
394 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &addr,
395 					  offset, offset + PTRACE_HBP_ADDR_SZ);
396 		if (ret)
397 			return ret;
398 		offset += PTRACE_HBP_ADDR_SZ;
399 
400 		ret = ptrace_hbp_get_ctrl(note_type, target, idx, &ctrl);
401 		if (ret)
402 			return ret;
403 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &ctrl,
404 					  offset, offset + PTRACE_HBP_CTRL_SZ);
405 		if (ret)
406 			return ret;
407 		offset += PTRACE_HBP_CTRL_SZ;
408 
409 		ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
410 					       offset,
411 					       offset + PTRACE_HBP_PAD_SZ);
412 		if (ret)
413 			return ret;
414 		offset += PTRACE_HBP_PAD_SZ;
415 		idx++;
416 	}
417 
418 	return 0;
419 }
420 
421 static int hw_break_set(struct task_struct *target,
422 			const struct user_regset *regset,
423 			unsigned int pos, unsigned int count,
424 			const void *kbuf, const void __user *ubuf)
425 {
426 	unsigned int note_type = regset->core_note_type;
427 	int ret, idx = 0, offset, limit;
428 	u32 ctrl;
429 	u64 addr;
430 
431 	/* Resource info and pad */
432 	offset = offsetof(struct user_hwdebug_state, dbg_regs);
433 	ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
434 	if (ret)
435 		return ret;
436 
437 	/* (address, ctrl) registers */
438 	limit = regset->n * regset->size;
439 	while (count && offset < limit) {
440 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,
441 					 offset, offset + PTRACE_HBP_ADDR_SZ);
442 		if (ret)
443 			return ret;
444 		ret = ptrace_hbp_set_addr(note_type, target, idx, addr);
445 		if (ret)
446 			return ret;
447 		offset += PTRACE_HBP_ADDR_SZ;
448 
449 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,
450 					 offset, offset + PTRACE_HBP_CTRL_SZ);
451 		if (ret)
452 			return ret;
453 		ret = ptrace_hbp_set_ctrl(note_type, target, idx, ctrl);
454 		if (ret)
455 			return ret;
456 		offset += PTRACE_HBP_CTRL_SZ;
457 
458 		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
459 						offset,
460 						offset + PTRACE_HBP_PAD_SZ);
461 		if (ret)
462 			return ret;
463 		offset += PTRACE_HBP_PAD_SZ;
464 		idx++;
465 	}
466 
467 	return 0;
468 }
469 #endif	/* CONFIG_HAVE_HW_BREAKPOINT */
470 
471 static int gpr_get(struct task_struct *target,
472 		   const struct user_regset *regset,
473 		   unsigned int pos, unsigned int count,
474 		   void *kbuf, void __user *ubuf)
475 {
476 	struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs;
477 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
478 }
479 
480 static int gpr_set(struct task_struct *target, const struct user_regset *regset,
481 		   unsigned int pos, unsigned int count,
482 		   const void *kbuf, const void __user *ubuf)
483 {
484 	int ret;
485 	struct user_pt_regs newregs;
486 
487 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
488 	if (ret)
489 		return ret;
490 
491 	if (!valid_user_regs(&newregs))
492 		return -EINVAL;
493 
494 	task_pt_regs(target)->user_regs = newregs;
495 	return 0;
496 }
497 
498 /*
499  * TODO: update fp accessors for lazy context switching (sync/flush hwstate)
500  */
501 static int fpr_get(struct task_struct *target, const struct user_regset *regset,
502 		   unsigned int pos, unsigned int count,
503 		   void *kbuf, void __user *ubuf)
504 {
505 	struct user_fpsimd_state *uregs;
506 	uregs = &target->thread.fpsimd_state.user_fpsimd;
507 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
508 }
509 
510 static int fpr_set(struct task_struct *target, const struct user_regset *regset,
511 		   unsigned int pos, unsigned int count,
512 		   const void *kbuf, const void __user *ubuf)
513 {
514 	int ret;
515 	struct user_fpsimd_state newstate;
516 
517 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);
518 	if (ret)
519 		return ret;
520 
521 	target->thread.fpsimd_state.user_fpsimd = newstate;
522 	return ret;
523 }
524 
525 static int tls_get(struct task_struct *target, const struct user_regset *regset,
526 		   unsigned int pos, unsigned int count,
527 		   void *kbuf, void __user *ubuf)
528 {
529 	unsigned long *tls = &target->thread.tp_value;
530 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, tls, 0, -1);
531 }
532 
533 static int tls_set(struct task_struct *target, const struct user_regset *regset,
534 		   unsigned int pos, unsigned int count,
535 		   const void *kbuf, const void __user *ubuf)
536 {
537 	int ret;
538 	unsigned long tls;
539 
540 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
541 	if (ret)
542 		return ret;
543 
544 	target->thread.tp_value = tls;
545 	return ret;
546 }
547 
548 enum aarch64_regset {
549 	REGSET_GPR,
550 	REGSET_FPR,
551 	REGSET_TLS,
552 #ifdef CONFIG_HAVE_HW_BREAKPOINT
553 	REGSET_HW_BREAK,
554 	REGSET_HW_WATCH,
555 #endif
556 };
557 
558 static const struct user_regset aarch64_regsets[] = {
559 	[REGSET_GPR] = {
560 		.core_note_type = NT_PRSTATUS,
561 		.n = sizeof(struct user_pt_regs) / sizeof(u64),
562 		.size = sizeof(u64),
563 		.align = sizeof(u64),
564 		.get = gpr_get,
565 		.set = gpr_set
566 	},
567 	[REGSET_FPR] = {
568 		.core_note_type = NT_PRFPREG,
569 		.n = sizeof(struct user_fpsimd_state) / sizeof(u32),
570 		/*
571 		 * We pretend we have 32-bit registers because the fpsr and
572 		 * fpcr are 32-bits wide.
573 		 */
574 		.size = sizeof(u32),
575 		.align = sizeof(u32),
576 		.get = fpr_get,
577 		.set = fpr_set
578 	},
579 	[REGSET_TLS] = {
580 		.core_note_type = NT_ARM_TLS,
581 		.n = 1,
582 		.size = sizeof(void *),
583 		.align = sizeof(void *),
584 		.get = tls_get,
585 		.set = tls_set,
586 	},
587 #ifdef CONFIG_HAVE_HW_BREAKPOINT
588 	[REGSET_HW_BREAK] = {
589 		.core_note_type = NT_ARM_HW_BREAK,
590 		.n = sizeof(struct user_hwdebug_state) / sizeof(u32),
591 		.size = sizeof(u32),
592 		.align = sizeof(u32),
593 		.get = hw_break_get,
594 		.set = hw_break_set,
595 	},
596 	[REGSET_HW_WATCH] = {
597 		.core_note_type = NT_ARM_HW_WATCH,
598 		.n = sizeof(struct user_hwdebug_state) / sizeof(u32),
599 		.size = sizeof(u32),
600 		.align = sizeof(u32),
601 		.get = hw_break_get,
602 		.set = hw_break_set,
603 	},
604 #endif
605 };
606 
607 static const struct user_regset_view user_aarch64_view = {
608 	.name = "aarch64", .e_machine = EM_AARCH64,
609 	.regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets)
610 };
611 
612 #ifdef CONFIG_COMPAT
613 #include <linux/compat.h>
614 
615 enum compat_regset {
616 	REGSET_COMPAT_GPR,
617 	REGSET_COMPAT_VFP,
618 };
619 
620 static int compat_gpr_get(struct task_struct *target,
621 			  const struct user_regset *regset,
622 			  unsigned int pos, unsigned int count,
623 			  void *kbuf, void __user *ubuf)
624 {
625 	int ret = 0;
626 	unsigned int i, start, num_regs;
627 
628 	/* Calculate the number of AArch32 registers contained in count */
629 	num_regs = count / regset->size;
630 
631 	/* Convert pos into an register number */
632 	start = pos / regset->size;
633 
634 	if (start + num_regs > regset->n)
635 		return -EIO;
636 
637 	for (i = 0; i < num_regs; ++i) {
638 		unsigned int idx = start + i;
639 		compat_ulong_t reg;
640 
641 		switch (idx) {
642 		case 15:
643 			reg = task_pt_regs(target)->pc;
644 			break;
645 		case 16:
646 			reg = task_pt_regs(target)->pstate;
647 			break;
648 		case 17:
649 			reg = task_pt_regs(target)->orig_x0;
650 			break;
651 		default:
652 			reg = task_pt_regs(target)->regs[idx];
653 		}
654 
655 		ret = copy_to_user(ubuf, &reg, sizeof(reg));
656 		if (ret)
657 			break;
658 
659 		ubuf += sizeof(reg);
660 	}
661 
662 	return ret;
663 }
664 
665 static int compat_gpr_set(struct task_struct *target,
666 			  const struct user_regset *regset,
667 			  unsigned int pos, unsigned int count,
668 			  const void *kbuf, const void __user *ubuf)
669 {
670 	struct pt_regs newregs;
671 	int ret = 0;
672 	unsigned int i, start, num_regs;
673 
674 	/* Calculate the number of AArch32 registers contained in count */
675 	num_regs = count / regset->size;
676 
677 	/* Convert pos into an register number */
678 	start = pos / regset->size;
679 
680 	if (start + num_regs > regset->n)
681 		return -EIO;
682 
683 	newregs = *task_pt_regs(target);
684 
685 	for (i = 0; i < num_regs; ++i) {
686 		unsigned int idx = start + i;
687 		compat_ulong_t reg;
688 
689 		ret = copy_from_user(&reg, ubuf, sizeof(reg));
690 		if (ret)
691 			return ret;
692 
693 		ubuf += sizeof(reg);
694 
695 		switch (idx) {
696 		case 15:
697 			newregs.pc = reg;
698 			break;
699 		case 16:
700 			newregs.pstate = reg;
701 			break;
702 		case 17:
703 			newregs.orig_x0 = reg;
704 			break;
705 		default:
706 			newregs.regs[idx] = reg;
707 		}
708 
709 	}
710 
711 	if (valid_user_regs(&newregs.user_regs))
712 		*task_pt_regs(target) = newregs;
713 	else
714 		ret = -EINVAL;
715 
716 	return ret;
717 }
718 
719 static int compat_vfp_get(struct task_struct *target,
720 			  const struct user_regset *regset,
721 			  unsigned int pos, unsigned int count,
722 			  void *kbuf, void __user *ubuf)
723 {
724 	struct user_fpsimd_state *uregs;
725 	compat_ulong_t fpscr;
726 	int ret;
727 
728 	uregs = &target->thread.fpsimd_state.user_fpsimd;
729 
730 	/*
731 	 * The VFP registers are packed into the fpsimd_state, so they all sit
732 	 * nicely together for us. We just need to create the fpscr separately.
733 	 */
734 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
735 				  VFP_STATE_SIZE - sizeof(compat_ulong_t));
736 
737 	if (count && !ret) {
738 		fpscr = (uregs->fpsr & VFP_FPSCR_STAT_MASK) |
739 			(uregs->fpcr & VFP_FPSCR_CTRL_MASK);
740 		ret = put_user(fpscr, (compat_ulong_t *)ubuf);
741 	}
742 
743 	return ret;
744 }
745 
746 static int compat_vfp_set(struct task_struct *target,
747 			  const struct user_regset *regset,
748 			  unsigned int pos, unsigned int count,
749 			  const void *kbuf, const void __user *ubuf)
750 {
751 	struct user_fpsimd_state *uregs;
752 	compat_ulong_t fpscr;
753 	int ret;
754 
755 	if (pos + count > VFP_STATE_SIZE)
756 		return -EIO;
757 
758 	uregs = &target->thread.fpsimd_state.user_fpsimd;
759 
760 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
761 				 VFP_STATE_SIZE - sizeof(compat_ulong_t));
762 
763 	if (count && !ret) {
764 		ret = get_user(fpscr, (compat_ulong_t *)ubuf);
765 		uregs->fpsr = fpscr & VFP_FPSCR_STAT_MASK;
766 		uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK;
767 	}
768 
769 	return ret;
770 }
771 
772 static const struct user_regset aarch32_regsets[] = {
773 	[REGSET_COMPAT_GPR] = {
774 		.core_note_type = NT_PRSTATUS,
775 		.n = COMPAT_ELF_NGREG,
776 		.size = sizeof(compat_elf_greg_t),
777 		.align = sizeof(compat_elf_greg_t),
778 		.get = compat_gpr_get,
779 		.set = compat_gpr_set
780 	},
781 	[REGSET_COMPAT_VFP] = {
782 		.core_note_type = NT_ARM_VFP,
783 		.n = VFP_STATE_SIZE / sizeof(compat_ulong_t),
784 		.size = sizeof(compat_ulong_t),
785 		.align = sizeof(compat_ulong_t),
786 		.get = compat_vfp_get,
787 		.set = compat_vfp_set
788 	},
789 };
790 
791 static const struct user_regset_view user_aarch32_view = {
792 	.name = "aarch32", .e_machine = EM_ARM,
793 	.regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets)
794 };
795 
796 static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
797 				   compat_ulong_t __user *ret)
798 {
799 	compat_ulong_t tmp;
800 
801 	if (off & 3)
802 		return -EIO;
803 
804 	if (off == COMPAT_PT_TEXT_ADDR)
805 		tmp = tsk->mm->start_code;
806 	else if (off == COMPAT_PT_DATA_ADDR)
807 		tmp = tsk->mm->start_data;
808 	else if (off == COMPAT_PT_TEXT_END_ADDR)
809 		tmp = tsk->mm->end_code;
810 	else if (off < sizeof(compat_elf_gregset_t))
811 		return copy_regset_to_user(tsk, &user_aarch32_view,
812 					   REGSET_COMPAT_GPR, off,
813 					   sizeof(compat_ulong_t), ret);
814 	else if (off >= COMPAT_USER_SZ)
815 		return -EIO;
816 	else
817 		tmp = 0;
818 
819 	return put_user(tmp, ret);
820 }
821 
822 static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off,
823 				    compat_ulong_t val)
824 {
825 	int ret;
826 
827 	if (off & 3 || off >= COMPAT_USER_SZ)
828 		return -EIO;
829 
830 	if (off >= sizeof(compat_elf_gregset_t))
831 		return 0;
832 
833 	ret = copy_regset_from_user(tsk, &user_aarch32_view,
834 				    REGSET_COMPAT_GPR, off,
835 				    sizeof(compat_ulong_t),
836 				    &val);
837 	return ret;
838 }
839 
840 #ifdef CONFIG_HAVE_HW_BREAKPOINT
841 
842 /*
843  * Convert a virtual register number into an index for a thread_info
844  * breakpoint array. Breakpoints are identified using positive numbers
845  * whilst watchpoints are negative. The registers are laid out as pairs
846  * of (address, control), each pair mapping to a unique hw_breakpoint struct.
847  * Register 0 is reserved for describing resource information.
848  */
849 static int compat_ptrace_hbp_num_to_idx(compat_long_t num)
850 {
851 	return (abs(num) - 1) >> 1;
852 }
853 
854 static int compat_ptrace_hbp_get_resource_info(u32 *kdata)
855 {
856 	u8 num_brps, num_wrps, debug_arch, wp_len;
857 	u32 reg = 0;
858 
859 	num_brps	= hw_breakpoint_slots(TYPE_INST);
860 	num_wrps	= hw_breakpoint_slots(TYPE_DATA);
861 
862 	debug_arch	= debug_monitors_arch();
863 	wp_len		= 8;
864 	reg		|= debug_arch;
865 	reg		<<= 8;
866 	reg		|= wp_len;
867 	reg		<<= 8;
868 	reg		|= num_wrps;
869 	reg		<<= 8;
870 	reg		|= num_brps;
871 
872 	*kdata = reg;
873 	return 0;
874 }
875 
876 static int compat_ptrace_hbp_get(unsigned int note_type,
877 				 struct task_struct *tsk,
878 				 compat_long_t num,
879 				 u32 *kdata)
880 {
881 	u64 addr = 0;
882 	u32 ctrl = 0;
883 
884 	int err, idx = compat_ptrace_hbp_num_to_idx(num);;
885 
886 	if (num & 1) {
887 		err = ptrace_hbp_get_addr(note_type, tsk, idx, &addr);
888 		*kdata = (u32)addr;
889 	} else {
890 		err = ptrace_hbp_get_ctrl(note_type, tsk, idx, &ctrl);
891 		*kdata = ctrl;
892 	}
893 
894 	return err;
895 }
896 
897 static int compat_ptrace_hbp_set(unsigned int note_type,
898 				 struct task_struct *tsk,
899 				 compat_long_t num,
900 				 u32 *kdata)
901 {
902 	u64 addr;
903 	u32 ctrl;
904 
905 	int err, idx = compat_ptrace_hbp_num_to_idx(num);
906 
907 	if (num & 1) {
908 		addr = *kdata;
909 		err = ptrace_hbp_set_addr(note_type, tsk, idx, addr);
910 	} else {
911 		ctrl = *kdata;
912 		err = ptrace_hbp_set_ctrl(note_type, tsk, idx, ctrl);
913 	}
914 
915 	return err;
916 }
917 
918 static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num,
919 				    compat_ulong_t __user *data)
920 {
921 	int ret;
922 	u32 kdata;
923 	mm_segment_t old_fs = get_fs();
924 
925 	set_fs(KERNEL_DS);
926 	/* Watchpoint */
927 	if (num < 0) {
928 		ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata);
929 	/* Resource info */
930 	} else if (num == 0) {
931 		ret = compat_ptrace_hbp_get_resource_info(&kdata);
932 	/* Breakpoint */
933 	} else {
934 		ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata);
935 	}
936 	set_fs(old_fs);
937 
938 	if (!ret)
939 		ret = put_user(kdata, data);
940 
941 	return ret;
942 }
943 
944 static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num,
945 				    compat_ulong_t __user *data)
946 {
947 	int ret;
948 	u32 kdata = 0;
949 	mm_segment_t old_fs = get_fs();
950 
951 	if (num == 0)
952 		return 0;
953 
954 	ret = get_user(kdata, data);
955 	if (ret)
956 		return ret;
957 
958 	set_fs(KERNEL_DS);
959 	if (num < 0)
960 		ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata);
961 	else
962 		ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata);
963 	set_fs(old_fs);
964 
965 	return ret;
966 }
967 #endif	/* CONFIG_HAVE_HW_BREAKPOINT */
968 
969 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
970 			compat_ulong_t caddr, compat_ulong_t cdata)
971 {
972 	unsigned long addr = caddr;
973 	unsigned long data = cdata;
974 	void __user *datap = compat_ptr(data);
975 	int ret;
976 
977 	switch (request) {
978 		case PTRACE_PEEKUSR:
979 			ret = compat_ptrace_read_user(child, addr, datap);
980 			break;
981 
982 		case PTRACE_POKEUSR:
983 			ret = compat_ptrace_write_user(child, addr, data);
984 			break;
985 
986 		case COMPAT_PTRACE_GETREGS:
987 			ret = copy_regset_to_user(child,
988 						  &user_aarch32_view,
989 						  REGSET_COMPAT_GPR,
990 						  0, sizeof(compat_elf_gregset_t),
991 						  datap);
992 			break;
993 
994 		case COMPAT_PTRACE_SETREGS:
995 			ret = copy_regset_from_user(child,
996 						    &user_aarch32_view,
997 						    REGSET_COMPAT_GPR,
998 						    0, sizeof(compat_elf_gregset_t),
999 						    datap);
1000 			break;
1001 
1002 		case COMPAT_PTRACE_GET_THREAD_AREA:
1003 			ret = put_user((compat_ulong_t)child->thread.tp_value,
1004 				       (compat_ulong_t __user *)datap);
1005 			break;
1006 
1007 		case COMPAT_PTRACE_SET_SYSCALL:
1008 			task_pt_regs(child)->syscallno = data;
1009 			ret = 0;
1010 			break;
1011 
1012 		case COMPAT_PTRACE_GETVFPREGS:
1013 			ret = copy_regset_to_user(child,
1014 						  &user_aarch32_view,
1015 						  REGSET_COMPAT_VFP,
1016 						  0, VFP_STATE_SIZE,
1017 						  datap);
1018 			break;
1019 
1020 		case COMPAT_PTRACE_SETVFPREGS:
1021 			ret = copy_regset_from_user(child,
1022 						    &user_aarch32_view,
1023 						    REGSET_COMPAT_VFP,
1024 						    0, VFP_STATE_SIZE,
1025 						    datap);
1026 			break;
1027 
1028 #ifdef CONFIG_HAVE_HW_BREAKPOINT
1029 		case COMPAT_PTRACE_GETHBPREGS:
1030 			ret = compat_ptrace_gethbpregs(child, addr, datap);
1031 			break;
1032 
1033 		case COMPAT_PTRACE_SETHBPREGS:
1034 			ret = compat_ptrace_sethbpregs(child, addr, datap);
1035 			break;
1036 #endif
1037 
1038 		default:
1039 			ret = compat_ptrace_request(child, request, addr,
1040 						    data);
1041 			break;
1042 	}
1043 
1044 	return ret;
1045 }
1046 #endif /* CONFIG_COMPAT */
1047 
1048 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
1049 {
1050 #ifdef CONFIG_COMPAT
1051 	if (is_compat_thread(task_thread_info(task)))
1052 		return &user_aarch32_view;
1053 #endif
1054 	return &user_aarch64_view;
1055 }
1056 
1057 long arch_ptrace(struct task_struct *child, long request,
1058 		 unsigned long addr, unsigned long data)
1059 {
1060 	return ptrace_request(child, request, addr, data);
1061 }
1062 
1063 asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
1064 {
1065 	unsigned long saved_reg;
1066 
1067 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
1068 		return regs->syscallno;
1069 
1070 	if (is_compat_task()) {
1071 		/* AArch32 uses ip (r12) for scratch */
1072 		saved_reg = regs->regs[12];
1073 		regs->regs[12] = dir;
1074 	} else {
1075 		/*
1076 		 * Save X7. X7 is used to denote syscall entry/exit:
1077 		 *   X7 = 0 -> entry, = 1 -> exit
1078 		 */
1079 		saved_reg = regs->regs[7];
1080 		regs->regs[7] = dir;
1081 	}
1082 
1083 	if (dir)
1084 		tracehook_report_syscall_exit(regs, 0);
1085 	else if (tracehook_report_syscall_entry(regs))
1086 		regs->syscallno = ~0UL;
1087 
1088 	if (is_compat_task())
1089 		regs->regs[12] = saved_reg;
1090 	else
1091 		regs->regs[7] = saved_reg;
1092 
1093 	return regs->syscallno;
1094 }
1095