Merge tag 'for-linus-4.11-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.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;
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 (access_process_vm(target,
580                                                       (unsigned long) u,
581                                                       &reg, sizeof(reg),
582                                                       FOLL_FORCE | FOLL_WRITE)
583                                     != sizeof(reg))
584                                         return -EFAULT;
585                                 pos++;
586                                 u++;
587                         }
588                 }
589         }
590         while (count > 0) {
591                 switch (pos) {
592                 case 32: /* PSR */
593                         reg = tstate_to_psr(regs->tstate);
594                         break;
595                 case 33: /* PC */
596                         reg = regs->tpc;
597                         break;
598                 case 34: /* NPC */
599                         reg = regs->tnpc;
600                         break;
601                 case 35: /* Y */
602                         reg = regs->y;
603                         break;
604                 case 36: /* WIM */
605                 case 37: /* TBR */
606                         reg = 0;
607                         break;
608                 default:
609                         goto finish;
610                 }
611
612                 if (kbuf)
613                         *k++ = reg;
614                 else if (put_user(reg, u++))
615                         return -EFAULT;
616                 pos++;
617                 count--;
618         }
619 finish:
620         pos *= sizeof(reg);
621         count *= sizeof(reg);
622
623         return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
624                                         38 * sizeof(reg), -1);
625 }
626
627 static int genregs32_set(struct task_struct *target,
628                          const struct user_regset *regset,
629                          unsigned int pos, unsigned int count,
630                          const void *kbuf, const void __user *ubuf)
631 {
632         struct pt_regs *regs = task_pt_regs(target);
633         compat_ulong_t __user *reg_window;
634         const compat_ulong_t *k = kbuf;
635         const compat_ulong_t __user *u = ubuf;
636         compat_ulong_t reg;
637
638         if (target == current)
639                 flushw_user();
640
641         pos /= sizeof(reg);
642         count /= sizeof(reg);
643
644         if (kbuf) {
645                 for (; count > 0 && pos < 16; count--)
646                         regs->u_regs[pos++] = *k++;
647
648                 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
649                 reg_window -= 16;
650                 if (target == current) {
651                         for (; count > 0 && pos < 32; count--) {
652                                 if (put_user(*k++, &reg_window[pos++]))
653                                         return -EFAULT;
654                         }
655                 } else {
656                         for (; count > 0 && pos < 32; count--) {
657                                 if (access_process_vm(target,
658                                                       (unsigned long)
659                                                       &reg_window[pos],
660                                                       (void *) k,
661                                                       sizeof(*k),
662                                                       FOLL_FORCE | FOLL_WRITE)
663                                     != sizeof(*k))
664                                         return -EFAULT;
665                                 k++;
666                                 pos++;
667                         }
668                 }
669         } else {
670                 for (; count > 0 && pos < 16; count--) {
671                         if (get_user(reg, u++))
672                                 return -EFAULT;
673                         regs->u_regs[pos++] = reg;
674                 }
675
676                 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
677                 reg_window -= 16;
678                 if (target == current) {
679                         for (; count > 0 && pos < 32; count--) {
680                                 if (get_user(reg, u++) ||
681                                     put_user(reg, &reg_window[pos++]))
682                                         return -EFAULT;
683                         }
684                 } else {
685                         for (; count > 0 && pos < 32; count--) {
686                                 if (access_process_vm(target,
687                                                       (unsigned long)
688                                                       u,
689                                                       &reg, sizeof(reg),
690                                                       FOLL_FORCE)
691                                     != sizeof(reg))
692                                         return -EFAULT;
693                                 if (access_process_vm(target,
694                                                       (unsigned long)
695                                                       &reg_window[pos],
696                                                       &reg, sizeof(reg),
697                                                       FOLL_FORCE | FOLL_WRITE)
698                                     != sizeof(reg))
699                                         return -EFAULT;
700                                 pos++;
701                                 u++;
702                         }
703                 }
704         }
705         while (count > 0) {
706                 unsigned long tstate;
707
708                 if (kbuf)
709                         reg = *k++;
710                 else if (get_user(reg, u++))
711                         return -EFAULT;
712
713                 switch (pos) {
714                 case 32: /* PSR */
715                         tstate = regs->tstate;
716                         tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
717                         tstate |= psr_to_tstate_icc(reg);
718                         if (reg & PSR_SYSCALL)
719                                 tstate |= TSTATE_SYSCALL;
720                         regs->tstate = tstate;
721                         break;
722                 case 33: /* PC */
723                         regs->tpc = reg;
724                         break;
725                 case 34: /* NPC */
726                         regs->tnpc = reg;
727                         break;
728                 case 35: /* Y */
729                         regs->y = reg;
730                         break;
731                 case 36: /* WIM */
732                 case 37: /* TBR */
733                         break;
734                 default:
735                         goto finish;
736                 }
737
738                 pos++;
739                 count--;
740         }
741 finish:
742         pos *= sizeof(reg);
743         count *= sizeof(reg);
744
745         return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
746                                          38 * sizeof(reg), -1);
747 }
748
749 static int fpregs32_get(struct task_struct *target,
750                         const struct user_regset *regset,
751                         unsigned int pos, unsigned int count,
752                         void *kbuf, void __user *ubuf)
753 {
754         const unsigned long *fpregs = task_thread_info(target)->fpregs;
755         compat_ulong_t enabled;
756         unsigned long fprs;
757         compat_ulong_t fsr;
758         int ret = 0;
759
760         if (target == current)
761                 save_and_clear_fpu();
762
763         fprs = task_thread_info(target)->fpsaved[0];
764         if (fprs & FPRS_FEF) {
765                 fsr = task_thread_info(target)->xfsr[0];
766                 enabled = 1;
767         } else {
768                 fsr = 0;
769                 enabled = 0;
770         }
771
772         ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
773                                   fpregs,
774                                   0, 32 * sizeof(u32));
775
776         if (!ret)
777                 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
778                                                32 * sizeof(u32),
779                                                33 * sizeof(u32));
780         if (!ret)
781                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
782                                           &fsr,
783                                           33 * sizeof(u32),
784                                           34 * sizeof(u32));
785
786         if (!ret) {
787                 compat_ulong_t val;
788
789                 val = (enabled << 8) | (8 << 16);
790                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
791                                           &val,
792                                           34 * sizeof(u32),
793                                           35 * sizeof(u32));
794         }
795
796         if (!ret)
797                 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
798                                                35 * sizeof(u32), -1);
799
800         return ret;
801 }
802
803 static int fpregs32_set(struct task_struct *target,
804                         const struct user_regset *regset,
805                         unsigned int pos, unsigned int count,
806                         const void *kbuf, const void __user *ubuf)
807 {
808         unsigned long *fpregs = task_thread_info(target)->fpregs;
809         unsigned long fprs;
810         int ret;
811
812         if (target == current)
813                 save_and_clear_fpu();
814
815         fprs = task_thread_info(target)->fpsaved[0];
816
817         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
818                                  fpregs,
819                                  0, 32 * sizeof(u32));
820         if (!ret)
821                 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
822                                           32 * sizeof(u32),
823                                           33 * sizeof(u32));
824         if (!ret && count > 0) {
825                 compat_ulong_t fsr;
826                 unsigned long val;
827
828                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
829                                          &fsr,
830                                          33 * sizeof(u32),
831                                          34 * sizeof(u32));
832                 if (!ret) {
833                         val = task_thread_info(target)->xfsr[0];
834                         val &= 0xffffffff00000000UL;
835                         val |= fsr;
836                         task_thread_info(target)->xfsr[0] = val;
837                 }
838         }
839
840         fprs |= (FPRS_FEF | FPRS_DL);
841         task_thread_info(target)->fpsaved[0] = fprs;
842
843         if (!ret)
844                 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
845                                                 34 * sizeof(u32), -1);
846         return ret;
847 }
848
849 static const struct user_regset sparc32_regsets[] = {
850         /* Format is:
851          *      G0 --> G7
852          *      O0 --> O7
853          *      L0 --> L7
854          *      I0 --> I7
855          *      PSR, PC, nPC, Y, WIM, TBR
856          */
857         [REGSET_GENERAL] = {
858                 .core_note_type = NT_PRSTATUS,
859                 .n = 38,
860                 .size = sizeof(u32), .align = sizeof(u32),
861                 .get = genregs32_get, .set = genregs32_set
862         },
863         /* Format is:
864          *      F0 --> F31
865          *      empty 32-bit word
866          *      FSR (32--bit word)
867          *      FPU QUEUE COUNT (8-bit char)
868          *      FPU QUEUE ENTRYSIZE (8-bit char)
869          *      FPU ENABLED (8-bit char)
870          *      empty 8-bit char
871          *      FPU QUEUE (64 32-bit ints)
872          */
873         [REGSET_FP] = {
874                 .core_note_type = NT_PRFPREG,
875                 .n = 99,
876                 .size = sizeof(u32), .align = sizeof(u32),
877                 .get = fpregs32_get, .set = fpregs32_set
878         },
879 };
880
881 static const struct user_regset_view user_sparc32_view = {
882         .name = "sparc", .e_machine = EM_SPARC,
883         .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
884 };
885 #endif /* CONFIG_COMPAT */
886
887 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
888 {
889 #ifdef CONFIG_COMPAT
890         if (test_tsk_thread_flag(task, TIF_32BIT))
891                 return &user_sparc32_view;
892 #endif
893         return &user_sparc64_view;
894 }
895
896 #ifdef CONFIG_COMPAT
897 struct compat_fps {
898         unsigned int regs[32];
899         unsigned int fsr;
900         unsigned int flags;
901         unsigned int extra;
902         unsigned int fpqd;
903         struct compat_fq {
904                 unsigned int insnaddr;
905                 unsigned int insn;
906         } fpq[16];
907 };
908
909 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
910                         compat_ulong_t caddr, compat_ulong_t cdata)
911 {
912         const struct user_regset_view *view = task_user_regset_view(current);
913         compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4];
914         struct pt_regs32 __user *pregs;
915         struct compat_fps __user *fps;
916         unsigned long addr2 = caddr2;
917         unsigned long addr = caddr;
918         unsigned long data = cdata;
919         int ret;
920
921         pregs = (struct pt_regs32 __user *) addr;
922         fps = (struct compat_fps __user *) addr;
923
924         switch (request) {
925         case PTRACE_PEEKUSR:
926                 ret = (addr != 0) ? -EIO : 0;
927                 break;
928
929         case PTRACE_GETREGS:
930                 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
931                                           32 * sizeof(u32),
932                                           4 * sizeof(u32),
933                                           &pregs->psr);
934                 if (!ret)
935                         ret = copy_regset_to_user(child, view, REGSET_GENERAL,
936                                                   1 * sizeof(u32),
937                                                   15 * sizeof(u32),
938                                                   &pregs->u_regs[0]);
939                 break;
940
941         case PTRACE_SETREGS:
942                 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
943                                             32 * sizeof(u32),
944                                             4 * sizeof(u32),
945                                             &pregs->psr);
946                 if (!ret)
947                         ret = copy_regset_from_user(child, view, REGSET_GENERAL,
948                                                     1 * sizeof(u32),
949                                                     15 * sizeof(u32),
950                                                     &pregs->u_regs[0]);
951                 break;
952
953         case PTRACE_GETFPREGS:
954                 ret = copy_regset_to_user(child, view, REGSET_FP,
955                                           0 * sizeof(u32),
956                                           32 * sizeof(u32),
957                                           &fps->regs[0]);
958                 if (!ret)
959                         ret = copy_regset_to_user(child, view, REGSET_FP,
960                                                   33 * sizeof(u32),
961                                                   1 * sizeof(u32),
962                                                   &fps->fsr);
963                 if (!ret) {
964                         if (__put_user(0, &fps->flags) ||
965                             __put_user(0, &fps->extra) ||
966                             __put_user(0, &fps->fpqd) ||
967                             clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
968                                 ret = -EFAULT;
969                 }
970                 break;
971
972         case PTRACE_SETFPREGS:
973                 ret = copy_regset_from_user(child, view, REGSET_FP,
974                                             0 * sizeof(u32),
975                                             32 * sizeof(u32),
976                                             &fps->regs[0]);
977                 if (!ret)
978                         ret = copy_regset_from_user(child, view, REGSET_FP,
979                                                     33 * sizeof(u32),
980                                                     1 * sizeof(u32),
981                                                     &fps->fsr);
982                 break;
983
984         case PTRACE_READTEXT:
985         case PTRACE_READDATA:
986                 ret = ptrace_readdata(child, addr,
987                                       (char __user *)addr2, data);
988                 if (ret == data)
989                         ret = 0;
990                 else if (ret >= 0)
991                         ret = -EIO;
992                 break;
993
994         case PTRACE_WRITETEXT:
995         case PTRACE_WRITEDATA:
996                 ret = ptrace_writedata(child, (char __user *) addr2,
997                                        addr, data);
998                 if (ret == data)
999                         ret = 0;
1000                 else if (ret >= 0)
1001                         ret = -EIO;
1002                 break;
1003
1004         default:
1005                 if (request == PTRACE_SPARC_DETACH)
1006                         request = PTRACE_DETACH;
1007                 ret = compat_ptrace_request(child, request, addr, data);
1008                 break;
1009         }
1010
1011         return ret;
1012 }
1013 #endif /* CONFIG_COMPAT */
1014
1015 struct fps {
1016         unsigned int regs[64];
1017         unsigned long fsr;
1018 };
1019
1020 long arch_ptrace(struct task_struct *child, long request,
1021                  unsigned long addr, unsigned long data)
1022 {
1023         const struct user_regset_view *view = task_user_regset_view(current);
1024         unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
1025         struct pt_regs __user *pregs;
1026         struct fps __user *fps;
1027         void __user *addr2p;
1028         int ret;
1029
1030         pregs = (struct pt_regs __user *) addr;
1031         fps = (struct fps __user *) addr;
1032         addr2p = (void __user *) addr2;
1033
1034         switch (request) {
1035         case PTRACE_PEEKUSR:
1036                 ret = (addr != 0) ? -EIO : 0;
1037                 break;
1038
1039         case PTRACE_GETREGS64:
1040                 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
1041                                           1 * sizeof(u64),
1042                                           15 * sizeof(u64),
1043                                           &pregs->u_regs[0]);
1044                 if (!ret) {
1045                         /* XXX doesn't handle 'y' register correctly XXX */
1046                         ret = copy_regset_to_user(child, view, REGSET_GENERAL,
1047                                                   32 * sizeof(u64),
1048                                                   4 * sizeof(u64),
1049                                                   &pregs->tstate);
1050                 }
1051                 break;
1052
1053         case PTRACE_SETREGS64:
1054                 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
1055                                             1 * sizeof(u64),
1056                                             15 * sizeof(u64),
1057                                             &pregs->u_regs[0]);
1058                 if (!ret) {
1059                         /* XXX doesn't handle 'y' register correctly XXX */
1060                         ret = copy_regset_from_user(child, view, REGSET_GENERAL,
1061                                                     32 * sizeof(u64),
1062                                                     4 * sizeof(u64),
1063                                                     &pregs->tstate);
1064                 }
1065                 break;
1066
1067         case PTRACE_GETFPREGS64:
1068                 ret = copy_regset_to_user(child, view, REGSET_FP,
1069                                           0 * sizeof(u64),
1070                                           33 * sizeof(u64),
1071                                           fps);
1072                 break;
1073
1074         case PTRACE_SETFPREGS64:
1075                 ret = copy_regset_from_user(child, view, REGSET_FP,
1076                                           0 * sizeof(u64),
1077                                           33 * sizeof(u64),
1078                                           fps);
1079                 break;
1080
1081         case PTRACE_READTEXT:
1082         case PTRACE_READDATA:
1083                 ret = ptrace_readdata(child, addr, addr2p, data);
1084                 if (ret == data)
1085                         ret = 0;
1086                 else if (ret >= 0)
1087                         ret = -EIO;
1088                 break;
1089
1090         case PTRACE_WRITETEXT:
1091         case PTRACE_WRITEDATA:
1092                 ret = ptrace_writedata(child, addr2p, addr, data);
1093                 if (ret == data)
1094                         ret = 0;
1095                 else if (ret >= 0)
1096                         ret = -EIO;
1097                 break;
1098
1099         default:
1100                 if (request == PTRACE_SPARC_DETACH)
1101                         request = PTRACE_DETACH;
1102                 ret = ptrace_request(child, request, addr, data);
1103                 break;
1104         }
1105
1106         return ret;
1107 }
1108
1109 asmlinkage int syscall_trace_enter(struct pt_regs *regs)
1110 {
1111         int ret = 0;
1112
1113         /* do the secure computing check first */
1114         secure_computing_strict(regs->u_regs[UREG_G1]);
1115
1116         if (test_thread_flag(TIF_NOHZ))
1117                 user_exit();
1118
1119         if (test_thread_flag(TIF_SYSCALL_TRACE))
1120                 ret = tracehook_report_syscall_entry(regs);
1121
1122         if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1123                 trace_sys_enter(regs, regs->u_regs[UREG_G1]);
1124
1125         audit_syscall_entry(regs->u_regs[UREG_G1], regs->u_regs[UREG_I0],
1126                             regs->u_regs[UREG_I1], regs->u_regs[UREG_I2],
1127                             regs->u_regs[UREG_I3]);
1128
1129         return ret;
1130 }
1131
1132 asmlinkage void syscall_trace_leave(struct pt_regs *regs)
1133 {
1134         if (test_thread_flag(TIF_NOHZ))
1135                 user_exit();
1136
1137         audit_syscall_exit(regs);
1138
1139         if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1140                 trace_sys_exit(regs, regs->u_regs[UREG_I0]);
1141
1142         if (test_thread_flag(TIF_SYSCALL_TRACE))
1143                 tracehook_report_syscall_exit(regs, 0);
1144
1145         if (test_thread_flag(TIF_NOHZ))
1146                 user_enter();
1147 }
1148
1149 /**
1150  * regs_query_register_offset() - query register offset from its name
1151  * @name:       the name of a register
1152  *
1153  * regs_query_register_offset() returns the offset of a register in struct
1154  * pt_regs from its name. If the name is invalid, this returns -EINVAL;
1155  */
1156 int regs_query_register_offset(const char *name)
1157 {
1158         const struct pt_regs_offset *roff;
1159
1160         for (roff = regoffset_table; roff->name != NULL; roff++)
1161                 if (!strcmp(roff->name, name))
1162                         return roff->offset;
1163         return -EINVAL;
1164 }