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))
211 static int fpregs_set(struct task_struct *target,
212 const struct utrace_regset *regset,
213 unsigned int pos, unsigned int count,
214 const void *kbuf, const void __user *ubuf)
216 struct thread_info *t = task_thread_info(target);
219 err = utrace_regset_copyin(&pos, &count, &kbuf, &ubuf,
220 t->fpregs, FPREG_F0 * 8, FPREG_FSR * 8);
223 err = utrace_regset_copyin(&pos, &count, &kbuf, &ubuf,
224 &t->xfsr[0], FPREG_FSR * 8,
228 err = utrace_regset_copyin(&pos, &count, &kbuf, &ubuf,
229 &t->gsr[0], FPREG_GSR * 8,
232 if (err == 0 && count > 0) {
233 struct pt_regs *regs = task_pt_regs(target);
236 regs->fprs = *(unsigned long *) kbuf;
237 else if (get_user(regs->fprs, (unsigned long __user *) ubuf))
244 static const struct utrace_regset native_regsets[] = {
247 .size = sizeof(long), .align = sizeof(long),
248 .get = genregs_get, .set = genregs_set
251 .n = SPARC64_NFPREGS,
252 .size = sizeof(long), .align = sizeof(long),
253 .get = fpregs_get, .set = fpregs_set
257 const struct utrace_regset_view utrace_sparc64_native_view = {
258 .name = UTS_MACHINE, .e_machine = ELF_ARCH,
259 .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets)
261 EXPORT_SYMBOL_GPL(utrace_sparc64_native_view);
265 #define GENREG32_G0 0
266 #define GENREG32_O0 8
267 #define GENREG32_L0 16
268 #define GENREG32_I0 24
269 #define GENREG32_PSR 32
270 #define GENREG32_PC 33
271 #define GENREG32_NPC 34
272 #define GENREG32_Y 35
273 #define GENREG32_WIM 36
274 #define GENREG32_TBR 37
276 #define SPARC32_NGREGS 38
278 static int genregs32_get(struct task_struct *target,
279 const struct utrace_regset *regset,
280 unsigned int pos, unsigned int count,
281 void *kbuf, void __user *ubuf)
283 struct pt_regs *regs = task_pt_regs(target);
285 while (count > 0 && pos < (GENREG32_L0 * 4)) {
286 u32 val = regs->u_regs[(pos - (GENREG32_G0*4))/sizeof(u32)];
290 } else if (put_user(val, (u32 __user *) ubuf))
295 count -= sizeof(u32);
298 if (count > 0 && pos < (GENREG32_PSR * 4)) {
299 struct thread_info *t = task_thread_info(target);
304 if (target == current)
307 wsaved = __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_WSAVED];
308 fp = regs->u_regs[UREG_FP] & 0xffffffffUL;
309 if (wsaved && t->rwbuf_stkptrs[wsaved - 1] == fp) {
311 for (i = 0; i < 8; i++)
313 t->reg_window[wsaved-1].locals[i];
314 for (i = 0; i < 8; i++)
316 t->reg_window[wsaved-1].ins[i];
320 if (target == current) {
322 if (copy_from_user(rwindow, (void __user *) fp,
326 err = access_process_vm(target, fp, rwindow,
327 16 * sizeof(u32), 0);
332 while (count > 0 && pos < (GENREG32_PSR * 4)) {
333 u32 val = rwindow[(pos - (GENREG32_L0*4))/sizeof(u32)];
338 } else if (put_user(val, (u32 __user *) ubuf))
343 count -= sizeof(u32);
347 if (count > 0 && pos == (GENREG32_PSR * 4)) {
348 u32 psr = tstate_to_psr(regs->tstate);
353 } else if (put_user(psr, (u32 __user *) ubuf))
358 count -= sizeof(u32);
361 if (count > 0 && pos == (GENREG32_PC * 4)) {
367 } else if (put_user(val, (u32 __user *) ubuf))
372 count -= sizeof(u32);
375 if (count > 0 && pos == (GENREG32_NPC * 4)) {
376 u32 val = regs->tnpc;
381 } else if (put_user(val, (u32 __user *) ubuf))
386 count -= sizeof(u32);
389 if (count > 0 && pos == (GENREG32_Y * 4)) {
391 *(u32 *) kbuf = regs->y;
393 } else if (put_user(regs->y, (u32 __user *) ubuf))
398 count -= sizeof(u32);
403 memset(kbuf, 0, count);
404 else if (clear_user(ubuf, count))
411 static int genregs32_set(struct task_struct *target,
412 const struct utrace_regset *regset,
413 unsigned int pos, unsigned int count,
414 const void *kbuf, const void __user *ubuf)
416 struct pt_regs *regs = task_pt_regs(target);
418 while (count > 0 && pos < (GENREG32_L0 * 4)) {
420 loc = ®s->u_regs[(pos - (GENREG32_G0*4))/sizeof(u32)];
422 *loc = *(u32 *) kbuf;
424 } else if (get_user(*loc, (u32 __user *) ubuf))
429 count -= sizeof(u32);
432 if (count > 0 && pos < (GENREG32_PSR * 4)) {
435 unsigned int off, copy;
438 if (target == current)
441 copy = (GENREG32_PSR * 4) - pos;
444 BUG_ON(copy > 16 * sizeof(u32));
446 fp = regs->u_regs[UREG_FP] & 0xffffffffUL;
447 off = pos - (GENREG32_L0 * 4);
449 memcpy(regbuf, kbuf, copy);
451 } else if (copy_from_user(regbuf, ubuf, copy))
458 if (target == current) {
460 if (copy_to_user((void __user *) fp + off,
464 err = access_process_vm(target, fp + off,
470 if (count > 0 && pos == (GENREG32_PSR * 4)) {
471 unsigned long tstate, tstate_save;
474 tstate_save = regs->tstate&~(TSTATE_ICC|TSTATE_XCC);
479 } else if (get_user(psr, (u32 __user *) ubuf))
484 count -= sizeof(u32);
486 tstate = psr_to_tstate_icc(psr);
487 regs->tstate = tstate_save | tstate;
490 if (count > 0 && pos == (GENREG32_PC * 4)) {
492 regs->tpc = *(u32 *) kbuf;
494 } else if (get_user(regs->tpc, (u32 __user *) ubuf))
499 count -= sizeof(u32);
502 if (count > 0 && pos == (GENREG32_NPC * 4)) {
504 regs->tnpc = *(u32 *) kbuf;
506 } else if (get_user(regs->tnpc, (u32 __user *) ubuf))
511 count -= sizeof(u32);
514 if (count > 0 && pos == (GENREG32_Y * 4)) {
516 regs->y = *(u32 *) kbuf;
518 } else if (get_user(regs->y, (u32 __user *) ubuf))
523 count -= sizeof(u32);
526 /* Ignore WIM and TBR */
532 #define FPREG32_FSR 32
534 #define SPARC32_NFPREGS 33
536 static int fpregs32_get(struct task_struct *target,
537 const struct utrace_regset *regset,
538 unsigned int pos, unsigned int count,
539 void *kbuf, void __user *ubuf)
541 struct thread_info *t = task_thread_info(target);
544 err = utrace_regset_copyout(&pos, &count, &kbuf, &ubuf,
545 t->fpregs, FPREG32_F0 * 4,
548 if (err == 0 && count > 0) {
550 *(u32 *) kbuf = t->xfsr[0];
551 } else if (put_user(t->xfsr[0], (u32 __user *) ubuf))
558 static int fpregs32_set(struct task_struct *target,
559 const struct utrace_regset *regset,
560 unsigned int pos, unsigned int count,
561 const void *kbuf, const void __user *ubuf)
563 struct thread_info *t = task_thread_info(target);
566 err = utrace_regset_copyin(&pos, &count, &kbuf, &ubuf,
567 t->fpregs, FPREG32_F0 * 4,
570 if (err == 0 && count > 0) {
574 } else if (get_user(fsr, (u32 __user *) ubuf))
576 t->xfsr[0] = (t->xfsr[0] & 0xffffffff00000000UL) | fsr;
582 static const struct utrace_regset sparc32_regsets[] = {
585 .size = sizeof(u32), .align = sizeof(u32),
586 .get = genregs32_get, .set = genregs32_set
589 .n = SPARC32_NFPREGS,
590 .size = sizeof(u32), .align = sizeof(u32),
591 .get = fpregs32_get, .set = fpregs32_set
595 const struct utrace_regset_view utrace_sparc32_view = {
596 .name = "sparc", .e_machine = EM_SPARC,
597 .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
599 EXPORT_SYMBOL_GPL(utrace_sparc32_view);
601 #endif /* CONFIG_COMPAT */
603 /* To get the necessary page struct, access_process_vm() first calls
604 * get_user_pages(). This has done a flush_dcache_page() on the
605 * accessed page. Then our caller (copy_{to,from}_user_page()) did
606 * to memcpy to read/write the data from that page.
608 * Now, the only thing we have to do is:
609 * 1) flush the D-cache if it's possible than an illegal alias
611 * 2) flush the I-cache if this is pre-cheetah and we did a write
613 void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
614 unsigned long uaddr, void *kaddr,
615 unsigned long len, int write)
617 BUG_ON(len > PAGE_SIZE);
619 if (tlb_type == hypervisor)
622 #ifdef DCACHE_ALIASING_POSSIBLE
623 /* If bit 13 of the kernel address we used to access the
624 * user page is the same as the virtual address that page
625 * is mapped to in the user's address space, we can skip the
628 if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
629 unsigned long start = __pa(kaddr);
630 unsigned long end = start + len;
631 unsigned long dcache_line_size;
633 dcache_line_size = local_cpu_data().dcache_line_size;
635 if (tlb_type == spitfire) {
636 for (; start < end; start += dcache_line_size)
637 spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
639 start &= ~(dcache_line_size - 1);
640 for (; start < end; start += dcache_line_size)
641 __asm__ __volatile__(
642 "stxa %%g0, [%0] %1\n\t"
646 "i" (ASI_DCACHE_INVALIDATE));
650 if (write && tlb_type == spitfire) {
651 unsigned long start = (unsigned long) kaddr;
652 unsigned long end = start + len;
653 unsigned long icache_line_size;
655 icache_line_size = local_cpu_data().icache_line_size;
657 for (; start < end; start += icache_line_size)
663 static const struct ptrace_layout_segment sparc64_getregs_layout[] = {
664 { 0, offsetof(struct pt_regs, u_regs[15]), 0, sizeof(long) },
665 { offsetof(struct pt_regs, u_regs[15]),
666 offsetof(struct pt_regs, tstate),
668 { offsetof(struct pt_regs, tstate), offsetof(struct pt_regs, y),
669 0, 32 * sizeof(long) },
673 int arch_ptrace(long *request, struct task_struct *child,
674 struct utrace_attached_engine *engine,
675 unsigned long addr, unsigned long data,
678 void __user *uaddr = (void __user *) addr;
679 struct pt_regs *uregs = uaddr;
683 case PTRACE_GETREGS64:
684 err = ptrace_layout_access(child, engine,
685 &utrace_sparc64_native_view,
686 sparc64_getregs_layout,
687 0, offsetof(struct pt_regs, y),
690 (put_user(task_pt_regs(child)->y, &uregs->y) ||
691 put_user(task_pt_regs(child)->fprs, &uregs->fprs)))
695 case PTRACE_SETREGS64:
696 err = ptrace_layout_access(child, engine,
697 &utrace_sparc64_native_view,
698 sparc64_getregs_layout,
699 0, offsetof(struct pt_regs, y),
702 (get_user(task_pt_regs(child)->y, &uregs->y) ||
703 get_user(task_pt_regs(child)->fprs, &uregs->fprs)))
707 case PTRACE_GETFPREGS64:
708 case PTRACE_SETFPREGS64:
709 err = ptrace_regset_access(child, engine,
710 utrace_native_view(current),
711 2, 0, 34 * sizeof(long), uaddr,
712 (*request == PTRACE_SETFPREGS64));
715 case PTRACE_SUNDETACH:
716 *request = PTRACE_DETACH;
726 static const struct ptrace_layout_segment sparc32_getregs_layout[] = {
727 { 0, offsetof(struct pt_regs32, u_regs[0]),
728 0, GENREG32_PSR * sizeof(u32) },
729 { offsetof(struct pt_regs32, u_regs[0]),
730 offsetof(struct pt_regs32, u_regs[15]),
731 0, 1 * sizeof(u32) },
732 { offsetof(struct pt_regs32, u_regs[15]), sizeof(struct pt_regs32),
737 int arch_compat_ptrace(compat_long_t *request, struct task_struct *child,
738 struct utrace_attached_engine *engine,
739 compat_ulong_t addr, compat_ulong_t data,
740 compat_long_t *retval)
742 void __user *uaddr = (void __user *) (unsigned long) addr;
748 err = ptrace_layout_access(child, engine,
749 &utrace_sparc32_view,
750 sparc32_getregs_layout,
751 0, sizeof(struct pt_regs32),
757 case PTRACE_GETFPREGS:
758 case PTRACE_SETFPREGS:
759 err = ptrace_whole_regset(child, engine, addr, 1,
760 (*request == PTRACE_SETFPREGS));
763 case PTRACE_SUNDETACH:
764 *request = PTRACE_DETACH;
772 #endif /* CONFIG_COMPAT */
773 #endif /* CONFIG_PTRACE */
775 asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
777 /* do the secure computing check first */
779 secure_computing(regs->u_regs[UREG_G1]);
781 if (unlikely(current->audit_context) && syscall_exit_p) {
782 unsigned long tstate = regs->tstate;
783 int result = AUDITSC_SUCCESS;
785 if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
786 result = AUDITSC_FAILURE;
788 audit_syscall_exit(result, regs->u_regs[UREG_I0]);
791 if (test_thread_flag(TIF_SYSCALL_TRACE))
792 tracehook_report_syscall(regs, syscall_exit_p);
794 if (unlikely(current->audit_context) && !syscall_exit_p)
795 audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
798 regs->u_regs[UREG_G1],
799 regs->u_regs[UREG_I0],
800 regs->u_regs[UREG_I1],
801 regs->u_regs[UREG_I2],
802 regs->u_regs[UREG_I3]);