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