xref: /linux/arch/arm64/kernel/ptrace.c (revision c4ee0af3fa0dc65f690fc908f02b8355f9576ea0)
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 	attr->disabled = disabled;
218 	if (disabled)
219 		return 0;
220 
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 	attr->bp_len	= len;
239 	attr->bp_type	= type;
240 
241 	return 0;
242 }
243 
244 static int ptrace_hbp_get_resource_info(unsigned int note_type, u32 *info)
245 {
246 	u8 num;
247 	u32 reg = 0;
248 
249 	switch (note_type) {
250 	case NT_ARM_HW_BREAK:
251 		num = hw_breakpoint_slots(TYPE_INST);
252 		break;
253 	case NT_ARM_HW_WATCH:
254 		num = hw_breakpoint_slots(TYPE_DATA);
255 		break;
256 	default:
257 		return -EINVAL;
258 	}
259 
260 	reg |= debug_monitors_arch();
261 	reg <<= 8;
262 	reg |= num;
263 
264 	*info = reg;
265 	return 0;
266 }
267 
268 static int ptrace_hbp_get_ctrl(unsigned int note_type,
269 			       struct task_struct *tsk,
270 			       unsigned long idx,
271 			       u32 *ctrl)
272 {
273 	struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
274 
275 	if (IS_ERR(bp))
276 		return PTR_ERR(bp);
277 
278 	*ctrl = bp ? encode_ctrl_reg(counter_arch_bp(bp)->ctrl) : 0;
279 	return 0;
280 }
281 
282 static int ptrace_hbp_get_addr(unsigned int note_type,
283 			       struct task_struct *tsk,
284 			       unsigned long idx,
285 			       u64 *addr)
286 {
287 	struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
288 
289 	if (IS_ERR(bp))
290 		return PTR_ERR(bp);
291 
292 	*addr = bp ? bp->attr.bp_addr : 0;
293 	return 0;
294 }
295 
296 static struct perf_event *ptrace_hbp_get_initialised_bp(unsigned int note_type,
297 							struct task_struct *tsk,
298 							unsigned long idx)
299 {
300 	struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
301 
302 	if (!bp)
303 		bp = ptrace_hbp_create(note_type, tsk, idx);
304 
305 	return bp;
306 }
307 
308 static int ptrace_hbp_set_ctrl(unsigned int note_type,
309 			       struct task_struct *tsk,
310 			       unsigned long idx,
311 			       u32 uctrl)
312 {
313 	int err;
314 	struct perf_event *bp;
315 	struct perf_event_attr attr;
316 	struct arch_hw_breakpoint_ctrl ctrl;
317 
318 	bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx);
319 	if (IS_ERR(bp)) {
320 		err = PTR_ERR(bp);
321 		return err;
322 	}
323 
324 	attr = bp->attr;
325 	decode_ctrl_reg(uctrl, &ctrl);
326 	err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr);
327 	if (err)
328 		return err;
329 
330 	return modify_user_hw_breakpoint(bp, &attr);
331 }
332 
333 static int ptrace_hbp_set_addr(unsigned int note_type,
334 			       struct task_struct *tsk,
335 			       unsigned long idx,
336 			       u64 addr)
337 {
338 	int err;
339 	struct perf_event *bp;
340 	struct perf_event_attr attr;
341 
342 	bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx);
343 	if (IS_ERR(bp)) {
344 		err = PTR_ERR(bp);
345 		return err;
346 	}
347 
348 	attr = bp->attr;
349 	attr.bp_addr = addr;
350 	err = modify_user_hw_breakpoint(bp, &attr);
351 	return err;
352 }
353 
354 #define PTRACE_HBP_ADDR_SZ	sizeof(u64)
355 #define PTRACE_HBP_CTRL_SZ	sizeof(u32)
356 #define PTRACE_HBP_PAD_SZ	sizeof(u32)
357 
358 static int hw_break_get(struct task_struct *target,
359 			const struct user_regset *regset,
360 			unsigned int pos, unsigned int count,
361 			void *kbuf, void __user *ubuf)
362 {
363 	unsigned int note_type = regset->core_note_type;
364 	int ret, idx = 0, offset, limit;
365 	u32 info, ctrl;
366 	u64 addr;
367 
368 	/* Resource info */
369 	ret = ptrace_hbp_get_resource_info(note_type, &info);
370 	if (ret)
371 		return ret;
372 
373 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0,
374 				  sizeof(info));
375 	if (ret)
376 		return ret;
377 
378 	/* Pad */
379 	offset = offsetof(struct user_hwdebug_state, pad);
380 	ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, offset,
381 				       offset + PTRACE_HBP_PAD_SZ);
382 	if (ret)
383 		return ret;
384 
385 	/* (address, ctrl) registers */
386 	offset = offsetof(struct user_hwdebug_state, dbg_regs);
387 	limit = regset->n * regset->size;
388 	while (count && offset < limit) {
389 		ret = ptrace_hbp_get_addr(note_type, target, idx, &addr);
390 		if (ret)
391 			return ret;
392 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &addr,
393 					  offset, offset + PTRACE_HBP_ADDR_SZ);
394 		if (ret)
395 			return ret;
396 		offset += PTRACE_HBP_ADDR_SZ;
397 
398 		ret = ptrace_hbp_get_ctrl(note_type, target, idx, &ctrl);
399 		if (ret)
400 			return ret;
401 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &ctrl,
402 					  offset, offset + PTRACE_HBP_CTRL_SZ);
403 		if (ret)
404 			return ret;
405 		offset += PTRACE_HBP_CTRL_SZ;
406 
407 		ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
408 					       offset,
409 					       offset + PTRACE_HBP_PAD_SZ);
410 		if (ret)
411 			return ret;
412 		offset += PTRACE_HBP_PAD_SZ;
413 		idx++;
414 	}
415 
416 	return 0;
417 }
418 
419 static int hw_break_set(struct task_struct *target,
420 			const struct user_regset *regset,
421 			unsigned int pos, unsigned int count,
422 			const void *kbuf, const void __user *ubuf)
423 {
424 	unsigned int note_type = regset->core_note_type;
425 	int ret, idx = 0, offset, limit;
426 	u32 ctrl;
427 	u64 addr;
428 
429 	/* Resource info and pad */
430 	offset = offsetof(struct user_hwdebug_state, dbg_regs);
431 	ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
432 	if (ret)
433 		return ret;
434 
435 	/* (address, ctrl) registers */
436 	limit = regset->n * regset->size;
437 	while (count && offset < limit) {
438 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,
439 					 offset, offset + PTRACE_HBP_ADDR_SZ);
440 		if (ret)
441 			return ret;
442 		ret = ptrace_hbp_set_addr(note_type, target, idx, addr);
443 		if (ret)
444 			return ret;
445 		offset += PTRACE_HBP_ADDR_SZ;
446 
447 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,
448 					 offset, offset + PTRACE_HBP_CTRL_SZ);
449 		if (ret)
450 			return ret;
451 		ret = ptrace_hbp_set_ctrl(note_type, target, idx, ctrl);
452 		if (ret)
453 			return ret;
454 		offset += PTRACE_HBP_CTRL_SZ;
455 
456 		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
457 						offset,
458 						offset + PTRACE_HBP_PAD_SZ);
459 		if (ret)
460 			return ret;
461 		offset += PTRACE_HBP_PAD_SZ;
462 		idx++;
463 	}
464 
465 	return 0;
466 }
467 #endif	/* CONFIG_HAVE_HW_BREAKPOINT */
468 
469 static int gpr_get(struct task_struct *target,
470 		   const struct user_regset *regset,
471 		   unsigned int pos, unsigned int count,
472 		   void *kbuf, void __user *ubuf)
473 {
474 	struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs;
475 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
476 }
477 
478 static int gpr_set(struct task_struct *target, const struct user_regset *regset,
479 		   unsigned int pos, unsigned int count,
480 		   const void *kbuf, const void __user *ubuf)
481 {
482 	int ret;
483 	struct user_pt_regs newregs;
484 
485 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
486 	if (ret)
487 		return ret;
488 
489 	if (!valid_user_regs(&newregs))
490 		return -EINVAL;
491 
492 	task_pt_regs(target)->user_regs = newregs;
493 	return 0;
494 }
495 
496 /*
497  * TODO: update fp accessors for lazy context switching (sync/flush hwstate)
498  */
499 static int fpr_get(struct task_struct *target, const struct user_regset *regset,
500 		   unsigned int pos, unsigned int count,
501 		   void *kbuf, void __user *ubuf)
502 {
503 	struct user_fpsimd_state *uregs;
504 	uregs = &target->thread.fpsimd_state.user_fpsimd;
505 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
506 }
507 
508 static int fpr_set(struct task_struct *target, const struct user_regset *regset,
509 		   unsigned int pos, unsigned int count,
510 		   const void *kbuf, const void __user *ubuf)
511 {
512 	int ret;
513 	struct user_fpsimd_state newstate;
514 
515 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);
516 	if (ret)
517 		return ret;
518 
519 	target->thread.fpsimd_state.user_fpsimd = newstate;
520 	return ret;
521 }
522 
523 static int tls_get(struct task_struct *target, const struct user_regset *regset,
524 		   unsigned int pos, unsigned int count,
525 		   void *kbuf, void __user *ubuf)
526 {
527 	unsigned long *tls = &target->thread.tp_value;
528 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, tls, 0, -1);
529 }
530 
531 static int tls_set(struct task_struct *target, const struct user_regset *regset,
532 		   unsigned int pos, unsigned int count,
533 		   const void *kbuf, const void __user *ubuf)
534 {
535 	int ret;
536 	unsigned long tls;
537 
538 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
539 	if (ret)
540 		return ret;
541 
542 	target->thread.tp_value = tls;
543 	return ret;
544 }
545 
546 enum aarch64_regset {
547 	REGSET_GPR,
548 	REGSET_FPR,
549 	REGSET_TLS,
550 #ifdef CONFIG_HAVE_HW_BREAKPOINT
551 	REGSET_HW_BREAK,
552 	REGSET_HW_WATCH,
553 #endif
554 };
555 
556 static const struct user_regset aarch64_regsets[] = {
557 	[REGSET_GPR] = {
558 		.core_note_type = NT_PRSTATUS,
559 		.n = sizeof(struct user_pt_regs) / sizeof(u64),
560 		.size = sizeof(u64),
561 		.align = sizeof(u64),
562 		.get = gpr_get,
563 		.set = gpr_set
564 	},
565 	[REGSET_FPR] = {
566 		.core_note_type = NT_PRFPREG,
567 		.n = sizeof(struct user_fpsimd_state) / sizeof(u32),
568 		/*
569 		 * We pretend we have 32-bit registers because the fpsr and
570 		 * fpcr are 32-bits wide.
571 		 */
572 		.size = sizeof(u32),
573 		.align = sizeof(u32),
574 		.get = fpr_get,
575 		.set = fpr_set
576 	},
577 	[REGSET_TLS] = {
578 		.core_note_type = NT_ARM_TLS,
579 		.n = 1,
580 		.size = sizeof(void *),
581 		.align = sizeof(void *),
582 		.get = tls_get,
583 		.set = tls_set,
584 	},
585 #ifdef CONFIG_HAVE_HW_BREAKPOINT
586 	[REGSET_HW_BREAK] = {
587 		.core_note_type = NT_ARM_HW_BREAK,
588 		.n = sizeof(struct user_hwdebug_state) / sizeof(u32),
589 		.size = sizeof(u32),
590 		.align = sizeof(u32),
591 		.get = hw_break_get,
592 		.set = hw_break_set,
593 	},
594 	[REGSET_HW_WATCH] = {
595 		.core_note_type = NT_ARM_HW_WATCH,
596 		.n = sizeof(struct user_hwdebug_state) / sizeof(u32),
597 		.size = sizeof(u32),
598 		.align = sizeof(u32),
599 		.get = hw_break_get,
600 		.set = hw_break_set,
601 	},
602 #endif
603 };
604 
605 static const struct user_regset_view user_aarch64_view = {
606 	.name = "aarch64", .e_machine = EM_AARCH64,
607 	.regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets)
608 };
609 
610 #ifdef CONFIG_COMPAT
611 #include <linux/compat.h>
612 
613 enum compat_regset {
614 	REGSET_COMPAT_GPR,
615 	REGSET_COMPAT_VFP,
616 };
617 
618 static int compat_gpr_get(struct task_struct *target,
619 			  const struct user_regset *regset,
620 			  unsigned int pos, unsigned int count,
621 			  void *kbuf, void __user *ubuf)
622 {
623 	int ret = 0;
624 	unsigned int i, start, num_regs;
625 
626 	/* Calculate the number of AArch32 registers contained in count */
627 	num_regs = count / regset->size;
628 
629 	/* Convert pos into an register number */
630 	start = pos / regset->size;
631 
632 	if (start + num_regs > regset->n)
633 		return -EIO;
634 
635 	for (i = 0; i < num_regs; ++i) {
636 		unsigned int idx = start + i;
637 		compat_ulong_t reg;
638 
639 		switch (idx) {
640 		case 15:
641 			reg = task_pt_regs(target)->pc;
642 			break;
643 		case 16:
644 			reg = task_pt_regs(target)->pstate;
645 			break;
646 		case 17:
647 			reg = task_pt_regs(target)->orig_x0;
648 			break;
649 		default:
650 			reg = task_pt_regs(target)->regs[idx];
651 		}
652 
653 		ret = copy_to_user(ubuf, &reg, sizeof(reg));
654 		if (ret)
655 			break;
656 
657 		ubuf += sizeof(reg);
658 	}
659 
660 	return ret;
661 }
662 
663 static int compat_gpr_set(struct task_struct *target,
664 			  const struct user_regset *regset,
665 			  unsigned int pos, unsigned int count,
666 			  const void *kbuf, const void __user *ubuf)
667 {
668 	struct pt_regs newregs;
669 	int ret = 0;
670 	unsigned int i, start, num_regs;
671 
672 	/* Calculate the number of AArch32 registers contained in count */
673 	num_regs = count / regset->size;
674 
675 	/* Convert pos into an register number */
676 	start = pos / regset->size;
677 
678 	if (start + num_regs > regset->n)
679 		return -EIO;
680 
681 	newregs = *task_pt_regs(target);
682 
683 	for (i = 0; i < num_regs; ++i) {
684 		unsigned int idx = start + i;
685 		compat_ulong_t reg;
686 
687 		ret = copy_from_user(&reg, ubuf, sizeof(reg));
688 		if (ret)
689 			return ret;
690 
691 		ubuf += sizeof(reg);
692 
693 		switch (idx) {
694 		case 15:
695 			newregs.pc = reg;
696 			break;
697 		case 16:
698 			newregs.pstate = reg;
699 			break;
700 		case 17:
701 			newregs.orig_x0 = reg;
702 			break;
703 		default:
704 			newregs.regs[idx] = reg;
705 		}
706 
707 	}
708 
709 	if (valid_user_regs(&newregs.user_regs))
710 		*task_pt_regs(target) = newregs;
711 	else
712 		ret = -EINVAL;
713 
714 	return ret;
715 }
716 
717 static int compat_vfp_get(struct task_struct *target,
718 			  const struct user_regset *regset,
719 			  unsigned int pos, unsigned int count,
720 			  void *kbuf, void __user *ubuf)
721 {
722 	struct user_fpsimd_state *uregs;
723 	compat_ulong_t fpscr;
724 	int ret;
725 
726 	uregs = &target->thread.fpsimd_state.user_fpsimd;
727 
728 	/*
729 	 * The VFP registers are packed into the fpsimd_state, so they all sit
730 	 * nicely together for us. We just need to create the fpscr separately.
731 	 */
732 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
733 				  VFP_STATE_SIZE - sizeof(compat_ulong_t));
734 
735 	if (count && !ret) {
736 		fpscr = (uregs->fpsr & VFP_FPSCR_STAT_MASK) |
737 			(uregs->fpcr & VFP_FPSCR_CTRL_MASK);
738 		ret = put_user(fpscr, (compat_ulong_t *)ubuf);
739 	}
740 
741 	return ret;
742 }
743 
744 static int compat_vfp_set(struct task_struct *target,
745 			  const struct user_regset *regset,
746 			  unsigned int pos, unsigned int count,
747 			  const void *kbuf, const void __user *ubuf)
748 {
749 	struct user_fpsimd_state *uregs;
750 	compat_ulong_t fpscr;
751 	int ret;
752 
753 	if (pos + count > VFP_STATE_SIZE)
754 		return -EIO;
755 
756 	uregs = &target->thread.fpsimd_state.user_fpsimd;
757 
758 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
759 				 VFP_STATE_SIZE - sizeof(compat_ulong_t));
760 
761 	if (count && !ret) {
762 		ret = get_user(fpscr, (compat_ulong_t *)ubuf);
763 		uregs->fpsr = fpscr & VFP_FPSCR_STAT_MASK;
764 		uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK;
765 	}
766 
767 	return ret;
768 }
769 
770 static const struct user_regset aarch32_regsets[] = {
771 	[REGSET_COMPAT_GPR] = {
772 		.core_note_type = NT_PRSTATUS,
773 		.n = COMPAT_ELF_NGREG,
774 		.size = sizeof(compat_elf_greg_t),
775 		.align = sizeof(compat_elf_greg_t),
776 		.get = compat_gpr_get,
777 		.set = compat_gpr_set
778 	},
779 	[REGSET_COMPAT_VFP] = {
780 		.core_note_type = NT_ARM_VFP,
781 		.n = VFP_STATE_SIZE / sizeof(compat_ulong_t),
782 		.size = sizeof(compat_ulong_t),
783 		.align = sizeof(compat_ulong_t),
784 		.get = compat_vfp_get,
785 		.set = compat_vfp_set
786 	},
787 };
788 
789 static const struct user_regset_view user_aarch32_view = {
790 	.name = "aarch32", .e_machine = EM_ARM,
791 	.regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets)
792 };
793 
794 static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
795 				   compat_ulong_t __user *ret)
796 {
797 	compat_ulong_t tmp;
798 
799 	if (off & 3)
800 		return -EIO;
801 
802 	if (off == COMPAT_PT_TEXT_ADDR)
803 		tmp = tsk->mm->start_code;
804 	else if (off == COMPAT_PT_DATA_ADDR)
805 		tmp = tsk->mm->start_data;
806 	else if (off == COMPAT_PT_TEXT_END_ADDR)
807 		tmp = tsk->mm->end_code;
808 	else if (off < sizeof(compat_elf_gregset_t))
809 		return copy_regset_to_user(tsk, &user_aarch32_view,
810 					   REGSET_COMPAT_GPR, off,
811 					   sizeof(compat_ulong_t), ret);
812 	else if (off >= COMPAT_USER_SZ)
813 		return -EIO;
814 	else
815 		tmp = 0;
816 
817 	return put_user(tmp, ret);
818 }
819 
820 static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off,
821 				    compat_ulong_t val)
822 {
823 	int ret;
824 
825 	if (off & 3 || off >= COMPAT_USER_SZ)
826 		return -EIO;
827 
828 	if (off >= sizeof(compat_elf_gregset_t))
829 		return 0;
830 
831 	ret = copy_regset_from_user(tsk, &user_aarch32_view,
832 				    REGSET_COMPAT_GPR, off,
833 				    sizeof(compat_ulong_t),
834 				    &val);
835 	return ret;
836 }
837 
838 #ifdef CONFIG_HAVE_HW_BREAKPOINT
839 
840 /*
841  * Convert a virtual register number into an index for a thread_info
842  * breakpoint array. Breakpoints are identified using positive numbers
843  * whilst watchpoints are negative. The registers are laid out as pairs
844  * of (address, control), each pair mapping to a unique hw_breakpoint struct.
845  * Register 0 is reserved for describing resource information.
846  */
847 static int compat_ptrace_hbp_num_to_idx(compat_long_t num)
848 {
849 	return (abs(num) - 1) >> 1;
850 }
851 
852 static int compat_ptrace_hbp_get_resource_info(u32 *kdata)
853 {
854 	u8 num_brps, num_wrps, debug_arch, wp_len;
855 	u32 reg = 0;
856 
857 	num_brps	= hw_breakpoint_slots(TYPE_INST);
858 	num_wrps	= hw_breakpoint_slots(TYPE_DATA);
859 
860 	debug_arch	= debug_monitors_arch();
861 	wp_len		= 8;
862 	reg		|= debug_arch;
863 	reg		<<= 8;
864 	reg		|= wp_len;
865 	reg		<<= 8;
866 	reg		|= num_wrps;
867 	reg		<<= 8;
868 	reg		|= num_brps;
869 
870 	*kdata = reg;
871 	return 0;
872 }
873 
874 static int compat_ptrace_hbp_get(unsigned int note_type,
875 				 struct task_struct *tsk,
876 				 compat_long_t num,
877 				 u32 *kdata)
878 {
879 	u64 addr = 0;
880 	u32 ctrl = 0;
881 
882 	int err, idx = compat_ptrace_hbp_num_to_idx(num);;
883 
884 	if (num & 1) {
885 		err = ptrace_hbp_get_addr(note_type, tsk, idx, &addr);
886 		*kdata = (u32)addr;
887 	} else {
888 		err = ptrace_hbp_get_ctrl(note_type, tsk, idx, &ctrl);
889 		*kdata = ctrl;
890 	}
891 
892 	return err;
893 }
894 
895 static int compat_ptrace_hbp_set(unsigned int note_type,
896 				 struct task_struct *tsk,
897 				 compat_long_t num,
898 				 u32 *kdata)
899 {
900 	u64 addr;
901 	u32 ctrl;
902 
903 	int err, idx = compat_ptrace_hbp_num_to_idx(num);
904 
905 	if (num & 1) {
906 		addr = *kdata;
907 		err = ptrace_hbp_set_addr(note_type, tsk, idx, addr);
908 	} else {
909 		ctrl = *kdata;
910 		err = ptrace_hbp_set_ctrl(note_type, tsk, idx, ctrl);
911 	}
912 
913 	return err;
914 }
915 
916 static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num,
917 				    compat_ulong_t __user *data)
918 {
919 	int ret;
920 	u32 kdata;
921 	mm_segment_t old_fs = get_fs();
922 
923 	set_fs(KERNEL_DS);
924 	/* Watchpoint */
925 	if (num < 0) {
926 		ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata);
927 	/* Resource info */
928 	} else if (num == 0) {
929 		ret = compat_ptrace_hbp_get_resource_info(&kdata);
930 	/* Breakpoint */
931 	} else {
932 		ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata);
933 	}
934 	set_fs(old_fs);
935 
936 	if (!ret)
937 		ret = put_user(kdata, data);
938 
939 	return ret;
940 }
941 
942 static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num,
943 				    compat_ulong_t __user *data)
944 {
945 	int ret;
946 	u32 kdata = 0;
947 	mm_segment_t old_fs = get_fs();
948 
949 	if (num == 0)
950 		return 0;
951 
952 	ret = get_user(kdata, data);
953 	if (ret)
954 		return ret;
955 
956 	set_fs(KERNEL_DS);
957 	if (num < 0)
958 		ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata);
959 	else
960 		ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata);
961 	set_fs(old_fs);
962 
963 	return ret;
964 }
965 #endif	/* CONFIG_HAVE_HW_BREAKPOINT */
966 
967 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
968 			compat_ulong_t caddr, compat_ulong_t cdata)
969 {
970 	unsigned long addr = caddr;
971 	unsigned long data = cdata;
972 	void __user *datap = compat_ptr(data);
973 	int ret;
974 
975 	switch (request) {
976 		case PTRACE_PEEKUSR:
977 			ret = compat_ptrace_read_user(child, addr, datap);
978 			break;
979 
980 		case PTRACE_POKEUSR:
981 			ret = compat_ptrace_write_user(child, addr, data);
982 			break;
983 
984 		case COMPAT_PTRACE_GETREGS:
985 			ret = copy_regset_to_user(child,
986 						  &user_aarch32_view,
987 						  REGSET_COMPAT_GPR,
988 						  0, sizeof(compat_elf_gregset_t),
989 						  datap);
990 			break;
991 
992 		case COMPAT_PTRACE_SETREGS:
993 			ret = copy_regset_from_user(child,
994 						    &user_aarch32_view,
995 						    REGSET_COMPAT_GPR,
996 						    0, sizeof(compat_elf_gregset_t),
997 						    datap);
998 			break;
999 
1000 		case COMPAT_PTRACE_GET_THREAD_AREA:
1001 			ret = put_user((compat_ulong_t)child->thread.tp_value,
1002 				       (compat_ulong_t __user *)datap);
1003 			break;
1004 
1005 		case COMPAT_PTRACE_SET_SYSCALL:
1006 			task_pt_regs(child)->syscallno = data;
1007 			ret = 0;
1008 			break;
1009 
1010 		case COMPAT_PTRACE_GETVFPREGS:
1011 			ret = copy_regset_to_user(child,
1012 						  &user_aarch32_view,
1013 						  REGSET_COMPAT_VFP,
1014 						  0, VFP_STATE_SIZE,
1015 						  datap);
1016 			break;
1017 
1018 		case COMPAT_PTRACE_SETVFPREGS:
1019 			ret = copy_regset_from_user(child,
1020 						    &user_aarch32_view,
1021 						    REGSET_COMPAT_VFP,
1022 						    0, VFP_STATE_SIZE,
1023 						    datap);
1024 			break;
1025 
1026 #ifdef CONFIG_HAVE_HW_BREAKPOINT
1027 		case COMPAT_PTRACE_GETHBPREGS:
1028 			ret = compat_ptrace_gethbpregs(child, addr, datap);
1029 			break;
1030 
1031 		case COMPAT_PTRACE_SETHBPREGS:
1032 			ret = compat_ptrace_sethbpregs(child, addr, datap);
1033 			break;
1034 #endif
1035 
1036 		default:
1037 			ret = compat_ptrace_request(child, request, addr,
1038 						    data);
1039 			break;
1040 	}
1041 
1042 	return ret;
1043 }
1044 #endif /* CONFIG_COMPAT */
1045 
1046 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
1047 {
1048 #ifdef CONFIG_COMPAT
1049 	if (is_compat_thread(task_thread_info(task)))
1050 		return &user_aarch32_view;
1051 #endif
1052 	return &user_aarch64_view;
1053 }
1054 
1055 long arch_ptrace(struct task_struct *child, long request,
1056 		 unsigned long addr, unsigned long data)
1057 {
1058 	return ptrace_request(child, request, addr, data);
1059 }
1060 
1061 asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
1062 {
1063 	unsigned long saved_reg;
1064 
1065 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
1066 		return regs->syscallno;
1067 
1068 	if (is_compat_task()) {
1069 		/* AArch32 uses ip (r12) for scratch */
1070 		saved_reg = regs->regs[12];
1071 		regs->regs[12] = dir;
1072 	} else {
1073 		/*
1074 		 * Save X7. X7 is used to denote syscall entry/exit:
1075 		 *   X7 = 0 -> entry, = 1 -> exit
1076 		 */
1077 		saved_reg = regs->regs[7];
1078 		regs->regs[7] = dir;
1079 	}
1080 
1081 	if (dir)
1082 		tracehook_report_syscall_exit(regs, 0);
1083 	else if (tracehook_report_syscall_entry(regs))
1084 		regs->syscallno = ~0UL;
1085 
1086 	if (is_compat_task())
1087 		regs->regs[12] = saved_reg;
1088 	else
1089 		regs->regs[7] = saved_reg;
1090 
1091 	return regs->syscallno;
1092 }
1093