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