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