GNU Linux-libre 4.14.257-gnu1
[releases.git] / arch / sparc / kernel / ptrace_64.c
1 /* ptrace.c: Sparc process tracing support.
2  *
3  * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
4  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5  *
6  * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
7  * and David Mosberger.
8  *
9  * Added Linux support -miguel (weird, eh?, the original code was meant
10  * to emulate SunOS).
11  */
12
13 #include <linux/kernel.h>
14 #include <linux/sched.h>
15 #include <linux/sched/task_stack.h>
16 #include <linux/mm.h>
17 #include <linux/errno.h>
18 #include <linux/export.h>
19 #include <linux/ptrace.h>
20 #include <linux/user.h>
21 #include <linux/smp.h>
22 #include <linux/security.h>
23 #include <linux/seccomp.h>
24 #include <linux/audit.h>
25 #include <linux/signal.h>
26 #include <linux/regset.h>
27 #include <linux/tracehook.h>
28 #include <trace/syscall.h>
29 #include <linux/compat.h>
30 #include <linux/elf.h>
31 #include <linux/context_tracking.h>
32
33 #include <asm/asi.h>
34 #include <asm/pgtable.h>
35 #include <linux/uaccess.h>
36 #include <asm/psrcompat.h>
37 #include <asm/visasm.h>
38 #include <asm/spitfire.h>
39 #include <asm/page.h>
40 #include <asm/cpudata.h>
41 #include <asm/cacheflush.h>
42
43 #define CREATE_TRACE_POINTS
44 #include <trace/events/syscalls.h>
45
46 #include "entry.h"
47
48 /* #define ALLOW_INIT_TRACING */
49
50 struct pt_regs_offset {
51         const char *name;
52         int offset;
53 };
54
55 #define REG_OFFSET_NAME(n, r) \
56         {.name = n, .offset = (PT_V9_##r)}
57 #define REG_OFFSET_END {.name = NULL, .offset = 0}
58
59 static const struct pt_regs_offset regoffset_table[] = {
60         REG_OFFSET_NAME("g0", G0),
61         REG_OFFSET_NAME("g1", G1),
62         REG_OFFSET_NAME("g2", G2),
63         REG_OFFSET_NAME("g3", G3),
64         REG_OFFSET_NAME("g4", G4),
65         REG_OFFSET_NAME("g5", G5),
66         REG_OFFSET_NAME("g6", G6),
67         REG_OFFSET_NAME("g7", G7),
68
69         REG_OFFSET_NAME("i0", I0),
70         REG_OFFSET_NAME("i1", I1),
71         REG_OFFSET_NAME("i2", I2),
72         REG_OFFSET_NAME("i3", I3),
73         REG_OFFSET_NAME("i4", I4),
74         REG_OFFSET_NAME("i5", I5),
75         REG_OFFSET_NAME("i6", I6),
76         REG_OFFSET_NAME("i7", I7),
77
78         REG_OFFSET_NAME("tstate", TSTATE),
79         REG_OFFSET_NAME("pc", TPC),
80         REG_OFFSET_NAME("npc", TNPC),
81         REG_OFFSET_NAME("y", Y),
82         REG_OFFSET_NAME("lr", I7),
83
84         REG_OFFSET_END,
85 };
86
87 /*
88  * Called by kernel/ptrace.c when detaching..
89  *
90  * Make sure single step bits etc are not set.
91  */
92 void ptrace_disable(struct task_struct *child)
93 {
94         /* nothing to do */
95 }
96
97 /* To get the necessary page struct, access_process_vm() first calls
98  * get_user_pages().  This has done a flush_dcache_page() on the
99  * accessed page.  Then our caller (copy_{to,from}_user_page()) did
100  * to memcpy to read/write the data from that page.
101  *
102  * Now, the only thing we have to do is:
103  * 1) flush the D-cache if it's possible than an illegal alias
104  *    has been created
105  * 2) flush the I-cache if this is pre-cheetah and we did a write
106  */
107 void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
108                          unsigned long uaddr, void *kaddr,
109                          unsigned long len, int write)
110 {
111         BUG_ON(len > PAGE_SIZE);
112
113         if (tlb_type == hypervisor)
114                 return;
115
116         preempt_disable();
117
118 #ifdef DCACHE_ALIASING_POSSIBLE
119         /* If bit 13 of the kernel address we used to access the
120          * user page is the same as the virtual address that page
121          * is mapped to in the user's address space, we can skip the
122          * D-cache flush.
123          */
124         if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
125                 unsigned long start = __pa(kaddr);
126                 unsigned long end = start + len;
127                 unsigned long dcache_line_size;
128
129                 dcache_line_size = local_cpu_data().dcache_line_size;
130
131                 if (tlb_type == spitfire) {
132                         for (; start < end; start += dcache_line_size)
133                                 spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
134                 } else {
135                         start &= ~(dcache_line_size - 1);
136                         for (; start < end; start += dcache_line_size)
137                                 __asm__ __volatile__(
138                                         "stxa %%g0, [%0] %1\n\t"
139                                         "membar #Sync"
140                                         : /* no outputs */
141                                         : "r" (start),
142                                         "i" (ASI_DCACHE_INVALIDATE));
143                 }
144         }
145 #endif
146         if (write && tlb_type == spitfire) {
147                 unsigned long start = (unsigned long) kaddr;
148                 unsigned long end = start + len;
149                 unsigned long icache_line_size;
150
151                 icache_line_size = local_cpu_data().icache_line_size;
152
153                 for (; start < end; start += icache_line_size)
154                         flushi(start);
155         }
156
157         preempt_enable();
158 }
159 EXPORT_SYMBOL_GPL(flush_ptrace_access);
160
161 static int get_from_target(struct task_struct *target, unsigned long uaddr,
162                            void *kbuf, int len)
163 {
164         if (target == current) {
165                 if (copy_from_user(kbuf, (void __user *) uaddr, len))
166                         return -EFAULT;
167         } else {
168                 int len2 = access_process_vm(target, uaddr, kbuf, len,
169                                 FOLL_FORCE);
170                 if (len2 != len)
171                         return -EFAULT;
172         }
173         return 0;
174 }
175
176 static int set_to_target(struct task_struct *target, unsigned long uaddr,
177                          void *kbuf, int len)
178 {
179         if (target == current) {
180                 if (copy_to_user((void __user *) uaddr, kbuf, len))
181                         return -EFAULT;
182         } else {
183                 int len2 = access_process_vm(target, uaddr, kbuf, len,
184                                 FOLL_FORCE | FOLL_WRITE);
185                 if (len2 != len)
186                         return -EFAULT;
187         }
188         return 0;
189 }
190
191 static int regwindow64_get(struct task_struct *target,
192                            const struct pt_regs *regs,
193                            struct reg_window *wbuf)
194 {
195         unsigned long rw_addr = regs->u_regs[UREG_I6];
196
197         if (!test_thread_64bit_stack(rw_addr)) {
198                 struct reg_window32 win32;
199                 int i;
200
201                 if (get_from_target(target, rw_addr, &win32, sizeof(win32)))
202                         return -EFAULT;
203                 for (i = 0; i < 8; i++)
204                         wbuf->locals[i] = win32.locals[i];
205                 for (i = 0; i < 8; i++)
206                         wbuf->ins[i] = win32.ins[i];
207         } else {
208                 rw_addr += STACK_BIAS;
209                 if (get_from_target(target, rw_addr, wbuf, sizeof(*wbuf)))
210                         return -EFAULT;
211         }
212
213         return 0;
214 }
215
216 static int regwindow64_set(struct task_struct *target,
217                            const struct pt_regs *regs,
218                            struct reg_window *wbuf)
219 {
220         unsigned long rw_addr = regs->u_regs[UREG_I6];
221
222         if (!test_thread_64bit_stack(rw_addr)) {
223                 struct reg_window32 win32;
224                 int i;
225
226                 for (i = 0; i < 8; i++)
227                         win32.locals[i] = wbuf->locals[i];
228                 for (i = 0; i < 8; i++)
229                         win32.ins[i] = wbuf->ins[i];
230
231                 if (set_to_target(target, rw_addr, &win32, sizeof(win32)))
232                         return -EFAULT;
233         } else {
234                 rw_addr += STACK_BIAS;
235                 if (set_to_target(target, rw_addr, wbuf, sizeof(*wbuf)))
236                         return -EFAULT;
237         }
238
239         return 0;
240 }
241
242 enum sparc_regset {
243         REGSET_GENERAL,
244         REGSET_FP,
245 };
246
247 static int genregs64_get(struct task_struct *target,
248                          const struct user_regset *regset,
249                          unsigned int pos, unsigned int count,
250                          void *kbuf, void __user *ubuf)
251 {
252         const struct pt_regs *regs = task_pt_regs(target);
253         int ret;
254
255         if (target == current)
256                 flushw_user();
257
258         ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
259                                   regs->u_regs,
260                                   0, 16 * sizeof(u64));
261         if (!ret && count && pos < (32 * sizeof(u64))) {
262                 struct reg_window window;
263
264                 if (regwindow64_get(target, regs, &window))
265                         return -EFAULT;
266                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
267                                           &window,
268                                           16 * sizeof(u64),
269                                           32 * sizeof(u64));
270         }
271
272         if (!ret) {
273                 /* TSTATE, TPC, TNPC */
274                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
275                                           &regs->tstate,
276                                           32 * sizeof(u64),
277                                           35 * sizeof(u64));
278         }
279
280         if (!ret) {
281                 unsigned long y = regs->y;
282
283                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
284                                           &y,
285                                           35 * sizeof(u64),
286                                           36 * sizeof(u64));
287         }
288
289         if (!ret) {
290                 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
291                                                36 * sizeof(u64), -1);
292
293         }
294         return ret;
295 }
296
297 static int genregs64_set(struct task_struct *target,
298                          const struct user_regset *regset,
299                          unsigned int pos, unsigned int count,
300                          const void *kbuf, const void __user *ubuf)
301 {
302         struct pt_regs *regs = task_pt_regs(target);
303         int ret;
304
305         if (target == current)
306                 flushw_user();
307
308         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
309                                  regs->u_regs,
310                                  0, 16 * sizeof(u64));
311         if (!ret && count && pos < (32 * sizeof(u64))) {
312                 struct reg_window window;
313
314                 if (regwindow64_get(target, regs, &window))
315                         return -EFAULT;
316
317                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
318                                          &window,
319                                          16 * sizeof(u64),
320                                          32 * sizeof(u64));
321
322                 if (!ret &&
323                     regwindow64_set(target, regs, &window))
324                         return -EFAULT;
325         }
326
327         if (!ret && count > 0) {
328                 unsigned long tstate;
329
330                 /* TSTATE */
331                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
332                                          &tstate,
333                                          32 * sizeof(u64),
334                                          33 * sizeof(u64));
335                 if (!ret) {
336                         /* Only the condition codes and the "in syscall"
337                          * state can be modified in the %tstate register.
338                          */
339                         tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
340                         regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
341                         regs->tstate |= tstate;
342                 }
343         }
344
345         if (!ret) {
346                 /* TPC, TNPC */
347                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
348                                          &regs->tpc,
349                                          33 * sizeof(u64),
350                                          35 * sizeof(u64));
351         }
352
353         if (!ret) {
354                 unsigned long y = regs->y;
355
356                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
357                                          &y,
358                                          35 * sizeof(u64),
359                                          36 * sizeof(u64));
360                 if (!ret)
361                         regs->y = y;
362         }
363
364         if (!ret)
365                 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
366                                                 36 * sizeof(u64), -1);
367
368         return ret;
369 }
370
371 static int fpregs64_get(struct task_struct *target,
372                         const struct user_regset *regset,
373                         unsigned int pos, unsigned int count,
374                         void *kbuf, void __user *ubuf)
375 {
376         const unsigned long *fpregs = task_thread_info(target)->fpregs;
377         unsigned long fprs, fsr, gsr;
378         int ret;
379
380         if (target == current)
381                 save_and_clear_fpu();
382
383         fprs = task_thread_info(target)->fpsaved[0];
384
385         if (fprs & FPRS_DL)
386                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
387                                           fpregs,
388                                           0, 16 * sizeof(u64));
389         else
390                 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
391                                                0,
392                                                16 * sizeof(u64));
393
394         if (!ret) {
395                 if (fprs & FPRS_DU)
396                         ret = user_regset_copyout(&pos, &count,
397                                                   &kbuf, &ubuf,
398                                                   fpregs + 16,
399                                                   16 * sizeof(u64),
400                                                   32 * sizeof(u64));
401                 else
402                         ret = user_regset_copyout_zero(&pos, &count,
403                                                        &kbuf, &ubuf,
404                                                        16 * sizeof(u64),
405                                                        32 * sizeof(u64));
406         }
407
408         if (fprs & FPRS_FEF) {
409                 fsr = task_thread_info(target)->xfsr[0];
410                 gsr = task_thread_info(target)->gsr[0];
411         } else {
412                 fsr = gsr = 0;
413         }
414
415         if (!ret)
416                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
417                                           &fsr,
418                                           32 * sizeof(u64),
419                                           33 * sizeof(u64));
420         if (!ret)
421                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
422                                           &gsr,
423                                           33 * sizeof(u64),
424                                           34 * sizeof(u64));
425         if (!ret)
426                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
427                                           &fprs,
428                                           34 * sizeof(u64),
429                                           35 * sizeof(u64));
430
431         if (!ret)
432                 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
433                                                35 * sizeof(u64), -1);
434
435         return ret;
436 }
437
438 static int fpregs64_set(struct task_struct *target,
439                         const struct user_regset *regset,
440                         unsigned int pos, unsigned int count,
441                         const void *kbuf, const void __user *ubuf)
442 {
443         unsigned long *fpregs = task_thread_info(target)->fpregs;
444         unsigned long fprs;
445         int ret;
446
447         if (target == current)
448                 save_and_clear_fpu();
449
450         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
451                                  fpregs,
452                                  0, 32 * sizeof(u64));
453         if (!ret)
454                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
455                                          task_thread_info(target)->xfsr,
456                                          32 * sizeof(u64),
457                                          33 * sizeof(u64));
458         if (!ret)
459                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
460                                          task_thread_info(target)->gsr,
461                                          33 * sizeof(u64),
462                                          34 * sizeof(u64));
463
464         fprs = task_thread_info(target)->fpsaved[0];
465         if (!ret && count > 0) {
466                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
467                                          &fprs,
468                                          34 * sizeof(u64),
469                                          35 * sizeof(u64));
470         }
471
472         fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU);
473         task_thread_info(target)->fpsaved[0] = fprs;
474
475         if (!ret)
476                 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
477                                                 35 * sizeof(u64), -1);
478         return ret;
479 }
480
481 static const struct user_regset sparc64_regsets[] = {
482         /* Format is:
483          *      G0 --> G7
484          *      O0 --> O7
485          *      L0 --> L7
486          *      I0 --> I7
487          *      TSTATE, TPC, TNPC, Y
488          */
489         [REGSET_GENERAL] = {
490                 .core_note_type = NT_PRSTATUS,
491                 .n = 36,
492                 .size = sizeof(u64), .align = sizeof(u64),
493                 .get = genregs64_get, .set = genregs64_set
494         },
495         /* Format is:
496          *      F0 --> F63
497          *      FSR
498          *      GSR
499          *      FPRS
500          */
501         [REGSET_FP] = {
502                 .core_note_type = NT_PRFPREG,
503                 .n = 35,
504                 .size = sizeof(u64), .align = sizeof(u64),
505                 .get = fpregs64_get, .set = fpregs64_set
506         },
507 };
508
509 static const struct user_regset_view user_sparc64_view = {
510         .name = "sparc64", .e_machine = EM_SPARCV9,
511         .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets)
512 };
513
514 #ifdef CONFIG_COMPAT
515 static int genregs32_get(struct task_struct *target,
516                          const struct user_regset *regset,
517                          unsigned int pos, unsigned int count,
518                          void *kbuf, void __user *ubuf)
519 {
520         const struct pt_regs *regs = task_pt_regs(target);
521         compat_ulong_t __user *reg_window;
522         compat_ulong_t *k = kbuf;
523         compat_ulong_t __user *u = ubuf;
524         compat_ulong_t reg;
525
526         if (target == current)
527                 flushw_user();
528
529         pos /= sizeof(reg);
530         count /= sizeof(reg);
531
532         if (kbuf) {
533                 for (; count > 0 && pos < 16; count--)
534                         *k++ = regs->u_regs[pos++];
535
536                 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
537                 reg_window -= 16;
538                 if (target == current) {
539                         for (; count > 0 && pos < 32; count--) {
540                                 if (get_user(*k++, &reg_window[pos++]))
541                                         return -EFAULT;
542                         }
543                 } else {
544                         for (; count > 0 && pos < 32; count--) {
545                                 if (access_process_vm(target,
546                                                       (unsigned long)
547                                                       &reg_window[pos],
548                                                       k, sizeof(*k),
549                                                       FOLL_FORCE)
550                                     != sizeof(*k))
551                                         return -EFAULT;
552                                 k++;
553                                 pos++;
554                         }
555                 }
556         } else {
557                 for (; count > 0 && pos < 16; count--) {
558                         if (put_user((compat_ulong_t) regs->u_regs[pos++], u++))
559                                 return -EFAULT;
560                 }
561
562                 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
563                 reg_window -= 16;
564                 if (target == current) {
565                         for (; count > 0 && pos < 32; count--) {
566                                 if (get_user(reg, &reg_window[pos++]) ||
567                                     put_user(reg, u++))
568                                         return -EFAULT;
569                         }
570                 } else {
571                         for (; count > 0 && pos < 32; count--) {
572                                 if (access_process_vm(target,
573                                                       (unsigned long)
574                                                       &reg_window[pos++],
575                                                       &reg, sizeof(reg),
576                                                       FOLL_FORCE)
577                                     != sizeof(reg))
578                                         return -EFAULT;
579                                 if (put_user(reg, u++))
580                                         return -EFAULT;
581                         }
582                 }
583         }
584         while (count > 0) {
585                 switch (pos) {
586                 case 32: /* PSR */
587                         reg = tstate_to_psr(regs->tstate);
588                         break;
589                 case 33: /* PC */
590                         reg = regs->tpc;
591                         break;
592                 case 34: /* NPC */
593                         reg = regs->tnpc;
594                         break;
595                 case 35: /* Y */
596                         reg = regs->y;
597                         break;
598                 case 36: /* WIM */
599                 case 37: /* TBR */
600                         reg = 0;
601                         break;
602                 default:
603                         goto finish;
604                 }
605
606                 if (kbuf)
607                         *k++ = reg;
608                 else if (put_user(reg, u++))
609                         return -EFAULT;
610                 pos++;
611                 count--;
612         }
613 finish:
614         pos *= sizeof(reg);
615         count *= sizeof(reg);
616
617         return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
618                                         38 * sizeof(reg), -1);
619 }
620
621 static int genregs32_set(struct task_struct *target,
622                          const struct user_regset *regset,
623                          unsigned int pos, unsigned int count,
624                          const void *kbuf, const void __user *ubuf)
625 {
626         struct pt_regs *regs = task_pt_regs(target);
627         compat_ulong_t __user *reg_window;
628         const compat_ulong_t *k = kbuf;
629         const compat_ulong_t __user *u = ubuf;
630         compat_ulong_t reg;
631
632         if (target == current)
633                 flushw_user();
634
635         pos /= sizeof(reg);
636         count /= sizeof(reg);
637
638         if (kbuf) {
639                 for (; count > 0 && pos < 16; count--)
640                         regs->u_regs[pos++] = *k++;
641
642                 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
643                 reg_window -= 16;
644                 if (target == current) {
645                         for (; count > 0 && pos < 32; count--) {
646                                 if (put_user(*k++, &reg_window[pos++]))
647                                         return -EFAULT;
648                         }
649                 } else {
650                         for (; count > 0 && pos < 32; count--) {
651                                 if (access_process_vm(target,
652                                                       (unsigned long)
653                                                       &reg_window[pos],
654                                                       (void *) k,
655                                                       sizeof(*k),
656                                                       FOLL_FORCE | FOLL_WRITE)
657                                     != sizeof(*k))
658                                         return -EFAULT;
659                                 k++;
660                                 pos++;
661                         }
662                 }
663         } else {
664                 for (; count > 0 && pos < 16; count--) {
665                         if (get_user(reg, u++))
666                                 return -EFAULT;
667                         regs->u_regs[pos++] = reg;
668                 }
669
670                 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
671                 reg_window -= 16;
672                 if (target == current) {
673                         for (; count > 0 && pos < 32; count--) {
674                                 if (get_user(reg, u++) ||
675                                     put_user(reg, &reg_window[pos++]))
676                                         return -EFAULT;
677                         }
678                 } else {
679                         for (; count > 0 && pos < 32; count--) {
680                                 if (get_user(reg, u++))
681                                         return -EFAULT;
682                                 if (access_process_vm(target,
683                                                       (unsigned long)
684                                                       &reg_window[pos],
685                                                       &reg, sizeof(reg),
686                                                       FOLL_FORCE | FOLL_WRITE)
687                                     != sizeof(reg))
688                                         return -EFAULT;
689                                 pos++;
690                                 u++;
691                         }
692                 }
693         }
694         while (count > 0) {
695                 unsigned long tstate;
696
697                 if (kbuf)
698                         reg = *k++;
699                 else if (get_user(reg, u++))
700                         return -EFAULT;
701
702                 switch (pos) {
703                 case 32: /* PSR */
704                         tstate = regs->tstate;
705                         tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
706                         tstate |= psr_to_tstate_icc(reg);
707                         if (reg & PSR_SYSCALL)
708                                 tstate |= TSTATE_SYSCALL;
709                         regs->tstate = tstate;
710                         break;
711                 case 33: /* PC */
712                         regs->tpc = reg;
713                         break;
714                 case 34: /* NPC */
715                         regs->tnpc = reg;
716                         break;
717                 case 35: /* Y */
718                         regs->y = reg;
719                         break;
720                 case 36: /* WIM */
721                 case 37: /* TBR */
722                         break;
723                 default:
724                         goto finish;
725                 }
726
727                 pos++;
728                 count--;
729         }
730 finish:
731         pos *= sizeof(reg);
732         count *= sizeof(reg);
733
734         return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
735                                          38 * sizeof(reg), -1);
736 }
737
738 static int fpregs32_get(struct task_struct *target,
739                         const struct user_regset *regset,
740                         unsigned int pos, unsigned int count,
741                         void *kbuf, void __user *ubuf)
742 {
743         const unsigned long *fpregs = task_thread_info(target)->fpregs;
744         compat_ulong_t enabled;
745         unsigned long fprs;
746         compat_ulong_t fsr;
747         int ret = 0;
748
749         if (target == current)
750                 save_and_clear_fpu();
751
752         fprs = task_thread_info(target)->fpsaved[0];
753         if (fprs & FPRS_FEF) {
754                 fsr = task_thread_info(target)->xfsr[0];
755                 enabled = 1;
756         } else {
757                 fsr = 0;
758                 enabled = 0;
759         }
760
761         ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
762                                   fpregs,
763                                   0, 32 * sizeof(u32));
764
765         if (!ret)
766                 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
767                                                32 * sizeof(u32),
768                                                33 * sizeof(u32));
769         if (!ret)
770                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
771                                           &fsr,
772                                           33 * sizeof(u32),
773                                           34 * sizeof(u32));
774
775         if (!ret) {
776                 compat_ulong_t val;
777
778                 val = (enabled << 8) | (8 << 16);
779                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
780                                           &val,
781                                           34 * sizeof(u32),
782                                           35 * sizeof(u32));
783         }
784
785         if (!ret)
786                 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
787                                                35 * sizeof(u32), -1);
788
789         return ret;
790 }
791
792 static int fpregs32_set(struct task_struct *target,
793                         const struct user_regset *regset,
794                         unsigned int pos, unsigned int count,
795                         const void *kbuf, const void __user *ubuf)
796 {
797         unsigned long *fpregs = task_thread_info(target)->fpregs;
798         unsigned long fprs;
799         int ret;
800
801         if (target == current)
802                 save_and_clear_fpu();
803
804         fprs = task_thread_info(target)->fpsaved[0];
805
806         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
807                                  fpregs,
808                                  0, 32 * sizeof(u32));
809         if (!ret)
810                 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
811                                           32 * sizeof(u32),
812                                           33 * sizeof(u32));
813         if (!ret && count > 0) {
814                 compat_ulong_t fsr;
815                 unsigned long val;
816
817                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
818                                          &fsr,
819                                          33 * sizeof(u32),
820                                          34 * sizeof(u32));
821                 if (!ret) {
822                         val = task_thread_info(target)->xfsr[0];
823                         val &= 0xffffffff00000000UL;
824                         val |= fsr;
825                         task_thread_info(target)->xfsr[0] = val;
826                 }
827         }
828
829         fprs |= (FPRS_FEF | FPRS_DL);
830         task_thread_info(target)->fpsaved[0] = fprs;
831
832         if (!ret)
833                 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
834                                                 34 * sizeof(u32), -1);
835         return ret;
836 }
837
838 static const struct user_regset sparc32_regsets[] = {
839         /* Format is:
840          *      G0 --> G7
841          *      O0 --> O7
842          *      L0 --> L7
843          *      I0 --> I7
844          *      PSR, PC, nPC, Y, WIM, TBR
845          */
846         [REGSET_GENERAL] = {
847                 .core_note_type = NT_PRSTATUS,
848                 .n = 38,
849                 .size = sizeof(u32), .align = sizeof(u32),
850                 .get = genregs32_get, .set = genregs32_set
851         },
852         /* Format is:
853          *      F0 --> F31
854          *      empty 32-bit word
855          *      FSR (32--bit word)
856          *      FPU QUEUE COUNT (8-bit char)
857          *      FPU QUEUE ENTRYSIZE (8-bit char)
858          *      FPU ENABLED (8-bit char)
859          *      empty 8-bit char
860          *      FPU QUEUE (64 32-bit ints)
861          */
862         [REGSET_FP] = {
863                 .core_note_type = NT_PRFPREG,
864                 .n = 99,
865                 .size = sizeof(u32), .align = sizeof(u32),
866                 .get = fpregs32_get, .set = fpregs32_set
867         },
868 };
869
870 static const struct user_regset_view user_sparc32_view = {
871         .name = "sparc", .e_machine = EM_SPARC,
872         .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
873 };
874 #endif /* CONFIG_COMPAT */
875
876 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
877 {
878 #ifdef CONFIG_COMPAT
879         if (test_tsk_thread_flag(task, TIF_32BIT))
880                 return &user_sparc32_view;
881 #endif
882         return &user_sparc64_view;
883 }
884
885 #ifdef CONFIG_COMPAT
886 struct compat_fps {
887         unsigned int regs[32];
888         unsigned int fsr;
889         unsigned int flags;
890         unsigned int extra;
891         unsigned int fpqd;
892         struct compat_fq {
893                 unsigned int insnaddr;
894                 unsigned int insn;
895         } fpq[16];
896 };
897
898 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
899                         compat_ulong_t caddr, compat_ulong_t cdata)
900 {
901         const struct user_regset_view *view = task_user_regset_view(current);
902         compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4];
903         struct pt_regs32 __user *pregs;
904         struct compat_fps __user *fps;
905         unsigned long addr2 = caddr2;
906         unsigned long addr = caddr;
907         unsigned long data = cdata;
908         int ret;
909
910         pregs = (struct pt_regs32 __user *) addr;
911         fps = (struct compat_fps __user *) addr;
912
913         switch (request) {
914         case PTRACE_PEEKUSR:
915                 ret = (addr != 0) ? -EIO : 0;
916                 break;
917
918         case PTRACE_GETREGS:
919                 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
920                                           32 * sizeof(u32),
921                                           4 * sizeof(u32),
922                                           &pregs->psr);
923                 if (!ret)
924                         ret = copy_regset_to_user(child, view, REGSET_GENERAL,
925                                                   1 * sizeof(u32),
926                                                   15 * sizeof(u32),
927                                                   &pregs->u_regs[0]);
928                 break;
929
930         case PTRACE_SETREGS:
931                 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
932                                             32 * sizeof(u32),
933                                             4 * sizeof(u32),
934                                             &pregs->psr);
935                 if (!ret)
936                         ret = copy_regset_from_user(child, view, REGSET_GENERAL,
937                                                     1 * sizeof(u32),
938                                                     15 * sizeof(u32),
939                                                     &pregs->u_regs[0]);
940                 break;
941
942         case PTRACE_GETFPREGS:
943                 ret = copy_regset_to_user(child, view, REGSET_FP,
944                                           0 * sizeof(u32),
945                                           32 * sizeof(u32),
946                                           &fps->regs[0]);
947                 if (!ret)
948                         ret = copy_regset_to_user(child, view, REGSET_FP,
949                                                   33 * sizeof(u32),
950                                                   1 * sizeof(u32),
951                                                   &fps->fsr);
952                 if (!ret) {
953                         if (__put_user(0, &fps->flags) ||
954                             __put_user(0, &fps->extra) ||
955                             __put_user(0, &fps->fpqd) ||
956                             clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
957                                 ret = -EFAULT;
958                 }
959                 break;
960
961         case PTRACE_SETFPREGS:
962                 ret = copy_regset_from_user(child, view, REGSET_FP,
963                                             0 * sizeof(u32),
964                                             32 * sizeof(u32),
965                                             &fps->regs[0]);
966                 if (!ret)
967                         ret = copy_regset_from_user(child, view, REGSET_FP,
968                                                     33 * sizeof(u32),
969                                                     1 * sizeof(u32),
970                                                     &fps->fsr);
971                 break;
972
973         case PTRACE_READTEXT:
974         case PTRACE_READDATA:
975                 ret = ptrace_readdata(child, addr,
976                                       (char __user *)addr2, data);
977                 if (ret == data)
978                         ret = 0;
979                 else if (ret >= 0)
980                         ret = -EIO;
981                 break;
982
983         case PTRACE_WRITETEXT:
984         case PTRACE_WRITEDATA:
985                 ret = ptrace_writedata(child, (char __user *) addr2,
986                                        addr, data);
987                 if (ret == data)
988                         ret = 0;
989                 else if (ret >= 0)
990                         ret = -EIO;
991                 break;
992
993         default:
994                 if (request == PTRACE_SPARC_DETACH)
995                         request = PTRACE_DETACH;
996                 ret = compat_ptrace_request(child, request, addr, data);
997                 break;
998         }
999
1000         return ret;
1001 }
1002 #endif /* CONFIG_COMPAT */
1003
1004 struct fps {
1005         unsigned int regs[64];
1006         unsigned long fsr;
1007 };
1008
1009 long arch_ptrace(struct task_struct *child, long request,
1010                  unsigned long addr, unsigned long data)
1011 {
1012         const struct user_regset_view *view = task_user_regset_view(current);
1013         unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
1014         struct pt_regs __user *pregs;
1015         struct fps __user *fps;
1016         void __user *addr2p;
1017         int ret;
1018
1019         pregs = (struct pt_regs __user *) addr;
1020         fps = (struct fps __user *) addr;
1021         addr2p = (void __user *) addr2;
1022
1023         switch (request) {
1024         case PTRACE_PEEKUSR:
1025                 ret = (addr != 0) ? -EIO : 0;
1026                 break;
1027
1028         case PTRACE_GETREGS64:
1029                 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
1030                                           1 * sizeof(u64),
1031                                           15 * sizeof(u64),
1032                                           &pregs->u_regs[0]);
1033                 if (!ret) {
1034                         /* XXX doesn't handle 'y' register correctly XXX */
1035                         ret = copy_regset_to_user(child, view, REGSET_GENERAL,
1036                                                   32 * sizeof(u64),
1037                                                   4 * sizeof(u64),
1038                                                   &pregs->tstate);
1039                 }
1040                 break;
1041
1042         case PTRACE_SETREGS64:
1043                 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
1044                                             1 * sizeof(u64),
1045                                             15 * sizeof(u64),
1046                                             &pregs->u_regs[0]);
1047                 if (!ret) {
1048                         /* XXX doesn't handle 'y' register correctly XXX */
1049                         ret = copy_regset_from_user(child, view, REGSET_GENERAL,
1050                                                     32 * sizeof(u64),
1051                                                     4 * sizeof(u64),
1052                                                     &pregs->tstate);
1053                 }
1054                 break;
1055
1056         case PTRACE_GETFPREGS64:
1057                 ret = copy_regset_to_user(child, view, REGSET_FP,
1058                                           0 * sizeof(u64),
1059                                           33 * sizeof(u64),
1060                                           fps);
1061                 break;
1062
1063         case PTRACE_SETFPREGS64:
1064                 ret = copy_regset_from_user(child, view, REGSET_FP,
1065                                           0 * sizeof(u64),
1066                                           33 * sizeof(u64),
1067                                           fps);
1068                 break;
1069
1070         case PTRACE_READTEXT:
1071         case PTRACE_READDATA:
1072                 ret = ptrace_readdata(child, addr, addr2p, data);
1073                 if (ret == data)
1074                         ret = 0;
1075                 else if (ret >= 0)
1076                         ret = -EIO;
1077                 break;
1078
1079         case PTRACE_WRITETEXT:
1080         case PTRACE_WRITEDATA:
1081                 ret = ptrace_writedata(child, addr2p, addr, data);
1082                 if (ret == data)
1083                         ret = 0;
1084                 else if (ret >= 0)
1085                         ret = -EIO;
1086                 break;
1087
1088         default:
1089                 if (request == PTRACE_SPARC_DETACH)
1090                         request = PTRACE_DETACH;
1091                 ret = ptrace_request(child, request, addr, data);
1092                 break;
1093         }
1094
1095         return ret;
1096 }
1097
1098 asmlinkage int syscall_trace_enter(struct pt_regs *regs)
1099 {
1100         int ret = 0;
1101
1102         /* do the secure computing check first */
1103         secure_computing_strict(regs->u_regs[UREG_G1]);
1104
1105         if (test_thread_flag(TIF_NOHZ))
1106                 user_exit();
1107
1108         if (test_thread_flag(TIF_SYSCALL_TRACE))
1109                 ret = tracehook_report_syscall_entry(regs);
1110
1111         if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1112                 trace_sys_enter(regs, regs->u_regs[UREG_G1]);
1113
1114         audit_syscall_entry(regs->u_regs[UREG_G1], regs->u_regs[UREG_I0],
1115                             regs->u_regs[UREG_I1], regs->u_regs[UREG_I2],
1116                             regs->u_regs[UREG_I3]);
1117
1118         return ret;
1119 }
1120
1121 asmlinkage void syscall_trace_leave(struct pt_regs *regs)
1122 {
1123         if (test_thread_flag(TIF_NOHZ))
1124                 user_exit();
1125
1126         audit_syscall_exit(regs);
1127
1128         if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1129                 trace_sys_exit(regs, regs->u_regs[UREG_I0]);
1130
1131         if (test_thread_flag(TIF_SYSCALL_TRACE))
1132                 tracehook_report_syscall_exit(regs, 0);
1133
1134         if (test_thread_flag(TIF_NOHZ))
1135                 user_enter();
1136 }
1137
1138 /**
1139  * regs_query_register_offset() - query register offset from its name
1140  * @name:       the name of a register
1141  *
1142  * regs_query_register_offset() returns the offset of a register in struct
1143  * pt_regs from its name. If the name is invalid, this returns -EINVAL;
1144  */
1145 int regs_query_register_offset(const char *name)
1146 {
1147         const struct pt_regs_offset *roff;
1148
1149         for (roff = regoffset_table; roff->name != NULL; roff++)
1150                 if (!strcmp(roff->name, name))
1151                         return roff->offset;
1152         return -EINVAL;
1153 }
1154
1155 /**
1156  * regs_within_kernel_stack() - check the address in the stack
1157  * @regs:       pt_regs which contains kernel stack pointer.
1158  * @addr:       address which is checked.
1159  *
1160  * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
1161  * If @addr is within the kernel stack, it returns true. If not, returns false.
1162  */
1163 static inline int regs_within_kernel_stack(struct pt_regs *regs,
1164                                            unsigned long addr)
1165 {
1166         unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS;
1167         return ((addr & ~(THREAD_SIZE - 1))  ==
1168                 (ksp & ~(THREAD_SIZE - 1)));
1169 }
1170
1171 /**
1172  * regs_get_kernel_stack_nth() - get Nth entry of the stack
1173  * @regs:       pt_regs which contains kernel stack pointer.
1174  * @n:          stack entry number.
1175  *
1176  * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
1177  * is specified by @regs. If the @n th entry is NOT in the kernel stack,
1178  * this returns 0.
1179  */
1180 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
1181 {
1182         unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS;
1183         unsigned long *addr = (unsigned long *)ksp;
1184         addr += n;
1185         if (regs_within_kernel_stack(regs, (unsigned long)addr))
1186                 return *addr;
1187         else
1188                 return 0;
1189 }