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>
38 #include <asm/cacheflush.h>
42 /* #define ALLOW_INIT_TRACING */
45 * Called by kernel/ptrace.c when detaching..
47 * Make sure single step bits etc are not set.
49 void ptrace_disable(struct task_struct *child)
54 /* To get the necessary page struct, access_process_vm() first calls
55 * get_user_pages(). This has done a flush_dcache_page() on the
56 * accessed page. Then our caller (copy_{to,from}_user_page()) did
57 * to memcpy to read/write the data from that page.
59 * Now, the only thing we have to do is:
60 * 1) flush the D-cache if it's possible than an illegal alias
62 * 2) flush the I-cache if this is pre-cheetah and we did a write
64 void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
65 unsigned long uaddr, void *kaddr,
66 unsigned long len, int write)
68 BUG_ON(len > PAGE_SIZE);
70 if (tlb_type == hypervisor)
75 #ifdef DCACHE_ALIASING_POSSIBLE
76 /* If bit 13 of the kernel address we used to access the
77 * user page is the same as the virtual address that page
78 * is mapped to in the user's address space, we can skip the
81 if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
82 unsigned long start = __pa(kaddr);
83 unsigned long end = start + len;
84 unsigned long dcache_line_size;
86 dcache_line_size = local_cpu_data().dcache_line_size;
88 if (tlb_type == spitfire) {
89 for (; start < end; start += dcache_line_size)
90 spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
92 start &= ~(dcache_line_size - 1);
93 for (; start < end; start += dcache_line_size)
95 "stxa %%g0, [%0] %1\n\t"
99 "i" (ASI_DCACHE_INVALIDATE));
103 if (write && tlb_type == spitfire) {
104 unsigned long start = (unsigned long) kaddr;
105 unsigned long end = start + len;
106 unsigned long icache_line_size;
108 icache_line_size = local_cpu_data().icache_line_size;
110 for (; start < end; start += icache_line_size)
122 static int genregs64_get(struct task_struct *target,
123 const struct user_regset *regset,
124 unsigned int pos, unsigned int count,
125 void *kbuf, void __user *ubuf)
127 const struct pt_regs *regs = task_pt_regs(target);
130 if (target == current)
133 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
135 0, 16 * sizeof(u64));
137 unsigned long __user *reg_window = (unsigned long __user *)
138 (regs->u_regs[UREG_I6] + STACK_BIAS);
139 unsigned long window[16];
141 if (copy_from_user(window, reg_window, sizeof(window)))
144 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
151 /* TSTATE, TPC, TNPC */
152 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
159 unsigned long y = regs->y;
161 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
168 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
169 36 * sizeof(u64), -1);
174 static int genregs64_set(struct task_struct *target,
175 const struct user_regset *regset,
176 unsigned int pos, unsigned int count,
177 const void *kbuf, const void __user *ubuf)
179 struct pt_regs *regs = task_pt_regs(target);
182 if (target == current)
185 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
187 0, 16 * sizeof(u64));
188 if (!ret && count > 0) {
189 unsigned long __user *reg_window = (unsigned long __user *)
190 (regs->u_regs[UREG_I6] + STACK_BIAS);
191 unsigned long window[16];
193 if (copy_from_user(window, reg_window, sizeof(window)))
196 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
201 copy_to_user(reg_window, window, sizeof(window)))
205 if (!ret && count > 0) {
206 unsigned long tstate;
209 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
214 /* Only the condition codes can be modified
215 * in the %tstate register.
217 tstate &= (TSTATE_ICC | TSTATE_XCC);
218 regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
219 regs->tstate |= tstate;
225 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
234 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
243 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
244 36 * sizeof(u64), -1);
249 static int fpregs64_get(struct task_struct *target,
250 const struct user_regset *regset,
251 unsigned int pos, unsigned int count,
252 void *kbuf, void __user *ubuf)
254 const unsigned long *fpregs = task_thread_info(target)->fpregs;
255 unsigned long fprs, fsr, gsr;
258 if (target == current)
259 save_and_clear_fpu();
261 fprs = task_thread_info(target)->fpsaved[0];
264 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
266 0, 16 * sizeof(u64));
268 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
274 ret = user_regset_copyout(&pos, &count,
280 ret = user_regset_copyout_zero(&pos, &count,
286 if (fprs & FPRS_FEF) {
287 fsr = task_thread_info(target)->xfsr[0];
288 gsr = task_thread_info(target)->gsr[0];
294 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
299 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
304 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
310 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
311 35 * sizeof(u64), -1);
316 static int fpregs64_set(struct task_struct *target,
317 const struct user_regset *regset,
318 unsigned int pos, unsigned int count,
319 const void *kbuf, const void __user *ubuf)
321 unsigned long *fpregs = task_thread_info(target)->fpregs;
325 if (target == current)
326 save_and_clear_fpu();
328 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
330 0, 32 * sizeof(u64));
332 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
333 task_thread_info(target)->xfsr,
337 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
338 task_thread_info(target)->gsr,
342 fprs = task_thread_info(target)->fpsaved[0];
343 if (!ret && count > 0) {
344 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
350 fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU);
351 task_thread_info(target)->fpsaved[0] = fprs;
354 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
355 35 * sizeof(u64), -1);
359 static const struct user_regset sparc64_regsets[] = {
365 * TSTATE, TPC, TNPC, Y
368 .core_note_type = NT_PRSTATUS,
369 .n = 36 * sizeof(u64),
370 .size = sizeof(u64), .align = sizeof(u64),
371 .get = genregs64_get, .set = genregs64_set
380 .core_note_type = NT_PRFPREG,
381 .n = 35 * sizeof(u64),
382 .size = sizeof(u64), .align = sizeof(u64),
383 .get = fpregs64_get, .set = fpregs64_set
387 static const struct user_regset_view user_sparc64_view = {
388 .name = "sparc64", .e_machine = EM_SPARCV9,
389 .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets)
393 static int genregs32_get(struct task_struct *target,
394 const struct user_regset *regset,
395 unsigned int pos, unsigned int count,
396 void *kbuf, void __user *ubuf)
398 const struct pt_regs *regs = task_pt_regs(target);
399 compat_ulong_t __user *reg_window;
400 compat_ulong_t *k = kbuf;
401 compat_ulong_t __user *u = ubuf;
404 if (target == current)
408 count /= sizeof(reg);
411 for (; count > 0 && pos < 16; count--)
412 *k++ = regs->u_regs[pos++];
414 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
415 for (; count > 0 && pos < 32; count--) {
416 if (get_user(*k++, ®_window[pos++]))
420 for (; count > 0 && pos < 16; count--) {
421 if (put_user((compat_ulong_t) regs->u_regs[pos++], u++))
425 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
426 for (; count > 0 && pos < 32; count--) {
427 if (get_user(reg, ®_window[pos++]) ||
435 reg = tstate_to_psr(regs->tstate);
456 else if (put_user(reg, u++))
463 count *= sizeof(reg);
465 return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
466 38 * sizeof(reg), -1);
469 static int genregs32_set(struct task_struct *target,
470 const struct user_regset *regset,
471 unsigned int pos, unsigned int count,
472 const void *kbuf, const void __user *ubuf)
474 struct pt_regs *regs = task_pt_regs(target);
475 compat_ulong_t __user *reg_window;
476 const compat_ulong_t *k = kbuf;
477 const compat_ulong_t __user *u = ubuf;
480 if (target == current)
484 count /= sizeof(reg);
487 for (; count > 0 && pos < 16; count--)
488 regs->u_regs[pos++] = *k++;
490 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
491 for (; count > 0 && pos < 32; count--) {
492 if (put_user(*k++, ®_window[pos++]))
496 for (; count > 0 && pos < 16; count--) {
497 if (get_user(reg, u++))
499 regs->u_regs[pos++] = reg;
502 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
503 for (; count > 0 && pos < 32; count--) {
504 if (get_user(reg, u++) ||
505 put_user(reg, ®_window[pos++]))
510 unsigned long tstate;
514 else if (get_user(reg, u++))
519 tstate = regs->tstate;
520 tstate &= ~(TSTATE_ICC | TSTATE_XCC);
521 tstate |= psr_to_tstate_icc(reg);
522 regs->tstate = tstate;
545 count *= sizeof(reg);
547 return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
548 38 * sizeof(reg), -1);
551 static int fpregs32_get(struct task_struct *target,
552 const struct user_regset *regset,
553 unsigned int pos, unsigned int count,
554 void *kbuf, void __user *ubuf)
556 const unsigned long *fpregs = task_thread_info(target)->fpregs;
557 compat_ulong_t enabled;
562 if (target == current)
563 save_and_clear_fpu();
565 fprs = task_thread_info(target)->fpsaved[0];
566 if (fprs & FPRS_FEF) {
567 fsr = task_thread_info(target)->xfsr[0];
574 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
576 0, 32 * sizeof(u32));
579 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
583 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
591 val = (enabled << 8) | (8 << 16);
592 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
599 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
600 35 * sizeof(u32), -1);
605 static int fpregs32_set(struct task_struct *target,
606 const struct user_regset *regset,
607 unsigned int pos, unsigned int count,
608 const void *kbuf, const void __user *ubuf)
610 unsigned long *fpregs = task_thread_info(target)->fpregs;
614 if (target == current)
615 save_and_clear_fpu();
617 fprs = task_thread_info(target)->fpsaved[0];
619 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
621 0, 32 * sizeof(u32));
623 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
626 if (!ret && count > 0) {
630 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
635 val = task_thread_info(target)->xfsr[0];
636 val &= 0xffffffff00000000UL;
638 task_thread_info(target)->xfsr[0] = val;
642 fprs |= (FPRS_FEF | FPRS_DL);
643 task_thread_info(target)->fpsaved[0] = fprs;
646 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
647 34 * sizeof(u32), -1);
651 static const struct user_regset sparc32_regsets[] = {
657 * PSR, PC, nPC, Y, WIM, TBR
660 .core_note_type = NT_PRSTATUS,
661 .n = 38 * sizeof(u32),
662 .size = sizeof(u32), .align = sizeof(u32),
663 .get = genregs32_get, .set = genregs32_set
669 * FPU QUEUE COUNT (8-bit char)
670 * FPU QUEUE ENTRYSIZE (8-bit char)
671 * FPU ENABLED (8-bit char)
673 * FPU QUEUE (64 32-bit ints)
676 .core_note_type = NT_PRFPREG,
677 .n = 99 * sizeof(u32),
678 .size = sizeof(u32), .align = sizeof(u32),
679 .get = fpregs32_get, .set = fpregs32_set
683 static const struct user_regset_view user_sparc32_view = {
684 .name = "sparc", .e_machine = EM_SPARC,
685 .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
687 #endif /* CONFIG_COMPAT */
689 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
692 if (test_tsk_thread_flag(task, TIF_32BIT))
693 return &user_sparc32_view;
695 return &user_sparc64_view;
700 unsigned int regs[32];
706 unsigned int insnaddr;
711 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
712 compat_ulong_t caddr, compat_ulong_t cdata)
714 const struct user_regset_view *view = task_user_regset_view(child);
715 compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4];
716 struct pt_regs32 __user *pregs;
717 struct compat_fps __user *fps;
718 unsigned long addr2 = caddr2;
719 unsigned long addr = caddr;
720 unsigned long data = cdata;
723 pregs = (struct pt_regs32 __user *) addr;
724 fps = (struct compat_fps __user *) addr;
728 ret = (addr != 0) ? -EIO : 0;
732 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
737 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
744 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
749 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
755 case PTRACE_GETFPREGS:
756 ret = copy_regset_to_user(child, view, REGSET_FP,
761 ret = copy_regset_to_user(child, view, REGSET_FP,
766 if (__put_user(0, &fps->flags) ||
767 __put_user(0, &fps->extra) ||
768 __put_user(0, &fps->fpqd) ||
769 clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
774 case PTRACE_SETFPREGS:
775 ret = copy_regset_from_user(child, view, REGSET_FP,
780 ret = copy_regset_from_user(child, view, REGSET_FP,
786 case PTRACE_READTEXT:
787 case PTRACE_READDATA:
788 ret = ptrace_readdata(child, addr,
789 (char __user *)addr2, data);
796 case PTRACE_WRITETEXT:
797 case PTRACE_WRITEDATA:
798 ret = ptrace_writedata(child, (char __user *) addr2,
807 ret = compat_ptrace_request(child, request, addr, data);
813 #endif /* CONFIG_COMPAT */
816 unsigned int regs[64];
820 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
822 const struct user_regset_view *view = task_user_regset_view(child);
823 unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
824 struct pt_regs __user *pregs;
825 struct fps __user *fps;
828 pregs = (struct pt_regs __user *) (unsigned long) addr;
829 fps = (struct fps __user *) (unsigned long) addr;
833 ret = (addr != 0) ? -EIO : 0;
836 case PTRACE_GETREGS64:
837 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
842 /* XXX doesn't handle 'y' register correctly XXX */
843 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
850 case PTRACE_SETREGS64:
851 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
856 /* XXX doesn't handle 'y' register correctly XXX */
857 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
864 case PTRACE_GETFPREGS64:
865 ret = copy_regset_to_user(child, view, REGSET_FP,
871 case PTRACE_SETFPREGS64:
872 ret = copy_regset_to_user(child, view, REGSET_FP,
878 case PTRACE_READTEXT:
879 case PTRACE_READDATA:
880 ret = ptrace_readdata(child, addr,
881 (char __user *)addr2, data);
888 case PTRACE_WRITETEXT:
889 case PTRACE_WRITEDATA:
890 ret = ptrace_writedata(child, (char __user *) addr2,
899 ret = ptrace_request(child, request, addr, data);
906 asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
908 /* do the secure computing check first */
909 secure_computing(regs->u_regs[UREG_G1]);
911 if (unlikely(current->audit_context) && syscall_exit_p) {
912 unsigned long tstate = regs->tstate;
913 int result = AUDITSC_SUCCESS;
915 if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
916 result = AUDITSC_FAILURE;
918 audit_syscall_exit(result, regs->u_regs[UREG_I0]);
921 if (!(current->ptrace & PT_PTRACED))
924 if (!test_thread_flag(TIF_SYSCALL_TRACE))
927 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
931 * this isn't the same as continuing with a signal, but it will do
932 * for normal use. strace only continues with a signal if the
933 * stopping signal is not SIGTRAP. -brl
935 if (current->exit_code) {
936 send_sig(current->exit_code, current, 1);
937 current->exit_code = 0;
941 if (unlikely(current->audit_context) && !syscall_exit_p)
942 audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
945 regs->u_regs[UREG_G1],
946 regs->u_regs[UREG_I0],
947 regs->u_regs[UREG_I1],
948 regs->u_regs[UREG_I2],
949 regs->u_regs[UREG_I3]);