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