aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/Makefile2
-rw-r--r--arch/powerpc/kernel/ptrace.c (renamed from arch/ppc/kernel/ptrace.c)168
-rw-r--r--arch/ppc/kernel/Makefile4
-rw-r--r--arch/ppc64/kernel/Makefile2
-rw-r--r--arch/ppc64/kernel/ptrace.c363
5 files changed, 141 insertions, 398 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index bce253969e4c..ae97295f270d 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -10,7 +10,7 @@ CFLAGS_prom_init.o += -fPIC
10CFLAGS_btext.o += -fPIC 10CFLAGS_btext.o += -fPIC
11endif 11endif
12 12
13obj-y := semaphore.o cputable.o 13obj-y := semaphore.o cputable.o ptrace.o
14obj-$(CONFIG_PPC64) += binfmt_elf32.o 14obj-$(CONFIG_PPC64) += binfmt_elf32.o
15obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o 15obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
16obj-$(CONFIG_POWER4) += idle_power4.o 16obj-$(CONFIG_POWER4) += idle_power4.o
diff --git a/arch/ppc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index e7aee4108dea..336b8bf542d7 100644
--- a/arch/ppc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1,6 +1,4 @@
1/* 1/*
2 * arch/ppc/kernel/ptrace.c
3 *
4 * PowerPC version 2 * PowerPC version
5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 3 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6 * 4 *
@@ -17,6 +15,7 @@
17 * this archive for more details. 15 * this archive for more details.
18 */ 16 */
19 17
18#include <linux/config.h>
20#include <linux/kernel.h> 19#include <linux/kernel.h>
21#include <linux/sched.h> 20#include <linux/sched.h>
22#include <linux/mm.h> 21#include <linux/mm.h>
@@ -29,13 +28,19 @@
29#include <linux/signal.h> 28#include <linux/signal.h>
30#include <linux/seccomp.h> 29#include <linux/seccomp.h>
31#include <linux/audit.h> 30#include <linux/audit.h>
31#ifdef CONFIG_PPC32
32#include <linux/module.h> 32#include <linux/module.h>
33#endif
33 34
34#include <asm/uaccess.h> 35#include <asm/uaccess.h>
35#include <asm/page.h> 36#include <asm/page.h>
36#include <asm/pgtable.h> 37#include <asm/pgtable.h>
37#include <asm/system.h> 38#include <asm/system.h>
39#ifdef CONFIG_PPC64
40#include <asm/ptrace-common.h>
41#endif
38 42
43#ifdef CONFIG_PPC32
39/* 44/*
40 * Set of msr bits that gdb can change on behalf of a process. 45 * Set of msr bits that gdb can change on behalf of a process.
41 */ 46 */
@@ -44,12 +49,14 @@
44#else 49#else
45#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) 50#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE)
46#endif 51#endif
52#endif /* CONFIG_PPC32 */
47 53
48/* 54/*
49 * does not yet catch signals sent when the child dies. 55 * does not yet catch signals sent when the child dies.
50 * in exit.c or in signal.c. 56 * in exit.c or in signal.c.
51 */ 57 */
52 58
59#ifdef CONFIG_PPC32
53/* 60/*
54 * Get contents of register REGNO in task TASK. 61 * Get contents of register REGNO in task TASK.
55 */ 62 */
@@ -228,6 +235,7 @@ clear_single_step(struct task_struct *task)
228#endif 235#endif
229 } 236 }
230} 237}
238#endif /* CONFIG_PPC32 */
231 239
232/* 240/*
233 * Called by kernel/ptrace.c when detaching.. 241 * Called by kernel/ptrace.c when detaching..
@@ -296,25 +304,28 @@ int sys_ptrace(long request, long pid, long addr, long data)
296 } 304 }
297 305
298 /* read the word at location addr in the USER area. */ 306 /* read the word at location addr in the USER area. */
299 /* XXX this will need fixing for 64-bit */
300 case PTRACE_PEEKUSR: { 307 case PTRACE_PEEKUSR: {
301 unsigned long index, tmp; 308 unsigned long index, tmp;
302 309
303 ret = -EIO; 310 ret = -EIO;
304 /* convert to index and check */ 311 /* convert to index and check */
312#ifdef CONFIG_PPC32
305 index = (unsigned long) addr >> 2; 313 index = (unsigned long) addr >> 2;
306 if ((addr & 3) || index > PT_FPSCR 314 if ((addr & 3) || (index > PT_FPSCR)
307 || child->thread.regs == NULL) 315 || (child->thread.regs == NULL))
316#else
317 index = (unsigned long) addr >> 3;
318 if ((addr & 7) || (index > PT_FPSCR))
319#endif
308 break; 320 break;
309 321
322#ifdef CONFIG_PPC32
310 CHECK_FULL_REGS(child->thread.regs); 323 CHECK_FULL_REGS(child->thread.regs);
324#endif
311 if (index < PT_FPR0) { 325 if (index < PT_FPR0) {
312 tmp = get_reg(child, (int) index); 326 tmp = get_reg(child, (int) index);
313 } else { 327 } else {
314 preempt_disable(); 328 flush_fp_to_thread(child);
315 if (child->thread.regs->msr & MSR_FP)
316 giveup_fpu(child);
317 preempt_enable();
318 tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; 329 tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
319 } 330 }
320 ret = put_user(tmp,(unsigned long __user *) data); 331 ret = put_user(tmp,(unsigned long __user *) data);
@@ -325,7 +336,8 @@ int sys_ptrace(long request, long pid, long addr, long data)
325 case PTRACE_POKETEXT: /* write the word at location addr. */ 336 case PTRACE_POKETEXT: /* write the word at location addr. */
326 case PTRACE_POKEDATA: 337 case PTRACE_POKEDATA:
327 ret = 0; 338 ret = 0;
328 if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) 339 if (access_process_vm(child, addr, &data, sizeof(data), 1)
340 == sizeof(data))
329 break; 341 break;
330 ret = -EIO; 342 ret = -EIO;
331 break; 343 break;
@@ -336,21 +348,25 @@ int sys_ptrace(long request, long pid, long addr, long data)
336 348
337 ret = -EIO; 349 ret = -EIO;
338 /* convert to index and check */ 350 /* convert to index and check */
351#ifdef CONFIG_PPC32
339 index = (unsigned long) addr >> 2; 352 index = (unsigned long) addr >> 2;
340 if ((addr & 3) || index > PT_FPSCR 353 if ((addr & 3) || (index > PT_FPSCR)
341 || child->thread.regs == NULL) 354 || (child->thread.regs == NULL))
355#else
356 index = (unsigned long) addr >> 3;
357 if ((addr & 7) || (index > PT_FPSCR))
358#endif
342 break; 359 break;
343 360
361#ifdef CONFIG_PPC32
344 CHECK_FULL_REGS(child->thread.regs); 362 CHECK_FULL_REGS(child->thread.regs);
363#endif
345 if (index == PT_ORIG_R3) 364 if (index == PT_ORIG_R3)
346 break; 365 break;
347 if (index < PT_FPR0) { 366 if (index < PT_FPR0) {
348 ret = put_reg(child, index, data); 367 ret = put_reg(child, index, data);
349 } else { 368 } else {
350 preempt_disable(); 369 flush_fp_to_thread(child);
351 if (child->thread.regs->msr & MSR_FP)
352 giveup_fpu(child);
353 preempt_enable();
354 ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data; 370 ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
355 ret = 0; 371 ret = 0;
356 } 372 }
@@ -362,11 +378,10 @@ int sys_ptrace(long request, long pid, long addr, long data)
362 ret = -EIO; 378 ret = -EIO;
363 if (!valid_signal(data)) 379 if (!valid_signal(data))
364 break; 380 break;
365 if (request == PTRACE_SYSCALL) { 381 if (request == PTRACE_SYSCALL)
366 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 382 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
367 } else { 383 else
368 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 384 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
369 }
370 child->exit_code = data; 385 child->exit_code = data;
371 /* make sure the single step bit is not set. */ 386 /* make sure the single step bit is not set. */
372 clear_single_step(child); 387 clear_single_step(child);
@@ -404,28 +419,102 @@ int sys_ptrace(long request, long pid, long addr, long data)
404 break; 419 break;
405 } 420 }
406 421
422#ifdef CONFIG_PPC64
423 case PTRACE_GET_DEBUGREG: {
424 ret = -EINVAL;
425 /* We only support one DABR and no IABRS at the moment */
426 if (addr > 0)
427 break;
428 ret = put_user(child->thread.dabr,
429 (unsigned long __user *)data);
430 break;
431 }
432
433 case PTRACE_SET_DEBUGREG:
434 ret = ptrace_set_debugreg(child, addr, data);
435 break;
436#endif
437
407 case PTRACE_DETACH: 438 case PTRACE_DETACH:
408 ret = ptrace_detach(child, data); 439 ret = ptrace_detach(child, data);
409 break; 440 break;
410 441
442#ifdef CONFIG_PPC64
443 case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
444 int i;
445 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
446 unsigned long __user *tmp = (unsigned long __user *)addr;
447
448 for (i = 0; i < 32; i++) {
449 ret = put_user(*reg, tmp);
450 if (ret)
451 break;
452 reg++;
453 tmp++;
454 }
455 break;
456 }
457
458 case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
459 int i;
460 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
461 unsigned long __user *tmp = (unsigned long __user *)addr;
462
463 for (i = 0; i < 32; i++) {
464 ret = get_user(*reg, tmp);
465 if (ret)
466 break;
467 reg++;
468 tmp++;
469 }
470 break;
471 }
472
473 case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
474 int i;
475 unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
476 unsigned long __user *tmp = (unsigned long __user *)addr;
477
478 flush_fp_to_thread(child);
479
480 for (i = 0; i < 32; i++) {
481 ret = put_user(*reg, tmp);
482 if (ret)
483 break;
484 reg++;
485 tmp++;
486 }
487 break;
488 }
489
490 case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
491 int i;
492 unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
493 unsigned long __user *tmp = (unsigned long __user *)addr;
494
495 flush_fp_to_thread(child);
496
497 for (i = 0; i < 32; i++) {
498 ret = get_user(*reg, tmp);
499 if (ret)
500 break;
501 reg++;
502 tmp++;
503 }
504 break;
505 }
506#endif /* CONFIG_PPC64 */
507
411#ifdef CONFIG_ALTIVEC 508#ifdef CONFIG_ALTIVEC
412 case PTRACE_GETVRREGS: 509 case PTRACE_GETVRREGS:
413 /* Get the child altivec register state. */ 510 /* Get the child altivec register state. */
414 preempt_disable(); 511 flush_altivec_to_thread(child);
415 if (child->thread.regs->msr & MSR_VEC)
416 giveup_altivec(child);
417 preempt_enable();
418 ret = get_vrregs((unsigned long __user *)data, child); 512 ret = get_vrregs((unsigned long __user *)data, child);
419 break; 513 break;
420 514
421 case PTRACE_SETVRREGS: 515 case PTRACE_SETVRREGS:
422 /* Set the child altivec register state. */ 516 /* Set the child altivec register state. */
423 /* this is to clear the MSR_VEC bit to force a reload 517 flush_altivec_to_thread(child);
424 * of register state from memory */
425 preempt_disable();
426 if (child->thread.regs->msr & MSR_VEC)
427 giveup_altivec(child);
428 preempt_enable();
429 ret = set_vrregs(child, (unsigned long __user *)data); 518 ret = set_vrregs(child, (unsigned long __user *)data);
430 break; 519 break;
431#endif 520#endif
@@ -478,12 +567,21 @@ static void do_syscall_trace(void)
478 567
479void do_syscall_trace_enter(struct pt_regs *regs) 568void do_syscall_trace_enter(struct pt_regs *regs)
480{ 569{
570#ifdef CONFIG_PPC64
571 secure_computing(regs->gpr[0]);
572#endif
573
481 if (test_thread_flag(TIF_SYSCALL_TRACE) 574 if (test_thread_flag(TIF_SYSCALL_TRACE)
482 && (current->ptrace & PT_PTRACED)) 575 && (current->ptrace & PT_PTRACED))
483 do_syscall_trace(); 576 do_syscall_trace();
484 577
485 if (unlikely(current->audit_context)) 578 if (unlikely(current->audit_context))
486 audit_syscall_entry(current, AUDIT_ARCH_PPC, 579 audit_syscall_entry(current,
580#ifdef CONFIG_PPC32
581 AUDIT_ARCH_PPC,
582#else
583 test_thread_flag(TIF_32BIT)?AUDIT_ARCH_PPC:AUDIT_ARCH_PPC64,
584#endif
487 regs->gpr[0], 585 regs->gpr[0],
488 regs->gpr[3], regs->gpr[4], 586 regs->gpr[3], regs->gpr[4],
489 regs->gpr[5], regs->gpr[6]); 587 regs->gpr[5], regs->gpr[6]);
@@ -491,17 +589,25 @@ void do_syscall_trace_enter(struct pt_regs *regs)
491 589
492void do_syscall_trace_leave(struct pt_regs *regs) 590void do_syscall_trace_leave(struct pt_regs *regs)
493{ 591{
592#ifdef CONFIG_PPC32
494 secure_computing(regs->gpr[0]); 593 secure_computing(regs->gpr[0]);
594#endif
495 595
496 if (unlikely(current->audit_context)) 596 if (unlikely(current->audit_context))
497 audit_syscall_exit(current, 597 audit_syscall_exit(current,
498 (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS, 598 (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
499 regs->result); 599 regs->result);
500 600
501 if ((test_thread_flag(TIF_SYSCALL_TRACE)) 601 if ((test_thread_flag(TIF_SYSCALL_TRACE)
602#ifdef CONFIG_PPC64
603 || test_thread_flag(TIF_SINGLESTEP)
604#endif
605 )
502 && (current->ptrace & PT_PTRACED)) 606 && (current->ptrace & PT_PTRACED))
503 do_syscall_trace(); 607 do_syscall_trace();
504} 608}
505 609
610#ifdef CONFIG_PPC32
506EXPORT_SYMBOL(do_syscall_trace_enter); 611EXPORT_SYMBOL(do_syscall_trace_enter);
507EXPORT_SYMBOL(do_syscall_trace_leave); 612EXPORT_SYMBOL(do_syscall_trace_leave);
613#endif
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index 0cba463adf9a..7d16b1f7cd31 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -13,7 +13,7 @@ extra-$(CONFIG_POWER4) += idle_power4.o
13extra-y += vmlinux.lds 13extra-y += vmlinux.lds
14 14
15obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ 15obj-y := entry.o traps.o irq.o idle.o time.o misc.o \
16 process.o signal.o ptrace.o align.o \ 16 process.o signal.o align.o \
17 syscalls.o setup.o \ 17 syscalls.o setup.o \
18 ppc_htab.o perfmon.o 18 ppc_htab.o perfmon.o
19obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o 19obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
@@ -38,7 +38,7 @@ endif
38 38
39else 39else
40obj-y := irq.o idle.o time.o \ 40obj-y := irq.o idle.o time.o \
41 signal.o ptrace.o align.o \ 41 signal.o align.o \
42 syscalls.o perfmon.o 42 syscalls.o perfmon.o
43obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o 43obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
44obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o 44obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 1a8f3532885a..b1203b79edf0 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -12,7 +12,7 @@ obj-y := setup.o entry.o misc.o prom.o
12endif 12endif
13 13
14obj-y += irq.o idle.o dma.o \ 14obj-y += irq.o idle.o dma.o \
15 time.o signal.o syscalls.o ptrace.o \ 15 time.o signal.o syscalls.o \
16 align.o bitops.o pacaData.o \ 16 align.o bitops.o pacaData.o \
17 udbg.o sys_ppc32.o ioctl32.o \ 17 udbg.o sys_ppc32.o ioctl32.o \
18 ptrace32.o signal32.o rtc.o \ 18 ptrace32.o signal32.o rtc.o \
diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
deleted file mode 100644
index b1c044ca5756..000000000000
--- a/arch/ppc64/kernel/ptrace.c
+++ /dev/null
@@ -1,363 +0,0 @@
1/*
2 * linux/arch/ppc64/kernel/ptrace.c
3 *
4 * PowerPC version
5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6 *
7 * Derived from "arch/m68k/kernel/ptrace.c"
8 * Copyright (C) 1994 by Hamish Macdonald
9 * Taken from linux/kernel/ptrace.c and modified for M680x0.
10 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
11 *
12 * Modified by Cort Dougan (cort@hq.fsmlabs.com)
13 * and Paul Mackerras (paulus@linuxcare.com.au).
14 *
15 * This file is subject to the terms and conditions of the GNU General
16 * Public License. See the file README.legal in the main directory of
17 * this archive for more details.
18 */
19
20#include <linux/config.h>
21#include <linux/kernel.h>
22#include <linux/sched.h>
23#include <linux/mm.h>
24#include <linux/smp.h>
25#include <linux/smp_lock.h>
26#include <linux/errno.h>
27#include <linux/ptrace.h>
28#include <linux/user.h>
29#include <linux/security.h>
30#include <linux/audit.h>
31#include <linux/seccomp.h>
32#include <linux/signal.h>
33
34#include <asm/uaccess.h>
35#include <asm/page.h>
36#include <asm/pgtable.h>
37#include <asm/system.h>
38#include <asm/ptrace-common.h>
39
40/*
41 * does not yet catch signals sent when the child dies.
42 * in exit.c or in signal.c.
43 */
44
45/*
46 * Called by kernel/ptrace.c when detaching..
47 *
48 * Make sure single step bits etc are not set.
49 */
50void ptrace_disable(struct task_struct *child)
51{
52 /* make sure the single step bit is not set. */
53 clear_single_step(child);
54}
55
56int sys_ptrace(long request, long pid, long addr, long data)
57{
58 struct task_struct *child;
59 int ret = -EPERM;
60
61 lock_kernel();
62 if (request == PTRACE_TRACEME) {
63 /* are we already being traced? */
64 if (current->ptrace & PT_PTRACED)
65 goto out;
66 ret = security_ptrace(current->parent, current);
67 if (ret)
68 goto out;
69 /* set the ptrace bit in the process flags. */
70 current->ptrace |= PT_PTRACED;
71 ret = 0;
72 goto out;
73 }
74 ret = -ESRCH;
75 read_lock(&tasklist_lock);
76 child = find_task_by_pid(pid);
77 if (child)
78 get_task_struct(child);
79 read_unlock(&tasklist_lock);
80 if (!child)
81 goto out;
82
83 ret = -EPERM;
84 if (pid == 1) /* you may not mess with init */
85 goto out_tsk;
86
87 if (request == PTRACE_ATTACH) {
88 ret = ptrace_attach(child);
89 goto out_tsk;
90 }
91
92 ret = ptrace_check_attach(child, request == PTRACE_KILL);
93 if (ret < 0)
94 goto out_tsk;
95
96 switch (request) {
97 /* when I and D space are separate, these will need to be fixed. */
98 case PTRACE_PEEKTEXT: /* read word at location addr. */
99 case PTRACE_PEEKDATA: {
100 unsigned long tmp;
101 int copied;
102
103 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
104 ret = -EIO;
105 if (copied != sizeof(tmp))
106 break;
107 ret = put_user(tmp,(unsigned long __user *) data);
108 break;
109 }
110
111 /* read the word at location addr in the USER area. */
112 case PTRACE_PEEKUSR: {
113 unsigned long index;
114 unsigned long tmp;
115
116 ret = -EIO;
117 /* convert to index and check */
118 index = (unsigned long) addr >> 3;
119 if ((addr & 7) || (index > PT_FPSCR))
120 break;
121
122 if (index < PT_FPR0) {
123 tmp = get_reg(child, (int)index);
124 } else {
125 flush_fp_to_thread(child);
126 tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
127 }
128 ret = put_user(tmp,(unsigned long __user *) data);
129 break;
130 }
131
132 /* If I and D space are separate, this will have to be fixed. */
133 case PTRACE_POKETEXT: /* write the word at location addr. */
134 case PTRACE_POKEDATA:
135 ret = 0;
136 if (access_process_vm(child, addr, &data, sizeof(data), 1)
137 == sizeof(data))
138 break;
139 ret = -EIO;
140 break;
141
142 /* write the word at location addr in the USER area */
143 case PTRACE_POKEUSR: {
144 unsigned long index;
145
146 ret = -EIO;
147 /* convert to index and check */
148 index = (unsigned long) addr >> 3;
149 if ((addr & 7) || (index > PT_FPSCR))
150 break;
151
152 if (index == PT_ORIG_R3)
153 break;
154 if (index < PT_FPR0) {
155 ret = put_reg(child, index, data);
156 } else {
157 flush_fp_to_thread(child);
158 ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
159 ret = 0;
160 }
161 break;
162 }
163
164 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
165 case PTRACE_CONT: { /* restart after signal. */
166 ret = -EIO;
167 if (!valid_signal(data))
168 break;
169 if (request == PTRACE_SYSCALL)
170 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
171 else
172 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
173 child->exit_code = data;
174 /* make sure the single step bit is not set. */
175 clear_single_step(child);
176 wake_up_process(child);
177 ret = 0;
178 break;
179 }
180
181 /*
182 * make the child exit. Best I can do is send it a sigkill.
183 * perhaps it should be put in the status that it wants to
184 * exit.
185 */
186 case PTRACE_KILL: {
187 ret = 0;
188 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
189 break;
190 child->exit_code = SIGKILL;
191 /* make sure the single step bit is not set. */
192 clear_single_step(child);
193 wake_up_process(child);
194 break;
195 }
196
197 case PTRACE_SINGLESTEP: { /* set the trap flag. */
198 ret = -EIO;
199 if (!valid_signal(data))
200 break;
201 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
202 set_single_step(child);
203 child->exit_code = data;
204 /* give it a chance to run. */
205 wake_up_process(child);
206 ret = 0;
207 break;
208 }
209
210 case PTRACE_GET_DEBUGREG: {
211 ret = -EINVAL;
212 /* We only support one DABR and no IABRS at the moment */
213 if (addr > 0)
214 break;
215 ret = put_user(child->thread.dabr,
216 (unsigned long __user *)data);
217 break;
218 }
219
220 case PTRACE_SET_DEBUGREG:
221 ret = ptrace_set_debugreg(child, addr, data);
222 break;
223
224 case PTRACE_DETACH:
225 ret = ptrace_detach(child, data);
226 break;
227
228 case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
229 int i;
230 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
231 unsigned long __user *tmp = (unsigned long __user *)addr;
232
233 for (i = 0; i < 32; i++) {
234 ret = put_user(*reg, tmp);
235 if (ret)
236 break;
237 reg++;
238 tmp++;
239 }
240 break;
241 }
242
243 case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
244 int i;
245 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
246 unsigned long __user *tmp = (unsigned long __user *)addr;
247
248 for (i = 0; i < 32; i++) {
249 ret = get_user(*reg, tmp);
250 if (ret)
251 break;
252 reg++;
253 tmp++;
254 }
255 break;
256 }
257
258 case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
259 int i;
260 unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
261 unsigned long __user *tmp = (unsigned long __user *)addr;
262
263 flush_fp_to_thread(child);
264
265 for (i = 0; i < 32; i++) {
266 ret = put_user(*reg, tmp);
267 if (ret)
268 break;
269 reg++;
270 tmp++;
271 }
272 break;
273 }
274
275 case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
276 int i;
277 unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
278 unsigned long __user *tmp = (unsigned long __user *)addr;
279
280 flush_fp_to_thread(child);
281
282 for (i = 0; i < 32; i++) {
283 ret = get_user(*reg, tmp);
284 if (ret)
285 break;
286 reg++;
287 tmp++;
288 }
289 break;
290 }
291
292#ifdef CONFIG_ALTIVEC
293 case PTRACE_GETVRREGS:
294 /* Get the child altivec register state. */
295 flush_altivec_to_thread(child);
296 ret = get_vrregs((unsigned long __user *)data, child);
297 break;
298
299 case PTRACE_SETVRREGS:
300 /* Set the child altivec register state. */
301 flush_altivec_to_thread(child);
302 ret = set_vrregs(child, (unsigned long __user *)data);
303 break;
304#endif
305
306 default:
307 ret = ptrace_request(child, request, addr, data);
308 break;
309 }
310out_tsk:
311 put_task_struct(child);
312out:
313 unlock_kernel();
314 return ret;
315}
316
317static void do_syscall_trace(void)
318{
319 /* the 0x80 provides a way for the tracing parent to distinguish
320 between a syscall stop and SIGTRAP delivery */
321 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
322 ? 0x80 : 0));
323
324 /*
325 * this isn't the same as continuing with a signal, but it will do
326 * for normal use. strace only continues with a signal if the
327 * stopping signal is not SIGTRAP. -brl
328 */
329 if (current->exit_code) {
330 send_sig(current->exit_code, current, 1);
331 current->exit_code = 0;
332 }
333}
334
335void do_syscall_trace_enter(struct pt_regs *regs)
336{
337 secure_computing(regs->gpr[0]);
338
339 if (test_thread_flag(TIF_SYSCALL_TRACE)
340 && (current->ptrace & PT_PTRACED))
341 do_syscall_trace();
342
343 if (unlikely(current->audit_context))
344 audit_syscall_entry(current,
345 test_thread_flag(TIF_32BIT)?AUDIT_ARCH_PPC:AUDIT_ARCH_PPC64,
346 regs->gpr[0],
347 regs->gpr[3], regs->gpr[4],
348 regs->gpr[5], regs->gpr[6]);
349
350}
351
352void do_syscall_trace_leave(struct pt_regs *regs)
353{
354 if (unlikely(current->audit_context))
355 audit_syscall_exit(current,
356 (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
357 regs->result);
358
359 if ((test_thread_flag(TIF_SYSCALL_TRACE)
360 || test_thread_flag(TIF_SINGLESTEP))
361 && (current->ptrace & PT_PTRACED))
362 do_syscall_trace();
363}