]> err.no Git - linux-2.6/blob - arch/sparc64/kernel/ptrace.c
[SPARC]: Kill DEBUG_PTRACE code.
[linux-2.6] / 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 ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
770             || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
771                 if (ptrace_attach(child)) {
772                         pt_error_return(regs, EPERM);
773                         goto out_tsk;
774                 }
775                 pt_succ_return(regs, 0);
776                 goto out_tsk;
777         }
778
779         ret = ptrace_check_attach(child, request == PTRACE_KILL);
780         if (ret < 0) {
781                 pt_error_return(regs, -ret);
782                 goto out_tsk;
783         }
784
785         if (!(test_thread_flag(TIF_32BIT))      &&
786             ((request == PTRACE_READDATA64)             ||
787              (request == PTRACE_WRITEDATA64)            ||
788              (request == PTRACE_READTEXT64)             ||
789              (request == PTRACE_WRITETEXT64)            ||
790              (request == PTRACE_PEEKTEXT64)             ||
791              (request == PTRACE_POKETEXT64)             ||
792              (request == PTRACE_PEEKDATA64)             ||
793              (request == PTRACE_POKEDATA64))) {
794                 addr = regs->u_regs[UREG_G2];
795                 addr2 = regs->u_regs[UREG_G3];
796                 request -= 30; /* wheee... */
797         }
798
799         switch(request) {
800         case PTRACE_PEEKUSR:
801                 if (addr != 0)
802                         pt_error_return(regs, EIO);
803                 else
804                         pt_succ_return(regs, 0);
805                 goto out_tsk;
806
807         case PTRACE_PEEKTEXT: /* read word at location addr. */ 
808         case PTRACE_PEEKDATA: {
809                 unsigned long tmp64;
810                 unsigned int tmp32;
811                 int res, copied;
812
813                 res = -EIO;
814                 if (test_thread_flag(TIF_32BIT)) {
815                         copied = access_process_vm(child, addr,
816                                                    &tmp32, sizeof(tmp32), 0);
817                         tmp64 = (unsigned long) tmp32;
818                         if (copied == sizeof(tmp32))
819                                 res = 0;
820                 } else {
821                         copied = access_process_vm(child, addr,
822                                                    &tmp64, sizeof(tmp64), 0);
823                         if (copied == sizeof(tmp64))
824                                 res = 0;
825                 }
826                 if (res < 0)
827                         pt_error_return(regs, -res);
828                 else
829                         pt_os_succ_return(regs, tmp64, (void __user *) data);
830                 goto out_tsk;
831         }
832
833         case PTRACE_POKETEXT: /* write the word at location addr. */
834         case PTRACE_POKEDATA: {
835                 unsigned long tmp64;
836                 unsigned int tmp32;
837                 int copied, res = -EIO;
838
839                 if (test_thread_flag(TIF_32BIT)) {
840                         tmp32 = data;
841                         copied = access_process_vm(child, addr,
842                                                    &tmp32, sizeof(tmp32), 1);
843                         if (copied == sizeof(tmp32))
844                                 res = 0;
845                 } else {
846                         tmp64 = data;
847                         copied = access_process_vm(child, addr,
848                                                    &tmp64, sizeof(tmp64), 1);
849                         if (copied == sizeof(tmp64))
850                                 res = 0;
851                 }
852                 if (res < 0)
853                         pt_error_return(regs, -res);
854                 else
855                         pt_succ_return(regs, res);
856                 goto out_tsk;
857         }
858
859         case PTRACE_GETREGS: {
860                 struct pt_regs32 __user *pregs =
861                         (struct pt_regs32 __user *) addr;
862                 struct pt_regs *cregs = task_pt_regs(child);
863                 int rval;
864
865                 if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
866                     __put_user(cregs->tpc, (&pregs->pc)) ||
867                     __put_user(cregs->tnpc, (&pregs->npc)) ||
868                     __put_user(cregs->y, (&pregs->y))) {
869                         pt_error_return(regs, EFAULT);
870                         goto out_tsk;
871                 }
872                 for (rval = 1; rval < 16; rval++)
873                         if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
874                                 pt_error_return(regs, EFAULT);
875                                 goto out_tsk;
876                         }
877                 pt_succ_return(regs, 0);
878                 goto out_tsk;
879         }
880
881         case PTRACE_GETREGS64: {
882                 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
883                 struct pt_regs *cregs = task_pt_regs(child);
884                 unsigned long tpc = cregs->tpc;
885                 int rval;
886
887                 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0)
888                         tpc &= 0xffffffff;
889                 if (__put_user(cregs->tstate, (&pregs->tstate)) ||
890                     __put_user(tpc, (&pregs->tpc)) ||
891                     __put_user(cregs->tnpc, (&pregs->tnpc)) ||
892                     __put_user(cregs->y, (&pregs->y))) {
893                         pt_error_return(regs, EFAULT);
894                         goto out_tsk;
895                 }
896                 for (rval = 1; rval < 16; rval++)
897                         if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
898                                 pt_error_return(regs, EFAULT);
899                                 goto out_tsk;
900                         }
901                 pt_succ_return(regs, 0);
902                 goto out_tsk;
903         }
904
905         case PTRACE_SETREGS: {
906                 struct pt_regs32 __user *pregs =
907                         (struct pt_regs32 __user *) addr;
908                 struct pt_regs *cregs = task_pt_regs(child);
909                 unsigned int psr, pc, npc, y;
910                 int i;
911
912                 /* Must be careful, tracing process can only set certain
913                  * bits in the psr.
914                  */
915                 if (__get_user(psr, (&pregs->psr)) ||
916                     __get_user(pc, (&pregs->pc)) ||
917                     __get_user(npc, (&pregs->npc)) ||
918                     __get_user(y, (&pregs->y))) {
919                         pt_error_return(regs, EFAULT);
920                         goto out_tsk;
921                 }
922                 cregs->tstate &= ~(TSTATE_ICC);
923                 cregs->tstate |= psr_to_tstate_icc(psr);
924                 if (!((pc | npc) & 3)) {
925                         cregs->tpc = pc;
926                         cregs->tnpc = npc;
927                 }
928                 cregs->y = y;
929                 for (i = 1; i < 16; i++) {
930                         if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
931                                 pt_error_return(regs, EFAULT);
932                                 goto out_tsk;
933                         }
934                 }
935                 pt_succ_return(regs, 0);
936                 goto out_tsk;
937         }
938
939         case PTRACE_SETREGS64: {
940                 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
941                 struct pt_regs *cregs = task_pt_regs(child);
942                 unsigned long tstate, tpc, tnpc, y;
943                 int i;
944
945                 /* Must be careful, tracing process can only set certain
946                  * bits in the psr.
947                  */
948                 if (__get_user(tstate, (&pregs->tstate)) ||
949                     __get_user(tpc, (&pregs->tpc)) ||
950                     __get_user(tnpc, (&pregs->tnpc)) ||
951                     __get_user(y, (&pregs->y))) {
952                         pt_error_return(regs, EFAULT);
953                         goto out_tsk;
954                 }
955                 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) {
956                         tpc &= 0xffffffff;
957                         tnpc &= 0xffffffff;
958                 }
959                 tstate &= (TSTATE_ICC | TSTATE_XCC);
960                 cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
961                 cregs->tstate |= tstate;
962                 if (!((tpc | tnpc) & 3)) {
963                         cregs->tpc = tpc;
964                         cregs->tnpc = tnpc;
965                 }
966                 cregs->y = y;
967                 for (i = 1; i < 16; i++) {
968                         if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
969                                 pt_error_return(regs, EFAULT);
970                                 goto out_tsk;
971                         }
972                 }
973                 pt_succ_return(regs, 0);
974                 goto out_tsk;
975         }
976
977         case PTRACE_GETFPREGS: {
978                 struct fps {
979                         unsigned int regs[32];
980                         unsigned int fsr;
981                         unsigned int flags;
982                         unsigned int extra;
983                         unsigned int fpqd;
984                         struct fq {
985                                 unsigned int insnaddr;
986                                 unsigned int insn;
987                         } fpq[16];
988                 };
989                 struct fps __user *fps = (struct fps __user *) addr;
990                 unsigned long *fpregs = task_thread_info(child)->fpregs;
991
992                 if (copy_to_user(&fps->regs[0], fpregs,
993                                  (32 * sizeof(unsigned int))) ||
994                     __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) ||
995                     __put_user(0, (&fps->fpqd)) ||
996                     __put_user(0, (&fps->flags)) ||
997                     __put_user(0, (&fps->extra)) ||
998                     clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) {
999                         pt_error_return(regs, EFAULT);
1000                         goto out_tsk;
1001                 }
1002                 pt_succ_return(regs, 0);
1003                 goto out_tsk;
1004         }
1005
1006         case PTRACE_GETFPREGS64: {
1007                 struct fps {
1008                         unsigned int regs[64];
1009                         unsigned long fsr;
1010                 };
1011                 struct fps __user *fps = (struct fps __user *) addr;
1012                 unsigned long *fpregs = task_thread_info(child)->fpregs;
1013
1014                 if (copy_to_user(&fps->regs[0], fpregs,
1015                                  (64 * sizeof(unsigned int))) ||
1016                     __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) {
1017                         pt_error_return(regs, EFAULT);
1018                         goto out_tsk;
1019                 }
1020                 pt_succ_return(regs, 0);
1021                 goto out_tsk;
1022         }
1023
1024         case PTRACE_SETFPREGS: {
1025                 struct fps {
1026                         unsigned int regs[32];
1027                         unsigned int fsr;
1028                         unsigned int flags;
1029                         unsigned int extra;
1030                         unsigned int fpqd;
1031                         struct fq {
1032                                 unsigned int insnaddr;
1033                                 unsigned int insn;
1034                         } fpq[16];
1035                 };
1036                 struct fps __user *fps = (struct fps __user *) addr;
1037                 unsigned long *fpregs = task_thread_info(child)->fpregs;
1038                 unsigned fsr;
1039
1040                 if (copy_from_user(fpregs, &fps->regs[0],
1041                                    (32 * sizeof(unsigned int))) ||
1042                     __get_user(fsr, (&fps->fsr))) {
1043                         pt_error_return(regs, EFAULT);
1044                         goto out_tsk;
1045                 }
1046                 task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL;
1047                 task_thread_info(child)->xfsr[0] |= fsr;
1048                 if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
1049                         task_thread_info(child)->gsr[0] = 0;
1050                 task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL);
1051                 pt_succ_return(regs, 0);
1052                 goto out_tsk;
1053         }
1054
1055         case PTRACE_SETFPREGS64: {
1056                 struct fps {
1057                         unsigned int regs[64];
1058                         unsigned long fsr;
1059                 };
1060                 struct fps __user *fps = (struct fps __user *) addr;
1061                 unsigned long *fpregs = task_thread_info(child)->fpregs;
1062
1063                 if (copy_from_user(fpregs, &fps->regs[0],
1064                                    (64 * sizeof(unsigned int))) ||
1065                     __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) {
1066                         pt_error_return(regs, EFAULT);
1067                         goto out_tsk;
1068                 }
1069                 if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
1070                         task_thread_info(child)->gsr[0] = 0;
1071                 task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU);
1072                 pt_succ_return(regs, 0);
1073                 goto out_tsk;
1074         }
1075
1076         case PTRACE_READTEXT:
1077         case PTRACE_READDATA: {
1078                 int res = ptrace_readdata(child, addr,
1079                                           (char __user *)addr2, data);
1080                 if (res == data) {
1081                         pt_succ_return(regs, 0);
1082                         goto out_tsk;
1083                 }
1084                 if (res >= 0)
1085                         res = -EIO;
1086                 pt_error_return(regs, -res);
1087                 goto out_tsk;
1088         }
1089
1090         case PTRACE_WRITETEXT:
1091         case PTRACE_WRITEDATA: {
1092                 int res = ptrace_writedata(child, (char __user *) addr2,
1093                                            addr, data);
1094                 if (res == data) {
1095                         pt_succ_return(regs, 0);
1096                         goto out_tsk;
1097                 }
1098                 if (res >= 0)
1099                         res = -EIO;
1100                 pt_error_return(regs, -res);
1101                 goto out_tsk;
1102         }
1103         case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
1104                 addr = 1;
1105
1106         case PTRACE_CONT: { /* restart after signal. */
1107                 if (!valid_signal(data)) {
1108                         pt_error_return(regs, EIO);
1109                         goto out_tsk;
1110                 }
1111
1112                 if (request == PTRACE_SYSCALL) {
1113                         set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
1114                 } else {
1115                         clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
1116                 }
1117
1118                 child->exit_code = data;
1119                 wake_up_process(child);
1120                 pt_succ_return(regs, 0);
1121                 goto out_tsk;
1122         }
1123
1124 /*
1125  * make the child exit.  Best I can do is send it a sigkill. 
1126  * perhaps it should be put in the status that it wants to 
1127  * exit.
1128  */
1129         case PTRACE_KILL: {
1130                 if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
1131                         pt_succ_return(regs, 0);
1132                         goto out_tsk;
1133                 }
1134                 child->exit_code = SIGKILL;
1135                 wake_up_process(child);
1136                 pt_succ_return(regs, 0);
1137                 goto out_tsk;
1138         }
1139
1140         case PTRACE_SUNDETACH: { /* detach a process that was attached. */
1141                 int error = ptrace_detach(child, data);
1142                 if (error) {
1143                         pt_error_return(regs, EIO);
1144                         goto out_tsk;
1145                 }
1146                 pt_succ_return(regs, 0);
1147                 goto out_tsk;
1148         }
1149
1150         /* PTRACE_DUMPCORE unsupported... */
1151
1152         case PTRACE_GETEVENTMSG: {
1153                 int err;
1154
1155                 if (test_thread_flag(TIF_32BIT))
1156                         err = put_user(child->ptrace_message,
1157                                        (unsigned int __user *) data);
1158                 else
1159                         err = put_user(child->ptrace_message,
1160                                        (unsigned long __user *) data);
1161                 if (err)
1162                         pt_error_return(regs, -err);
1163                 else
1164                         pt_succ_return(regs, 0);
1165                 break;
1166         }
1167
1168         default: {
1169                 int err = ptrace_request(child, request, addr, data);
1170                 if (err)
1171                         pt_error_return(regs, -err);
1172                 else
1173                         pt_succ_return(regs, 0);
1174                 goto out_tsk;
1175         }
1176         }
1177 out_tsk:
1178         if (child)
1179                 put_task_struct(child);
1180 out:
1181         unlock_kernel();
1182 }
1183
1184 asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
1185 {
1186         /* do the secure computing check first */
1187         secure_computing(regs->u_regs[UREG_G1]);
1188
1189         if (unlikely(current->audit_context) && syscall_exit_p) {
1190                 unsigned long tstate = regs->tstate;
1191                 int result = AUDITSC_SUCCESS;
1192
1193                 if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
1194                         result = AUDITSC_FAILURE;
1195
1196                 audit_syscall_exit(result, regs->u_regs[UREG_I0]);
1197         }
1198
1199         if (!(current->ptrace & PT_PTRACED))
1200                 goto out;
1201
1202         if (!test_thread_flag(TIF_SYSCALL_TRACE))
1203                 goto out;
1204
1205         ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
1206                                  ? 0x80 : 0));
1207
1208         /*
1209          * this isn't the same as continuing with a signal, but it will do
1210          * for normal use.  strace only continues with a signal if the
1211          * stopping signal is not SIGTRAP.  -brl
1212          */
1213         if (current->exit_code) {
1214                 send_sig(current->exit_code, current, 1);
1215                 current->exit_code = 0;
1216         }
1217
1218 out:
1219         if (unlikely(current->audit_context) && !syscall_exit_p)
1220                 audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
1221                                      AUDIT_ARCH_SPARC :
1222                                      AUDIT_ARCH_SPARC64),
1223                                     regs->u_regs[UREG_G1],
1224                                     regs->u_regs[UREG_I0],
1225                                     regs->u_regs[UREG_I1],
1226                                     regs->u_regs[UREG_I2],
1227                                     regs->u_regs[UREG_I3]);
1228 }