1 /* ptrace.c: Sparc64 process tracing support.
3 * Copyright (C) 1996, 2006 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/module.h>
15 #include <linux/sched.h>
17 #include <linux/security.h>
18 #include <linux/seccomp.h>
19 #include <linux/audit.h>
20 #include <linux/tracehook.h>
21 #include <linux/elf.h>
22 #include <linux/ptrace.h>
25 #include <asm/pgtable.h>
26 #include <asm/system.h>
27 #include <asm/spitfire.h>
29 #include <asm/cpudata.h>
30 #include <asm/psrcompat.h>
36 #define GENREG_TSTATE 32
38 #define GENREG_TNPC 34
41 #define SPARC64_NGREGS 36
43 static int genregs_get(struct task_struct *target,
44 const struct utrace_regset *regset,
45 unsigned int pos, unsigned int count,
46 void *kbuf, void __user *ubuf)
48 struct pt_regs *regs = task_pt_regs(target);
51 err = utrace_regset_copyout(&pos, &count, &kbuf, &ubuf, regs->u_regs,
52 GENREG_G0 * 8, GENREG_L0 * 8);
54 if (err == 0 && count > 0 && pos < (GENREG_TSTATE * 8)) {
55 struct thread_info *t = task_thread_info(target);
56 unsigned long rwindow[16], fp, *win;
59 if (target == current)
62 wsaved = __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_WSAVED];
63 fp = regs->u_regs[UREG_FP] + STACK_BIAS;
64 if (wsaved && t->rwbuf_stkptrs[wsaved - 1] == fp)
65 win = &t->reg_window[wsaved - 1].locals[0];
67 if (target == current) {
68 if (copy_from_user(rwindow,
73 err = access_process_vm(target, fp, rwindow,
74 16 * sizeof(long), 0);
80 err = utrace_regset_copyout(&pos, &count, &kbuf, &ubuf,
86 err = utrace_regset_copyout(&pos, &count, &kbuf, &ubuf,
87 ®s->tstate, GENREG_TSTATE * 8,
89 if (err == 0 && count > 0) {
91 *(unsigned long *) kbuf = regs->y;
92 else if (put_user(regs->y, (unsigned long __user *) ubuf))
99 /* Consistent with signal handling, we only allow userspace to
100 * modify the %asi, %icc, and %xcc fields of the %tstate register.
102 #define TSTATE_DEBUGCHANGE (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)
104 static int genregs_set(struct task_struct *target,
105 const struct utrace_regset *regset,
106 unsigned int pos, unsigned int count,
107 const void *kbuf, const void __user *ubuf)
109 struct pt_regs *regs = task_pt_regs(target);
110 unsigned long tstate_save;
113 err = utrace_regset_copyin(&pos, &count, &kbuf, &ubuf, regs->u_regs,
114 GENREG_G0 * 8, GENREG_L0 * 8);
116 if (err == 0 && count > 0 && pos < (GENREG_TSTATE * 8)) {
117 unsigned long fp = regs->u_regs[UREG_FP] + STACK_BIAS;
118 unsigned long rwindow[16], *winbuf;
119 unsigned int copy = (GENREG_TSTATE * 8) - pos;
123 if (target == current)
128 off = pos - (GENREG_L0 * 8);
131 winbuf = (unsigned long *) kbuf;
136 if (copy_from_user(winbuf, ubuf, copy))
143 if (target == current)
144 err = copy_to_user((void __user *) fp + off,
147 err = access_process_vm(target, fp + off,
151 tstate_save = regs->tstate &~ TSTATE_DEBUGCHANGE;
154 err = utrace_regset_copyin(&pos, &count, &kbuf, &ubuf,
155 ®s->tstate, GENREG_TSTATE * 8,
158 regs->tstate &= TSTATE_DEBUGCHANGE;
159 regs->tstate |= tstate_save;
161 if (err == 0 && count > 0) {
163 regs->y = *(unsigned long *) kbuf;
164 else if (get_user(regs->y, (unsigned long __user *) ubuf))
174 #define FPREG_FPRS 34
176 #define SPARC64_NFPREGS 35
178 static int fpregs_get(struct task_struct *target,
179 const struct utrace_regset *regset,
180 unsigned int pos, unsigned int count,
181 void *kbuf, void __user *ubuf)
183 struct thread_info *t = task_thread_info(target);
186 err = utrace_regset_copyout(&pos, &count, &kbuf, &ubuf,
187 t->fpregs, FPREG_F0 * 8, FPREG_FSR * 8);
190 err = utrace_regset_copyout(&pos, &count, &kbuf, &ubuf,
191 &t->xfsr[0], FPREG_FSR * 8,
195 err = utrace_regset_copyout(&pos, &count, &kbuf, &ubuf,
196 &t->gsr[0], FPREG_GSR * 8,
199 if (err == 0 && count > 0) {
200 struct pt_regs *regs = task_pt_regs(target);
203 *(unsigned long *) kbuf = regs->fprs;
204 else if (put_user(regs->fprs, (unsigned long __user *) ubuf))
207 if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT)) {
208 pt_error_return(regs, ESRCH);
215 static int fpregs_set(struct task_struct *target,
216 const struct utrace_regset *regset,
217 unsigned int pos, unsigned int count,
218 const void *kbuf, const void __user *ubuf)
220 struct thread_info *t = task_thread_info(target);
223 err = utrace_regset_copyin(&pos, &count, &kbuf, &ubuf,
224 t->fpregs, FPREG_F0 * 8, FPREG_FSR * 8);
227 err = utrace_regset_copyin(&pos, &count, &kbuf, &ubuf,
228 &t->xfsr[0], FPREG_FSR * 8,
232 err = utrace_regset_copyin(&pos, &count, &kbuf, &ubuf,
233 &t->gsr[0], FPREG_GSR * 8,
236 if (err == 0 && count > 0) {
237 struct pt_regs *regs = task_pt_regs(target);
240 regs->fprs = *(unsigned long *) kbuf;
241 else if (get_user(regs->fprs, (unsigned long __user *) ubuf))
248 static const struct utrace_regset native_regsets[] = {
251 .size = sizeof(long), .align = sizeof(long),
252 .get = genregs_get, .set = genregs_set
255 .n = SPARC64_NFPREGS,
256 .size = sizeof(long), .align = sizeof(long),
257 .get = fpregs_get, .set = fpregs_set
261 const struct utrace_regset_view utrace_sparc64_native_view = {
262 .name = UTS_MACHINE, .e_machine = ELF_ARCH,
263 .regsets = native_regsets,
264 .n = sizeof native_regsets / sizeof native_regsets[0],
266 EXPORT_SYMBOL_GPL(utrace_sparc64_native_view);
270 #define GENREG32_G0 0
271 #define GENREG32_O0 8
272 #define GENREG32_L0 16
273 #define GENREG32_I0 24
274 #define GENREG32_PSR 32
275 #define GENREG32_PC 33
276 #define GENREG32_NPC 34
277 #define GENREG32_Y 35
278 #define GENREG32_WIM 36
279 #define GENREG32_TBR 37
281 #define SPARC32_NGREGS 38
283 static int genregs32_get(struct task_struct *target,
284 const struct utrace_regset *regset,
285 unsigned int pos, unsigned int count,
286 void *kbuf, void __user *ubuf)
288 struct pt_regs *regs = task_pt_regs(target);
290 while (count > 0 && pos < (GENREG32_L0 * 4)) {
291 u32 val = regs->u_regs[(pos - (GENREG32_G0*4))/sizeof(u32)];
295 } else if (put_user(val, (u32 __user *) ubuf))
300 count -= sizeof(u32);
303 if (count > 0 && pos < (GENREG32_PSR * 4)) {
304 struct thread_info *t = task_thread_info(target);
309 if (target == current)
312 wsaved = __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_WSAVED];
313 fp = regs->u_regs[UREG_FP] & 0xffffffffUL;
314 if (wsaved && t->rwbuf_stkptrs[wsaved - 1] == fp) {
316 for (i = 0; i < 8; i++)
318 t->reg_window[wsaved-1].locals[i];
319 for (i = 0; i < 8; i++)
321 t->reg_window[wsaved-1].ins[i];
325 if (target == current) {
327 if (copy_from_user(rwindow, (void __user *) fp,
331 err = access_process_vm(target, fp, rwindow,
332 16 * sizeof(u32), 0);
337 while (count > 0 && pos < (GENREG32_PSR * 4)) {
338 u32 val = rwindow[(pos - (GENREG32_L0*4))/sizeof(u32)];
343 } else if (put_user(val, (u32 __user *) ubuf))
348 count -= sizeof(u32);
352 if (count > 0 && pos == (GENREG32_PSR * 4)) {
353 u32 psr = tstate_to_psr(regs->tstate);
358 } else if (put_user(psr, (u32 __user *) ubuf))
363 count -= sizeof(u32);
366 if (count > 0 && pos == (GENREG32_PC * 4)) {
372 } else if (put_user(val, (u32 __user *) ubuf))
377 count -= sizeof(u32);
380 if (count > 0 && pos == (GENREG32_NPC * 4)) {
381 u32 val = regs->tnpc;
386 } else if (put_user(val, (u32 __user *) ubuf))
391 count -= sizeof(u32);
394 if (count > 0 && pos == (GENREG32_Y * 4)) {
396 *(u32 *) kbuf = regs->y;
398 } else if (put_user(regs->y, (u32 __user *) ubuf))
403 count -= sizeof(u32);
408 memset(kbuf, 0, count);
409 else if (clear_user(ubuf, count))
416 static int genregs32_set(struct task_struct *target,
417 const struct utrace_regset *regset,
418 unsigned int pos, unsigned int count,
419 const void *kbuf, const void __user *ubuf)
421 struct pt_regs *regs = task_pt_regs(target);
423 while (count > 0 && pos < (GENREG32_L0 * 4)) {
425 loc = ®s->u_regs[(pos - (GENREG32_G0*4))/sizeof(u32)];
427 *loc = *(u32 *) kbuf;
429 } else if (get_user(*loc, (u32 __user *) ubuf))
434 count -= sizeof(u32);
437 if (count > 0 && pos < (GENREG32_PSR * 4)) {
440 unsigned int off, copy;
443 if (target == current)
446 copy = (GENREG32_PSR * 4) - pos;
449 BUG_ON(copy > 16 * sizeof(u32));
451 fp = regs->u_regs[UREG_FP] & 0xffffffffUL;
452 off = pos - (GENREG32_L0 * 4);
454 memcpy(regbuf, kbuf, copy);
456 } else if (copy_from_user(regbuf, ubuf, copy))
463 if (target == current) {
465 if (copy_to_user((void __user *) fp + off,
469 err = access_process_vm(target, fp + off,
475 if (count > 0 && pos == (GENREG32_PSR * 4)) {
476 unsigned long tstate, tstate_save;
479 tstate_save = regs->tstate&~(TSTATE_ICC|TSTATE_XCC);
484 } else if (get_user(psr, (u32 __user *) ubuf))
489 count -= sizeof(u32);
491 tstate = psr_to_tstate_icc(psr);
492 regs->tstate = tstate_save | tstate;
495 if (count > 0 && pos == (GENREG32_PC * 4)) {
497 regs->tpc = *(u32 *) kbuf;
499 } else if (get_user(regs->tpc, (u32 __user *) ubuf))
504 count -= sizeof(u32);
507 if (count > 0 && pos == (GENREG32_NPC * 4)) {
509 regs->tnpc = *(u32 *) kbuf;
511 } else if (get_user(regs->tnpc, (u32 __user *) ubuf))
516 count -= sizeof(u32);
519 if (count > 0 && pos == (GENREG32_Y * 4)) {
521 regs->y = *(u32 *) kbuf;
523 } else if (get_user(regs->y, (u32 __user *) ubuf))
528 count -= sizeof(u32);
531 /* Ignore WIM and TBR */
537 #define FPREG32_FSR 32
539 #define SPARC32_NFPREGS 33
541 static int fpregs32_get(struct task_struct *target,
542 const struct utrace_regset *regset,
543 unsigned int pos, unsigned int count,
544 void *kbuf, void __user *ubuf)
546 struct thread_info *t = task_thread_info(target);
549 err = utrace_regset_copyout(&pos, &count, &kbuf, &ubuf,
550 t->fpregs, FPREG32_F0 * 4,
553 if (err == 0 && count > 0) {
555 *(u32 *) kbuf = t->xfsr[0];
556 } else if (put_user(t->xfsr[0], (u32 __user *) ubuf))
563 static int fpregs32_set(struct task_struct *target,
564 const struct utrace_regset *regset,
565 unsigned int pos, unsigned int count,
566 const void *kbuf, const void __user *ubuf)
568 struct thread_info *t = task_thread_info(target);
571 err = utrace_regset_copyin(&pos, &count, &kbuf, &ubuf,
572 t->fpregs, FPREG32_F0 * 4,
575 if (err == 0 && count > 0) {
579 } else if (get_user(fsr, (u32 __user *) ubuf))
581 t->xfsr[0] = (t->xfsr[0] & 0xffffffff00000000UL) | fsr;
587 static const struct utrace_regset sparc32_regsets[] = {
590 .size = sizeof(u32), .align = sizeof(u32),
591 .get = genregs32_get, .set = genregs32_set
594 .n = SPARC32_NFPREGS,
595 .size = sizeof(u32), .align = sizeof(u32),
596 .get = fpregs32_get, .set = fpregs32_set
600 const struct utrace_regset_view utrace_sparc32_view = {
601 .name = "sparc", .e_machine = EM_SPARC,
602 .regsets = sparc32_regsets,
603 .n = sizeof sparc32_regsets / sizeof sparc32_regsets[0],
605 EXPORT_SYMBOL_GPL(utrace_sparc32_view);
607 #endif /* CONFIG_COMPAT */
609 /* To get the necessary page struct, access_process_vm() first calls
610 * get_user_pages(). This has done a flush_dcache_page() on the
611 * accessed page. Then our caller (copy_{to,from}_user_page()) did
612 * to memcpy to read/write the data from that page.
614 * Now, the only thing we have to do is:
615 * 1) flush the D-cache if it's possible than an illegal alias
617 * 2) flush the I-cache if this is pre-cheetah and we did a write
619 void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
620 unsigned long uaddr, void *kaddr,
621 unsigned long len, int write)
623 BUG_ON(len > PAGE_SIZE);
625 if (tlb_type == hypervisor)
628 #ifdef DCACHE_ALIASING_POSSIBLE
629 /* If bit 13 of the kernel address we used to access the
630 * user page is the same as the virtual address that page
631 * is mapped to in the user's address space, we can skip the
634 if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
635 unsigned long start = __pa(kaddr);
636 unsigned long end = start + len;
637 unsigned long dcache_line_size;
639 dcache_line_size = local_cpu_data().dcache_line_size;
641 if (tlb_type == spitfire) {
642 for (; start < end; start += dcache_line_size)
643 spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
645 start &= ~(dcache_line_size - 1);
646 for (; start < end; start += dcache_line_size)
647 __asm__ __volatile__(
648 "stxa %%g0, [%0] %1\n\t"
652 "i" (ASI_DCACHE_INVALIDATE));
656 if (write && tlb_type == spitfire) {
657 unsigned long start = (unsigned long) kaddr;
658 unsigned long end = start + len;
659 unsigned long icache_line_size;
661 icache_line_size = local_cpu_data().icache_line_size;
663 for (; start < end; start += icache_line_size)
669 static const struct ptrace_layout_segment sparc64_getregs_layout[] = {
670 { 0, offsetof(struct pt_regs, u_regs[15]), 0, sizeof(long) },
671 { offsetof(struct pt_regs, u_regs[15]),
672 offsetof(struct pt_regs, tstate),
674 { offsetof(struct pt_regs, tstate), offsetof(struct pt_regs, y),
675 0, 32 * sizeof(long) },
679 int arch_ptrace(long *request, struct task_struct *child,
680 struct utrace_attached_engine *engine,
681 unsigned long addr, unsigned long data,
684 void __user *uaddr = (void __user *) addr;
685 struct pt_regs *uregs = uaddr;
689 case PTRACE_GETREGS64:
690 err = ptrace_layout_access(child, engine,
691 &utrace_sparc64_native_view,
692 sparc64_getregs_layout,
693 0, offsetof(struct pt_regs, y),
696 (put_user(task_pt_regs(child)->y, &uregs->y) ||
697 put_user(task_pt_regs(child)->fprs, &uregs->fprs)))
701 case PTRACE_SETREGS64:
702 err = ptrace_layout_access(child, engine,
703 &utrace_sparc64_native_view,
704 sparc64_getregs_layout,
705 0, offsetof(struct pt_regs, y),
708 (get_user(task_pt_regs(child)->y, &uregs->y) ||
709 get_user(task_pt_regs(child)->fprs, &uregs->fprs)))
713 case PTRACE_GETFPREGS64:
714 case PTRACE_SETFPREGS64:
715 err = ptrace_regset_access(child, engine,
716 utrace_native_view(current),
717 2, 0, 34 * sizeof(long), uaddr,
718 (*request == PTRACE_SETFPREGS64));
721 case PTRACE_SUNDETACH:
722 *request = PTRACE_DETACH;
732 static const struct ptrace_layout_segment sparc32_getregs_layout[] = {
733 { 0, offsetof(struct pt_regs32, u_regs[0]),
734 0, GENREG32_PSR * sizeof(u32) },
735 { offsetof(struct pt_regs32, u_regs[0]),
736 offsetof(struct pt_regs32, u_regs[15]),
737 0, 1 * sizeof(u32) },
738 { offsetof(struct pt_regs32, u_regs[15]), sizeof(struct pt_regs32),
743 int arch_compat_ptrace(compat_long_t *request, struct task_struct *child,
744 struct utrace_attached_engine *engine,
745 compat_ulong_t addr, compat_ulong_t data,
746 compat_long_t *retval)
748 void __user *uaddr = (void __user *) (unsigned long) addr;
754 err = ptrace_layout_access(child, engine,
755 &utrace_sparc32_view,
756 sparc32_getregs_layout,
757 0, sizeof(struct pt_regs32),
763 case PTRACE_GETFPREGS:
764 case PTRACE_SETFPREGS:
765 err = ptrace_whole_regset(child, engine, addr, 1,
766 (*request == PTRACE_SETFPREGS));
769 case PTRACE_SUNDETACH:
770 *request = PTRACE_DETACH;
778 #endif /* CONFIG_COMPAT */
779 #endif /* CONFIG_PTRACE */
781 asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
783 /* do the secure computing check first */
785 secure_computing(regs->u_regs[UREG_G1]);
787 if (unlikely(current->audit_context) && syscall_exit_p) {
788 unsigned long tstate = regs->tstate;
789 int result = AUDITSC_SUCCESS;
791 if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
792 result = AUDITSC_FAILURE;
794 audit_syscall_exit(result, regs->u_regs[UREG_I0]);
797 if (test_thread_flag(TIF_SYSCALL_TRACE))
798 tracehook_report_syscall(regs, syscall_exit_p);
800 if (unlikely(current->audit_context) && !syscall_exit_p)
801 audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
804 regs->u_regs[UREG_G1],
805 regs->u_regs[UREG_I0],
806 regs->u_regs[UREG_I1],
807 regs->u_regs[UREG_I2],
808 regs->u_regs[UREG_I3]);