1 /* ptrace.c: Sparc process tracing support.
3 * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
6 * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
9 * Added Linux support -miguel (weird, eh?, the original code was meant
13 #include <linux/kernel.h>
14 #include <linux/sched.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>
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>
37 #include <asm/cpudata.h>
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.
44 static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
46 regs->u_regs[UREG_I0] = error;
47 regs->tstate |= (TSTATE_ICARRY | TSTATE_XCARRY);
48 regs->tpc = regs->tnpc;
52 static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
54 regs->u_regs[UREG_I0] = value;
55 regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
56 regs->tpc = regs->tnpc;
61 pt_succ_return_linux(struct pt_regs *regs, unsigned long value, void __user *addr)
63 if (test_thread_flag(TIF_32BIT)) {
64 if (put_user(value, (unsigned int __user *) addr)) {
65 pt_error_return(regs, EFAULT);
69 if (put_user(value, (long __user *) addr)) {
70 pt_error_return(regs, EFAULT);
74 regs->u_regs[UREG_I0] = 0;
75 regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
76 regs->tpc = regs->tnpc;
81 pt_os_succ_return (struct pt_regs *regs, unsigned long val, void __user *addr)
83 if (current->personality == PER_SUNOS)
84 pt_succ_return (regs, val);
86 pt_succ_return_linux (regs, val, addr);
89 /* #define ALLOW_INIT_TRACING */
92 * Called by kernel/ptrace.c when detaching..
94 * Make sure single step bits etc are not set.
96 void ptrace_disable(struct task_struct *child)
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.
106 * Now, the only thing we have to do is:
107 * 1) flush the D-cache if it's possible than an illegal alias
109 * 2) flush the I-cache if this is pre-cheetah and we did a write
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)
115 BUG_ON(len > PAGE_SIZE);
117 if (tlb_type == hypervisor)
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
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;
131 dcache_line_size = local_cpu_data().dcache_line_size;
133 if (tlb_type == spitfire) {
134 for (; start < end; start += dcache_line_size)
135 spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
137 start &= ~(dcache_line_size - 1);
138 for (; start < end; start += dcache_line_size)
139 __asm__ __volatile__(
140 "stxa %%g0, [%0] %1\n\t"
144 "i" (ASI_DCACHE_INVALIDATE));
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;
153 icache_line_size = local_cpu_data().icache_line_size;
155 for (; start < end; start += icache_line_size)
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)
170 const struct pt_regs *regs = task_pt_regs(target);
173 if (target == current)
176 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
178 0, 16 * sizeof(u64));
180 unsigned long __user *reg_window = (unsigned long __user *)
181 (regs->u_regs[UREG_I6] + STACK_BIAS);
182 unsigned long window[16];
184 if (copy_from_user(window, reg_window, sizeof(window)))
187 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
194 /* TSTATE, TPC, TNPC */
195 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
202 unsigned long y = regs->y;
204 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
211 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
212 36 * sizeof(u64), -1);
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)
222 struct pt_regs *regs = task_pt_regs(target);
225 if (target == current)
228 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
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];
236 if (copy_from_user(window, reg_window, sizeof(window)))
239 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
244 copy_to_user(reg_window, window, sizeof(window)))
248 if (!ret && count > 0) {
249 unsigned long tstate;
252 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
257 /* Only the condition codes can be modified
258 * in the %tstate register.
260 tstate &= (TSTATE_ICC | TSTATE_XCC);
261 regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
262 regs->tstate |= tstate;
268 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
277 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
286 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
287 36 * sizeof(u64), -1);
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)
297 const unsigned long *fpregs = task_thread_info(target)->fpregs;
298 unsigned long fprs, fsr, gsr;
301 if (target == current)
302 save_and_clear_fpu();
304 fprs = task_thread_info(target)->fpsaved[0];
307 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
309 0, 16 * sizeof(u64));
311 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
317 ret = user_regset_copyout(&pos, &count,
323 ret = user_regset_copyout_zero(&pos, &count,
329 if (fprs & FPRS_FEF) {
330 fsr = task_thread_info(target)->xfsr[0];
331 gsr = task_thread_info(target)->gsr[0];
337 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
342 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
347 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
353 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
354 35 * sizeof(u64), -1);
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)
364 unsigned long *fpregs = task_thread_info(target)->fpregs;
368 if (target == current)
369 save_and_clear_fpu();
371 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
373 0, 32 * sizeof(u64));
375 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
376 task_thread_info(target)->xfsr,
380 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
381 task_thread_info(target)->gsr,
385 fprs = task_thread_info(target)->fpsaved[0];
386 if (!ret && count > 0) {
387 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
393 fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU);
394 task_thread_info(target)->fpsaved[0] = fprs;
397 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
398 35 * sizeof(u64), -1);
402 static const struct user_regset sparc64_regsets[] = {
408 * TSTATE, TPC, TNPC, Y
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
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
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)
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)
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;
446 if (target == current)
450 count /= sizeof(reg);
453 for (; count > 0 && pos < 16; count--)
454 *k++ = regs->u_regs[pos++];
456 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
457 for (; count > 0 && pos < 32; count--) {
458 if (get_user(*k++, ®_window[pos++]))
462 for (; count > 0 && pos < 16; count--) {
463 if (put_user((compat_ulong_t) regs->u_regs[pos++], u++))
467 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
468 for (; count > 0 && pos < 32; count--) {
469 if (get_user(reg, ®_window[pos++]) ||
477 reg = tstate_to_psr(regs->tstate);
498 else if (put_user(reg, u++))
505 count *= sizeof(reg);
507 return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
508 38 * sizeof(reg), -1);
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)
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;
522 if (target == current)
526 count /= sizeof(reg);
529 for (; count > 0 && pos < 16; count--)
530 regs->u_regs[pos++] = *k++;
532 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
533 for (; count > 0 && pos < 32; count--) {
534 if (put_user(*k++, ®_window[pos++]))
538 for (; count > 0 && pos < 16; count--) {
539 if (get_user(reg, u++))
541 regs->u_regs[pos++] = reg;
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, ®_window[pos++]))
552 unsigned long tstate;
556 else if (get_user(reg, u++))
561 tstate = regs->tstate;
562 tstate &= ~(TSTATE_ICC | TSTATE_XCC);
563 tstate |= psr_to_tstate_icc(reg);
564 regs->tstate = tstate;
587 count *= sizeof(reg);
589 return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
590 38 * sizeof(reg), -1);
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)
598 const unsigned long *fpregs = task_thread_info(target)->fpregs;
599 compat_ulong_t enabled;
604 if (target == current)
605 save_and_clear_fpu();
607 fprs = task_thread_info(target)->fpsaved[0];
608 if (fprs & FPRS_FEF) {
609 fsr = task_thread_info(target)->xfsr[0];
616 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
618 0, 32 * sizeof(u32));
621 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
625 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
633 val = (enabled << 8) | (8 << 16);
634 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
641 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
642 35 * sizeof(u32), -1);
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)
652 unsigned long *fpregs = task_thread_info(target)->fpregs;
656 if (target == current)
657 save_and_clear_fpu();
659 fprs = task_thread_info(target)->fpsaved[0];
661 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
663 0, 32 * sizeof(u32));
665 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
668 if (!ret && count > 0) {
672 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
677 val = task_thread_info(target)->xfsr[0];
678 val &= 0xffffffff00000000UL;
680 task_thread_info(target)->xfsr[0] = val;
684 fprs |= (FPRS_FEF | FPRS_DL);
685 task_thread_info(target)->fpsaved[0] = fprs;
688 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
689 34 * sizeof(u32), -1);
693 static const struct user_regset sparc32_regsets[] = {
699 * PSR, PC, nPC, Y, WIM, TBR
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
711 * FPU QUEUE COUNT (8-bit char)
712 * FPU QUEUE ENTRYSIZE (8-bit char)
713 * FPU ENABLED (8-bit char)
715 * FPU QUEUE (64 32-bit ints)
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
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)
730 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
732 if (test_tsk_thread_flag(task, TIF_32BIT))
733 return &user_sparc32_view;
734 return &user_sparc64_view;
737 asmlinkage void do_ptrace(struct pt_regs *regs)
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;
747 if (test_thread_flag(TIF_32BIT)) {
748 addr &= 0xffffffffUL;
749 data &= 0xffffffffUL;
750 addr2 &= 0xffffffffUL;
753 if (request == PTRACE_TRACEME) {
754 ret = ptrace_traceme();
756 pt_error_return(regs, -ret);
758 pt_succ_return(regs, 0);
762 child = ptrace_get_task_struct(pid);
764 ret = PTR_ERR(child);
765 pt_error_return(regs, -ret);
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);
775 pt_succ_return(regs, 0);
779 ret = ptrace_check_attach(child, request == PTRACE_KILL);
781 pt_error_return(regs, -ret);
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... */
802 pt_error_return(regs, EIO);
804 pt_succ_return(regs, 0);
807 case PTRACE_PEEKTEXT: /* read word at location addr. */
808 case PTRACE_PEEKDATA: {
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))
821 copied = access_process_vm(child, addr,
822 &tmp64, sizeof(tmp64), 0);
823 if (copied == sizeof(tmp64))
827 pt_error_return(regs, -res);
829 pt_os_succ_return(regs, tmp64, (void __user *) data);
833 case PTRACE_POKETEXT: /* write the word at location addr. */
834 case PTRACE_POKEDATA: {
837 int copied, res = -EIO;
839 if (test_thread_flag(TIF_32BIT)) {
841 copied = access_process_vm(child, addr,
842 &tmp32, sizeof(tmp32), 1);
843 if (copied == sizeof(tmp32))
847 copied = access_process_vm(child, addr,
848 &tmp64, sizeof(tmp64), 1);
849 if (copied == sizeof(tmp64))
853 pt_error_return(regs, -res);
855 pt_succ_return(regs, res);
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);
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);
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);
877 pt_succ_return(regs, 0);
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;
887 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0)
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);
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);
901 pt_succ_return(regs, 0);
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;
912 /* Must be careful, tracing process can only set certain
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);
922 cregs->tstate &= ~(TSTATE_ICC);
923 cregs->tstate |= psr_to_tstate_icc(psr);
924 if (!((pc | npc) & 3)) {
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);
935 pt_succ_return(regs, 0);
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;
945 /* Must be careful, tracing process can only set certain
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);
955 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) {
959 tstate &= (TSTATE_ICC | TSTATE_XCC);
960 cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
961 cregs->tstate |= tstate;
962 if (!((tpc | tnpc) & 3)) {
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);
973 pt_succ_return(regs, 0);
977 case PTRACE_GETFPREGS: {
979 unsigned int regs[32];
985 unsigned int insnaddr;
989 struct fps __user *fps = (struct fps __user *) addr;
990 unsigned long *fpregs = task_thread_info(child)->fpregs;
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);
1002 pt_succ_return(regs, 0);
1006 case PTRACE_GETFPREGS64: {
1008 unsigned int regs[64];
1011 struct fps __user *fps = (struct fps __user *) addr;
1012 unsigned long *fpregs = task_thread_info(child)->fpregs;
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);
1020 pt_succ_return(regs, 0);
1024 case PTRACE_SETFPREGS: {
1026 unsigned int regs[32];
1032 unsigned int insnaddr;
1036 struct fps __user *fps = (struct fps __user *) addr;
1037 unsigned long *fpregs = task_thread_info(child)->fpregs;
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);
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);
1055 case PTRACE_SETFPREGS64: {
1057 unsigned int regs[64];
1060 struct fps __user *fps = (struct fps __user *) addr;
1061 unsigned long *fpregs = task_thread_info(child)->fpregs;
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);
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);
1076 case PTRACE_READTEXT:
1077 case PTRACE_READDATA: {
1078 int res = ptrace_readdata(child, addr,
1079 (char __user *)addr2, data);
1081 pt_succ_return(regs, 0);
1086 pt_error_return(regs, -res);
1090 case PTRACE_WRITETEXT:
1091 case PTRACE_WRITEDATA: {
1092 int res = ptrace_writedata(child, (char __user *) addr2,
1095 pt_succ_return(regs, 0);
1100 pt_error_return(regs, -res);
1103 case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
1106 case PTRACE_CONT: { /* restart after signal. */
1107 if (!valid_signal(data)) {
1108 pt_error_return(regs, EIO);
1112 if (request == PTRACE_SYSCALL) {
1113 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
1115 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
1118 child->exit_code = data;
1119 wake_up_process(child);
1120 pt_succ_return(regs, 0);
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
1130 if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
1131 pt_succ_return(regs, 0);
1134 child->exit_code = SIGKILL;
1135 wake_up_process(child);
1136 pt_succ_return(regs, 0);
1140 case PTRACE_SUNDETACH: { /* detach a process that was attached. */
1141 int error = ptrace_detach(child, data);
1143 pt_error_return(regs, EIO);
1146 pt_succ_return(regs, 0);
1150 /* PTRACE_DUMPCORE unsupported... */
1152 case PTRACE_GETEVENTMSG: {
1155 if (test_thread_flag(TIF_32BIT))
1156 err = put_user(child->ptrace_message,
1157 (unsigned int __user *) data);
1159 err = put_user(child->ptrace_message,
1160 (unsigned long __user *) data);
1162 pt_error_return(regs, -err);
1164 pt_succ_return(regs, 0);
1169 int err = ptrace_request(child, request, addr, data);
1171 pt_error_return(regs, -err);
1173 pt_succ_return(regs, 0);
1179 put_task_struct(child);
1184 asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
1186 /* do the secure computing check first */
1187 secure_computing(regs->u_regs[UREG_G1]);
1189 if (unlikely(current->audit_context) && syscall_exit_p) {
1190 unsigned long tstate = regs->tstate;
1191 int result = AUDITSC_SUCCESS;
1193 if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
1194 result = AUDITSC_FAILURE;
1196 audit_syscall_exit(result, regs->u_regs[UREG_I0]);
1199 if (!(current->ptrace & PT_PTRACED))
1202 if (!test_thread_flag(TIF_SYSCALL_TRACE))
1205 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
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
1213 if (current->exit_code) {
1214 send_sig(current->exit_code, current, 1);
1215 current->exit_code = 0;
1219 if (unlikely(current->audit_context) && !syscall_exit_p)
1220 audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
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]);