[PATCH 1/4] ppc64 FTRACE_WITH_REGS implementation

2015-06-11 Thread Torsten Duwe
Implement FTRACE_WITH_REGS for powerpc64, on ELF ABI v2.
Initial work started by Vojtech Pavlik, used with permission.

  * arch/powerpc/kernel/entry_64.S:
- enhance _mcount with a stub to test (ftrace_trace_function == 
&ftrace_stub)
  as suggested in Documentation/trace/ftrace-design.txt
  (for reference only, patched out at runtime)
- Implement an effective ftrace_caller that works from within the kernel
  binary as well as from modules.
  * arch/powerpc/kernel/ftrace.c:
- be prepared to deal with ppc64 ELV ABI v2, especially calls to _mcount
  that result from gcc -mprofile-kernel
  * arch/powerpc/kernel/module_64.c:
- do not save the TOC pointer on the trampoline when the destination
  is ftrace_caller. This trampoline jump happens from a function prologue
  before a new stack frame is set up, so bad things may happen otherwise...
- relax is_module_trampoline() to recognise the modified trampoline.

Signed-off-by: Torsten Duwe 
--
 arch/powerpc/include/asm/ftrace.h |5 +
 arch/powerpc/kernel/entry_64.S|  112 +++---
 arch/powerpc/kernel/ftrace.c  |   67 --
 arch/powerpc/kernel/module_64.c   |   33 ++-
 4 files changed, 186 insertions(+), 31 deletions(-)
--
diff --git a/arch/powerpc/include/asm/ftrace.h 
b/arch/powerpc/include/asm/ftrace.h
index e366187..691 100644
--- a/arch/powerpc/include/asm/ftrace.h
+++ b/arch/powerpc/include/asm/ftrace.h
@@ -46,6 +46,8 @@
 extern void _mcount(void);
 
 #ifdef CONFIG_DYNAMIC_FTRACE
+# define FTRACE_ADDR ((unsigned long)ftrace_caller+8)
+# define FTRACE_REGS_ADDR FTRACE_ADDR
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
/* reloction of mcount call site is the same as the address */
@@ -58,6 +60,9 @@ struct dyn_arch_ftrace {
 #endif /*  CONFIG_DYNAMIC_FTRACE */
 #endif /* __ASSEMBLY__ */
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+#define ARCH_SUPPORTS_FTRACE_OPS 1
+#endif
 #endif
 
 #if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64) && 
!defined(__ASSEMBLY__)
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index d180caf..a4132ef 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -1152,32 +1152,107 @@ _GLOBAL(enter_prom)
 
 #ifdef CONFIG_FUNCTION_TRACER
 #ifdef CONFIG_DYNAMIC_FTRACE
-_GLOBAL(mcount)
+
+#define TOCSAVE 24
+
 _GLOBAL(_mcount)
-   blr
+   nop // REQUIRED for ftrace, to calculate local/global entry diff
+.localentry _mcount,.-_mcount
+   mflrr0
+   mtctr   r0
+
+   LOAD_REG_ADDR_PIC(r12,ftrace_trace_function)
+   ld  r12,0(r12)
+   LOAD_REG_ADDR_PIC(r0,ftrace_stub)
+   cmpdr0,r12
+   ld  r0,LRSAVE(r1)
+   bne-2f
+
+   mtlrr0
+   bctr
+
+2: /* here we have (*ftrace_trace_function)() in r12,
+  "selfpc" in CTR
+  and "frompc" in r0 */
+
+   mtlrr0
+   bctr
+
+_GLOBAL(ftrace_caller)
+   mr  r0,r2   // global (module) call: save module TOC
+   b   1f
+.localentry ftrace_caller,.-ftrace_caller
+   mr  r0,r2   // local call: callee's TOC == our TOC
+   b   2f
+
+1: addis   r2,r12,(.TOC.-0b)@ha
+   addir2,r2,(.TOC.-0b)@l
+
+2: // Here we have our proper TOC ptr in R2,
+   // and the one we need to restore on return in r0.
+
+   ld  r12, 16(r1) // get caller's adress
+
+   stdur1,-SWITCH_FRAME_SIZE(r1)
+
+   std r12, _LINK(r1)
+   SAVE_8GPRS(0,r1)
+   std r0,TOCSAVE(r1)
+   SAVE_8GPRS(8,r1)
+   SAVE_8GPRS(16,r1)
+   SAVE_8GPRS(24,r1)
+
+
+   LOAD_REG_IMMEDIATE(r3,function_trace_op)
+   ld  r5,0(r3)
+
+   mflrr3
+   std r3, _NIP(r1)
+   std r3, 16(r1)
+   subir3, r3, MCOUNT_INSN_SIZE
+   mfmsr   r4
+   std r4, _MSR(r1)
+   mfctr   r4
+   std r4, _CTR(r1)
+   mfxer   r4
+   std r4, _XER(r1)
+   mr  r4, r12
+   addir6, r1 ,STACK_FRAME_OVERHEAD
 
-_GLOBAL_TOC(ftrace_caller)
-   /* Taken from output of objdump from lib64/glibc */
-   mflrr3
-   ld  r11, 0(r1)
-   stdur1, -112(r1)
-   std r3, 128(r1)
-   ld  r4, 16(r11)
-   subir3, r3, MCOUNT_INSN_SIZE
 .globl ftrace_call
 ftrace_call:
bl  ftrace_stub
nop
+
+   ld  r3, _NIP(r1)
+   mtlrr3
+
+   REST_8GPRS(0,r1)
+   REST_8GPRS(8,r1)
+   REST_8GPRS(16,r1)
+   REST_8GPRS(24,r1)
+
+   addi r1, r1, SWITCH_FRAME_SIZE
+
+   ld  r12, 16(r1) // get caller's adress
+   mr  r2,r0   // restore callee's TOC
+   mflrr0  // move this LR to CTR
+   mtctr   r0
+   mr  r0,r12  // restore callee's lr at _mcount site
+   mtlrr0
+   bctr// jump after _mcount site
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 .globl ftrace_graph_call

[RESEND PATCH 1/4] ppc64 FTRACE_WITH_REGS implementation

2015-06-18 Thread Torsten Duwe
Implement FTRACE_WITH_REGS for powerpc64, on ELF ABI v2.
Initial work started by Vojtech Pavlik, used with permission.

  * arch/powerpc/kernel/entry_64.S:
- enhance _mcount with a stub to test (ftrace_trace_function == 
&ftrace_stub)
  as suggested in Documentation/trace/ftrace-design.txt
  (for reference only, patched out at runtime)
- Implement an effective ftrace_caller that works from within the kernel
  binary as well as from modules.
  * arch/powerpc/kernel/ftrace.c:
- be prepared to deal with ppc64 ELV ABI v2, especially calls to _mcount
  that result from gcc -mprofile-kernel
  * arch/powerpc/kernel/module_64.c:
- do not save the TOC pointer on the trampoline when the destination
  is ftrace_caller. This trampoline jump happens from a function prologue
  before a new stack frame is set up, so bad things may happen otherwise...
- relax is_module_trampoline() to recognise the modified trampoline.

Signed-off-by: Torsten Duwe 
--
 arch/powerpc/include/asm/ftrace.h |5 +
 arch/powerpc/kernel/entry_64.S|  112 +++---
 arch/powerpc/kernel/ftrace.c  |   67 --
 arch/powerpc/kernel/module_64.c   |   33 ++-
 4 files changed, 186 insertions(+), 31 deletions(-)
--
diff --git a/arch/powerpc/include/asm/ftrace.h 
b/arch/powerpc/include/asm/ftrace.h
index e366187..691 100644
--- a/arch/powerpc/include/asm/ftrace.h
+++ b/arch/powerpc/include/asm/ftrace.h
@@ -46,6 +46,8 @@
 extern void _mcount(void);
 
 #ifdef CONFIG_DYNAMIC_FTRACE
+# define FTRACE_ADDR ((unsigned long)ftrace_caller+8)
+# define FTRACE_REGS_ADDR FTRACE_ADDR
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
/* reloction of mcount call site is the same as the address */
@@ -58,6 +60,9 @@ struct dyn_arch_ftrace {
 #endif /*  CONFIG_DYNAMIC_FTRACE */
 #endif /* __ASSEMBLY__ */
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+#define ARCH_SUPPORTS_FTRACE_OPS 1
+#endif
 #endif
 
 #if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64) && 
!defined(__ASSEMBLY__)
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index d180caf..a4132ef 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -1152,32 +1152,107 @@ _GLOBAL(enter_prom)
 
 #ifdef CONFIG_FUNCTION_TRACER
 #ifdef CONFIG_DYNAMIC_FTRACE
-_GLOBAL(mcount)
+
+#define TOCSAVE 24
+
 _GLOBAL(_mcount)
-   blr
+   nop // REQUIRED for ftrace, to calculate local/global entry diff
+.localentry _mcount,.-_mcount
+   mflrr0
+   mtctr   r0
+
+   LOAD_REG_ADDR_PIC(r12,ftrace_trace_function)
+   ld  r12,0(r12)
+   LOAD_REG_ADDR_PIC(r0,ftrace_stub)
+   cmpdr0,r12
+   ld  r0,LRSAVE(r1)
+   bne-2f
+
+   mtlrr0
+   bctr
+
+2: /* here we have (*ftrace_trace_function)() in r12,
+  "selfpc" in CTR
+  and "frompc" in r0 */
+
+   mtlrr0
+   bctr
+
+_GLOBAL(ftrace_caller)
+   mr  r0,r2   // global (module) call: save module TOC
+   b   1f
+.localentry ftrace_caller,.-ftrace_caller
+   mr  r0,r2   // local call: callee's TOC == our TOC
+   b   2f
+
+1: addis   r2,r12,(.TOC.-0b)@ha
+   addir2,r2,(.TOC.-0b)@l
+
+2: // Here we have our proper TOC ptr in R2,
+   // and the one we need to restore on return in r0.
+
+   ld  r12, 16(r1) // get caller's adress
+
+   stdur1,-SWITCH_FRAME_SIZE(r1)
+
+   std r12, _LINK(r1)
+   SAVE_8GPRS(0,r1)
+   std r0,TOCSAVE(r1)
+   SAVE_8GPRS(8,r1)
+   SAVE_8GPRS(16,r1)
+   SAVE_8GPRS(24,r1)
+
+
+   LOAD_REG_IMMEDIATE(r3,function_trace_op)
+   ld  r5,0(r3)
+
+   mflrr3
+   std r3, _NIP(r1)
+   std r3, 16(r1)
+   subir3, r3, MCOUNT_INSN_SIZE
+   mfmsr   r4
+   std r4, _MSR(r1)
+   mfctr   r4
+   std r4, _CTR(r1)
+   mfxer   r4
+   std r4, _XER(r1)
+   mr  r4, r12
+   addir6, r1 ,STACK_FRAME_OVERHEAD
 
-_GLOBAL_TOC(ftrace_caller)
-   /* Taken from output of objdump from lib64/glibc */
-   mflrr3
-   ld  r11, 0(r1)
-   stdur1, -112(r1)
-   std r3, 128(r1)
-   ld  r4, 16(r11)
-   subir3, r3, MCOUNT_INSN_SIZE
 .globl ftrace_call
 ftrace_call:
bl  ftrace_stub
nop
+
+   ld  r3, _NIP(r1)
+   mtlrr3
+
+   REST_8GPRS(0,r1)
+   REST_8GPRS(8,r1)
+   REST_8GPRS(16,r1)
+   REST_8GPRS(24,r1)
+
+   addi r1, r1, SWITCH_FRAME_SIZE
+
+   ld  r12, 16(r1) // get caller's adress
+   mr  r2,r0   // restore callee's TOC
+   mflrr0  // move this LR to CTR
+   mtctr   r0
+   mr  r0,r12  // restore callee's lr at _mcount site
+   mtlrr0
+   bctr// jump after _mcount site
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 .globl ftrace_graph_call

Re: [RESEND PATCH 1/4] ppc64 FTRACE_WITH_REGS implementation

2015-06-18 Thread Steven Rostedt
On Thu, 18 Jun 2015 18:21:07 +0200
Torsten Duwe  wrote:

> + 
>  _GLOBAL(ftrace_stub)
> + nop
> + nop
> +.localentry ftrace_stub,.-ftrace_stub

You might want to run checkpatch and fix your whitespace errors.

-- Steve

>   blr
>  #else
>  _GLOBAL_TOC(_mcount)
> @@ -1211,12 +1286,12 @@ _GLOBAL(ftrace_stub)
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [RESEND PATCH 1/4] ppc64 FTRACE_WITH_REGS implementation

2015-06-19 Thread Torsten Duwe
On Thu, Jun 18, 2015 at 12:49:00PM -0400, Steven Rostedt wrote:
> On Thu, 18 Jun 2015 18:21:07 +0200
> Torsten Duwe  wrote:
> 
> > +   
> >  _GLOBAL(ftrace_stub)
> > +   nop
> > +   nop
> > +.localentry ftrace_stub,.-ftrace_stub  
> 
> You might want to run checkpatch and fix your whitespace errors.

Right. Will do.
Thanks,

Torsten

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [RESEND PATCH 1/4] ppc64 FTRACE_WITH_REGS implementation

2015-06-19 Thread Steven Rostedt
On Thu, 18 Jun 2015 18:21:07 +0200
Torsten Duwe  wrote:

> Implement FTRACE_WITH_REGS for powerpc64, on ELF ABI v2.
> Initial work started by Vojtech Pavlik, used with permission.
> 
>   * arch/powerpc/kernel/entry_64.S:
> - enhance _mcount with a stub to test (ftrace_trace_function == 
> &ftrace_stub)
>   as suggested in Documentation/trace/ftrace-design.txt
>   (for reference only, patched out at runtime)
> - Implement an effective ftrace_caller that works from within the kernel
>   binary as well as from modules.
>   * arch/powerpc/kernel/ftrace.c:
> - be prepared to deal with ppc64 ELV ABI v2, especially calls to _mcount
>   that result from gcc -mprofile-kernel
>   * arch/powerpc/kernel/module_64.c:
> - do not save the TOC pointer on the trampoline when the destination
>   is ftrace_caller. This trampoline jump happens from a function prologue
>   before a new stack frame is set up, so bad things may happen 
> otherwise...
> - relax is_module_trampoline() to recognise the modified trampoline.
> 
> Signed-off-by: Torsten Duwe 
> --

FYI, the standard notation after the change log is '---' not '--'. That
way git will chop off this from the change log. When I did a git am -s
on this patch I had:

Signed-off-by: Torsten Duwe 
--
 arch/powerpc/include/asm/ftrace.h |5 +
 arch/powerpc/kernel/entry_64.S|  112 
+++---
 arch/powerpc/kernel/ftrace.c  |   67 --
 arch/powerpc/kernel/module_64.c   |   33 ++-
 4 files changed, 186 insertions(+), 31 deletions(-)
--
Signed-off-by: Steven Rostedt 

-- Steve


>  arch/powerpc/include/asm/ftrace.h |5 +
>  arch/powerpc/kernel/entry_64.S|  112 
> +++---
>  arch/powerpc/kernel/ftrace.c  |   67 --
>  arch/powerpc/kernel/module_64.c   |   33 ++-
>  4 files changed, 186 insertions(+), 31 deletions(-)
> --
> diff --git a/arch/powerpc/include/asm/ftrace.h 
> b/arch/powerpc/include/asm/ftrace.h
> index e366187..691 100644
> --- a/arch/powerpc/include/asm/ftrace.h
> +++ b/arch/powerpc/include/asm/ftrace.h
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev