s390/ftrace: fix mcount adjustment
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Mon, 13 May 2013 12:48:52 +0000 (14:48 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 15 May 2013 11:09:09 +0000 (13:09 +0200)
Tony Jones reported that the ftrace self tests on s390 do not work:

<6>Testing dynamic ftrace ops #1: (0 0 0 0 0) FAILED!
<6>Testing tracer irqsoff:
<3>failed to start irqsoff tracer
<4>.. no entries found ..FAILED!
<6>Testing tracer wakeup:
<3>failed to start wakeup tracer
<4>.. no entries found ..FAILED!
<6>Testing tracer function_graph:
<4>Failed to init function_graph tracer, init returned -19
<4>FAILED!

This happens because we forgot to adjust the instruction pointer that gets
passed to the ftrace trace function by MCOUNT_INSN_SIZE.

In addition change MCOUNT_INSN_SIZE to the correct value on 31 bit.
It only worked so far because the to be patched instruction was identical.

Reported-by: Tony Jones <tonyj@suse.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/ftrace.h
arch/s390/kernel/ftrace.c
arch/s390/kernel/mcount.S
arch/s390/kernel/mcount64.S

index b7931fa..bf246da 100644 (file)
@@ -9,11 +9,6 @@ struct dyn_arch_ftrace { };
 
 #define MCOUNT_ADDR ((long)_mcount)
 
-#ifdef CONFIG_64BIT
-#define MCOUNT_INSN_SIZE  12
-#else
-#define MCOUNT_INSN_SIZE  20
-#endif
 
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
@@ -21,4 +16,11 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 }
 
 #endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_64BIT
+#define MCOUNT_INSN_SIZE  12
+#else
+#define MCOUNT_INSN_SIZE  22
+#endif
+
 #endif /* _ASM_S390_FTRACE_H */
index 78bdf0e..e3043ae 100644 (file)
 #include <trace/syscall.h>
 #include <asm/asm-offsets.h>
 
-#ifdef CONFIG_64BIT
-#define MCOUNT_OFFSET_RET 12
-#else
-#define MCOUNT_OFFSET_RET 22
-#endif
-
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 void ftrace_disable_code(void);
@@ -155,9 +149,10 @@ unsigned long __kprobes prepare_ftrace_return(unsigned long parent,
 
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                goto out;
+       ip = (ip & PSW_ADDR_INSN) - MCOUNT_INSN_SIZE;
        if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY)
                goto out;
-       trace.func = (ip & PSW_ADDR_INSN) - MCOUNT_OFFSET_RET;
+       trace.func = ip;
        /* Only trace if the calling function expects to. */
        if (!ftrace_graph_entry(&trace)) {
                current->curr_ret_stack--;
index 4567ce2..08dcf21 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
+#include <asm/ftrace.h>
 
        .section .kprobes.text, "ax"
 
@@ -33,6 +34,7 @@ ENTRY(ftrace_caller)
        la      %r2,0(%r14)
        st      %r0,__SF_BACKCHAIN(%r15)
        la      %r3,0(%r3)
+       ahi     %r2,-MCOUNT_INSN_SIZE
        l       %r14,0b-0b(%r1)
        l       %r14,0(%r14)
        basr    %r14,%r14
index 1133219..1c52eae 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
+#include <asm/ftrace.h>
 
        .section .kprobes.text, "ax"
 
@@ -29,6 +30,7 @@ ENTRY(ftrace_caller)
        stg     %r1,__SF_BACKCHAIN(%r15)
        lgr     %r2,%r14
        lg      %r3,168(%r15)
+       aghi    %r2,-MCOUNT_INSN_SIZE
        larl    %r14,ftrace_trace_function
        lg      %r14,0(%r14)
        basr    %r14,%r14