aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2008-07-27 02:51:03 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-07-28 02:30:49 -0400
commit4f72c4279eab1e5f3ed1ac4e55d4527617582392 (patch)
tree5a170211e0206d4d17a008dec9c88827c95c1152 /arch/powerpc
parent6558ba2b5cc3a2f22039db30616fcd07c1b28ac8 (diff)
powerpc: Make syscall tracing use tracehook.h helpers
This changes powerpc syscall tracing to use the new tracehook.h entry points. There is no change, only cleanup. In addition, the assembly changes allow do_syscall_trace_enter() to abort the syscall without losing the information about the original r0 value. Signed-off-by: Roland McGrath <roland@redhat.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/entry_32.S7
-rw-r--r--arch/powerpc/kernel/entry_64.S7
-rw-r--r--arch/powerpc/kernel/ptrace.c47
3 files changed, 34 insertions, 27 deletions
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index da52269aec1e..e6fca6a9014d 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -343,7 +343,12 @@ syscall_dotrace:
343 stw r0,_TRAP(r1) 343 stw r0,_TRAP(r1)
344 addi r3,r1,STACK_FRAME_OVERHEAD 344 addi r3,r1,STACK_FRAME_OVERHEAD
345 bl do_syscall_trace_enter 345 bl do_syscall_trace_enter
346 lwz r0,GPR0(r1) /* Restore original registers */ 346 /*
347 * Restore argument registers possibly just changed.
348 * We use the return value of do_syscall_trace_enter
349 * for call number to look up in the table (r0).
350 */
351 mr r0,r3
347 lwz r3,GPR3(r1) 352 lwz r3,GPR3(r1)
348 lwz r4,GPR4(r1) 353 lwz r4,GPR4(r1)
349 lwz r5,GPR5(r1) 354 lwz r5,GPR5(r1)
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index d7369243ae44..79c089e97ce4 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -214,7 +214,12 @@ syscall_dotrace:
214 bl .save_nvgprs 214 bl .save_nvgprs
215 addi r3,r1,STACK_FRAME_OVERHEAD 215 addi r3,r1,STACK_FRAME_OVERHEAD
216 bl .do_syscall_trace_enter 216 bl .do_syscall_trace_enter
217 ld r0,GPR0(r1) /* Restore original registers */ 217 /*
218 * Restore argument registers possibly just changed.
219 * We use the return value of do_syscall_trace_enter
220 * for the call number to look up in the table (r0).
221 */
222 mr r0,r3
218 ld r3,GPR3(r1) 223 ld r3,GPR3(r1)
219 ld r4,GPR4(r1) 224 ld r4,GPR4(r1)
220 ld r5,GPR5(r1) 225 ld r5,GPR5(r1)
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 66204cb51a1a..6b66cd85b433 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -22,6 +22,7 @@
22#include <linux/errno.h> 22#include <linux/errno.h>
23#include <linux/ptrace.h> 23#include <linux/ptrace.h>
24#include <linux/regset.h> 24#include <linux/regset.h>
25#include <linux/tracehook.h>
25#include <linux/elf.h> 26#include <linux/elf.h>
26#include <linux/user.h> 27#include <linux/user.h>
27#include <linux/security.h> 28#include <linux/security.h>
@@ -1014,31 +1015,24 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
1014 return ret; 1015 return ret;
1015} 1016}
1016 1017
1017static void do_syscall_trace(void) 1018/*
1019 * We must return the syscall number to actually look up in the table.
1020 * This can be -1L to skip running any syscall at all.
1021 */
1022long do_syscall_trace_enter(struct pt_regs *regs)
1018{ 1023{
1019 /* the 0x80 provides a way for the tracing parent to distinguish 1024 long ret = 0;
1020 between a syscall stop and SIGTRAP delivery */
1021 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
1022 ? 0x80 : 0));
1023
1024 /*
1025 * this isn't the same as continuing with a signal, but it will do
1026 * for normal use. strace only continues with a signal if the
1027 * stopping signal is not SIGTRAP. -brl
1028 */
1029 if (current->exit_code) {
1030 send_sig(current->exit_code, current, 1);
1031 current->exit_code = 0;
1032 }
1033}
1034 1025
1035void do_syscall_trace_enter(struct pt_regs *regs)
1036{
1037 secure_computing(regs->gpr[0]); 1026 secure_computing(regs->gpr[0]);
1038 1027
1039 if (test_thread_flag(TIF_SYSCALL_TRACE) 1028 if (test_thread_flag(TIF_SYSCALL_TRACE) &&
1040 && (current->ptrace & PT_PTRACED)) 1029 tracehook_report_syscall_entry(regs))
1041 do_syscall_trace(); 1030 /*
1031 * Tracing decided this syscall should not happen.
1032 * We'll return a bogus call number to get an ENOSYS
1033 * error, but leave the original number in regs->gpr[0].
1034 */
1035 ret = -1L;
1042 1036
1043 if (unlikely(current->audit_context)) { 1037 if (unlikely(current->audit_context)) {
1044#ifdef CONFIG_PPC64 1038#ifdef CONFIG_PPC64
@@ -1056,16 +1050,19 @@ void do_syscall_trace_enter(struct pt_regs *regs)
1056 regs->gpr[5] & 0xffffffff, 1050 regs->gpr[5] & 0xffffffff,
1057 regs->gpr[6] & 0xffffffff); 1051 regs->gpr[6] & 0xffffffff);
1058 } 1052 }
1053
1054 return ret ?: regs->gpr[0];
1059} 1055}
1060 1056
1061void do_syscall_trace_leave(struct pt_regs *regs) 1057void do_syscall_trace_leave(struct pt_regs *regs)
1062{ 1058{
1059 int step;
1060
1063 if (unlikely(current->audit_context)) 1061 if (unlikely(current->audit_context))
1064 audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS, 1062 audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
1065 regs->result); 1063 regs->result);
1066 1064
1067 if ((test_thread_flag(TIF_SYSCALL_TRACE) 1065 step = test_thread_flag(TIF_SINGLESTEP);
1068 || test_thread_flag(TIF_SINGLESTEP)) 1066 if (step || test_thread_flag(TIF_SYSCALL_TRACE))
1069 && (current->ptrace & PT_PTRACED)) 1067 tracehook_report_syscall_exit(regs, step);
1070 do_syscall_trace();
1071} 1068}