All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v9 00/10] ftrace for MIPS
@ 2009-11-20 12:28 Wu Zhangjin
  2009-11-20 12:34 ` [PATCH v9 01/10] tracing: add static function tracer support " Wu Zhangjin
                   ` (9 more replies)
  0 siblings, 10 replies; 24+ messages in thread
From: Wu Zhangjin @ 2009-11-20 12:28 UTC (permalink / raw)
  To: Ralf Baechle, rostedt
  Cc: Nicholas Mc Guire, zhangfx, Wu Zhangjin, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

From: Wu Zhangjin <wuzhangjin@gmail.com>

After getting the feedback of v8 revision from Thomas, I have written a
cnt3_to_63() based sched_clock() for MIPS and send it out as a standalone
patch("MIPS: Add a high precision sched_clock() via cnt32_to_63()").

This v9 revision only reserve the Ftrace parts. So, Steven or Ralf, Is it time
to apply it? Thanks!

Best Regards,
     Wu Zhangjin

Wu Zhangjin (10):
  tracing: add static function tracer support for MIPS
  tracing: enable HAVE_FUNCTION_TRACE_MCOUNT_TEST for MIPS
  tracing: add an endian argument to scripts/recordmcount.pl
  tracing: add dynamic function tracer support for MIPS
  tracing: add IRQENTRY_EXIT section for MIPS
  tracing: add function graph tracer support for MIPS
  tracing: add dynamic function graph tracer for MIPS
  tracing: make ftrace for MIPS work without -fno-omit-frame-pointer
  tracing: reserve $12(t0) for mcount-ra-address of gcc 4.5
  tracing: make function graph tracer work with -mmcount-ra-address

 arch/mips/Kconfig              |    5 +
 arch/mips/Makefile             |    9 ++
 arch/mips/include/asm/ftrace.h |   91 +++++++++++++-
 arch/mips/include/asm/irq.h    |   29 +----
 arch/mips/kernel/Makefile      |    7 +
 arch/mips/kernel/ftrace.c      |  275 ++++++++++++++++++++++++++++++++++++++++
 arch/mips/kernel/irq.c         |   30 +++++
 arch/mips/kernel/mcount.S      |  189 +++++++++++++++++++++++++++
 arch/mips/kernel/mips_ksyms.c  |    5 +
 arch/mips/kernel/smp.c         |    3 +-
 arch/mips/kernel/smtc.c        |   21 ++-
 arch/mips/kernel/vmlinux.lds.S |    1 +
 arch/mips/sgi-ip22/ip22-int.c  |    3 +-
 arch/mips/sgi-ip22/ip22-time.c |    3 +-
 scripts/Makefile.build         |    1 +
 scripts/recordmcount.pl        |   60 ++++++++-
 16 files changed, 691 insertions(+), 41 deletions(-)
 create mode 100644 arch/mips/kernel/ftrace.c
 create mode 100644 arch/mips/kernel/mcount.S


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v9 01/10] tracing: add static function tracer support for MIPS
  2009-11-20 12:28 [PATCH v9 00/10] ftrace for MIPS Wu Zhangjin
@ 2009-11-20 12:34 ` Wu Zhangjin
  2009-11-20 17:22   ` Ralf Baechle
  2009-11-20 12:34 ` [PATCH v9 02/10] tracing: enable HAVE_FUNCTION_TRACE_MCOUNT_TEST " Wu Zhangjin
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 24+ messages in thread
From: Wu Zhangjin @ 2009-11-20 12:34 UTC (permalink / raw)
  To: Ralf Baechle, rostedt
  Cc: Nicholas Mc Guire, zhangfx, Wu Zhangjin, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

From: Wu Zhangjin <wuzhangjin@gmail.com>

If -pg of gcc is enabled with CONFIG_FUNCTION_TRACER=y. a calling to
_mcount will be inserted into each kernel function. so, there is a
possibility to trace the kernel functions in _mcount.

This patch add the MIPS specific _mcount support for static function
tracing. by default, ftrace_trace_function is initialized as
ftrace_stub(an empty function), so, the default _mcount will introduce
very little overhead. after enabling ftrace in user-space, it will jump
to a real tracing function and do static function tracing for us.

and -ffunction-sections is incompatible with -pg, so, disable it when
ftracer is enabled.

Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/Kconfig              |    1 +
 arch/mips/Makefile             |    2 +
 arch/mips/include/asm/ftrace.h |   25 +++++++++++-
 arch/mips/kernel/Makefile      |    6 +++
 arch/mips/kernel/mcount.S      |   83 ++++++++++++++++++++++++++++++++++++++++
 arch/mips/kernel/mips_ksyms.c  |    5 ++
 6 files changed, 121 insertions(+), 1 deletions(-)
 create mode 100644 arch/mips/kernel/mcount.S

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 03bd56a..6b33e88 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -4,6 +4,7 @@ config MIPS
 	select HAVE_IDE
 	select HAVE_OPROFILE
 	select HAVE_ARCH_KGDB
+	select HAVE_FUNCTION_TRACER
 	# Horrible source of confusion.  Die, die, die ...
 	select EMBEDDED
 	select RTC_LIB if !LEMOTE_FULOONG2E
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 77f5021..0a2073e 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -48,7 +48,9 @@ ifneq ($(SUBARCH),$(ARCH))
   endif
 endif
 
+ifndef CONFIG_FUNCTION_TRACER
 cflags-y := -ffunction-sections
+endif
 cflags-y += $(call cc-option, -mno-check-zero-division)
 
 ifdef CONFIG_32BIT
diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h
index 40a8c17..5f8ebcf 100644
--- a/arch/mips/include/asm/ftrace.h
+++ b/arch/mips/include/asm/ftrace.h
@@ -1 +1,24 @@
-/* empty */
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive for
+ * more details.
+ *
+ * Copyright (C) 2009 DSLab, Lanzhou University, China
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ */
+
+#ifndef _ASM_MIPS_FTRACE_H
+#define _ASM_MIPS_FTRACE_H
+
+#ifdef CONFIG_FUNCTION_TRACER
+
+#define MCOUNT_ADDR ((unsigned long)(_mcount))
+#define MCOUNT_INSN_SIZE 4		/* sizeof mcount call */
+
+#ifndef __ASSEMBLY__
+extern void _mcount(void);
+#define mcount _mcount
+
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_FUNCTION_TRACER */
+#endif /* _ASM_MIPS_FTRACE_H */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 8e26e9c..67ac1f2 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -8,6 +8,10 @@ obj-y		+= cpu-probe.o branch.o entry.o genex.o irq.o process.o \
 		   ptrace.o reset.o setup.o signal.o syscall.o \
 		   time.o topology.o traps.o unaligned.o watch.o
 
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_early_printk.o = -pg
+endif
+
 obj-$(CONFIG_CEVT_BCM1480)	+= cevt-bcm1480.o
 obj-$(CONFIG_CEVT_R4K_LIB)	+= cevt-r4k.o
 obj-$(CONFIG_MIPS_MT_SMTC)	+= cevt-smtc.o
@@ -24,6 +28,8 @@ obj-$(CONFIG_SYNC_R4K)		+= sync-r4k.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
 
+obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o
+
 obj-$(CONFIG_CPU_LOONGSON2)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_MIPS32)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_MIPS64)	+= r4k_fpu.o r4k_switch.o
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
new file mode 100644
index 0000000..cebcc3c
--- /dev/null
+++ b/arch/mips/kernel/mcount.S
@@ -0,0 +1,83 @@
+/*
+ * MIPS specific _mcount support
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive for
+ * more details.
+ *
+ * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ */
+
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/ftrace.h>
+
+	.text
+	.set noreorder
+	.set noat
+
+	.macro MCOUNT_SAVE_REGS
+	PTR_SUBU	sp, PT_SIZE
+	PTR_S	ra, PT_R31(sp)
+	PTR_S	AT, PT_R1(sp)
+	PTR_S	a0, PT_R4(sp)
+	PTR_S	a1, PT_R5(sp)
+	PTR_S	a2, PT_R6(sp)
+	PTR_S	a3, PT_R7(sp)
+#ifdef CONFIG_64BIT
+	PTR_S	a4, PT_R8(sp)
+	PTR_S	a5, PT_R9(sp)
+	PTR_S	a6, PT_R10(sp)
+	PTR_S	a7, PT_R11(sp)
+#endif
+	.endm
+
+	.macro MCOUNT_RESTORE_REGS
+	PTR_L	ra, PT_R31(sp)
+	PTR_L	AT, PT_R1(sp)
+	PTR_L	a0, PT_R4(sp)
+	PTR_L	a1, PT_R5(sp)
+	PTR_L	a2, PT_R6(sp)
+	PTR_L	a3, PT_R7(sp)
+#ifdef CONFIG_64BIT
+	PTR_L	a4, PT_R8(sp)
+	PTR_L	a5, PT_R9(sp)
+	PTR_L	a6, PT_R10(sp)
+	PTR_L	a7, PT_R11(sp)
+#endif
+#ifdef CONFIG_64BIT
+	PTR_ADDIU	sp, PT_SIZE
+#else
+	PTR_ADDIU	sp, (PT_SIZE + 8)
+#endif
+.endm
+
+	.macro RETURN_BACK
+	jr ra
+	 move ra, AT
+	.endm
+
+NESTED(_mcount, PT_SIZE, ra)
+	PTR_LA	t0, ftrace_stub
+	PTR_L	t1, ftrace_trace_function /* Prepare t1 for (1) */
+	bne	t0, t1, static_trace
+	 nop
+	b	ftrace_stub
+	 nop
+
+static_trace:
+	MCOUNT_SAVE_REGS
+
+	move	a0, ra		/* arg1: next ip, selfaddr */
+	jalr	t1	/* (1) call *ftrace_trace_function */
+	 move	a1, AT		/* arg2: the caller's next ip, parent */
+
+	MCOUNT_RESTORE_REGS
+	.globl ftrace_stub
+ftrace_stub:
+	RETURN_BACK
+	END(_mcount)
+
+	.set at
+	.set reorder
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 225755d..1d04807 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -13,6 +13,7 @@
 #include <asm/checksum.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
+#include <asm/ftrace.h>
 
 extern void *__bzero(void *__s, size_t __count);
 extern long __strncpy_from_user_nocheck_asm(char *__to,
@@ -51,3 +52,7 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
 EXPORT_SYMBOL(__csum_partial_copy_user);
 
 EXPORT_SYMBOL(invalid_pte_table);
+#ifdef CONFIG_FUNCTION_TRACER
+/* _mcount is defined in arch/mips/kernel/mcount.S */
+EXPORT_SYMBOL(_mcount);
+#endif
-- 
1.6.2.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v9 02/10] tracing: enable HAVE_FUNCTION_TRACE_MCOUNT_TEST for MIPS
  2009-11-20 12:28 [PATCH v9 00/10] ftrace for MIPS Wu Zhangjin
  2009-11-20 12:34 ` [PATCH v9 01/10] tracing: add static function tracer support " Wu Zhangjin
@ 2009-11-20 12:34 ` Wu Zhangjin
  2009-11-20 17:22   ` Ralf Baechle
  2009-11-20 12:34 ` [PATCH v9 03/10] tracing: add an endian argument to scripts/recordmcount.pl Wu Zhangjin
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 24+ messages in thread
From: Wu Zhangjin @ 2009-11-20 12:34 UTC (permalink / raw)
  To: Ralf Baechle, rostedt
  Cc: Nicholas Mc Guire, zhangfx, Wu Zhangjin, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

From: Wu Zhangjin <wuzhangjin@gmail.com>

There is an exisiting common ftrace_test_stop_func() in
kernel/trace/ftrace.c, which is used to check the global variable
ftrace_trace_stop to determine whether stop the function tracing.

This patch implepment the MIPS specific one to speedup the procedure.

Thanks goes to Zhang Le for Cleaning it up.

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/Kconfig         |    1 +
 arch/mips/kernel/mcount.S |    3 +++
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 6b33e88..a9bd992 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -5,6 +5,7 @@ config MIPS
 	select HAVE_OPROFILE
 	select HAVE_ARCH_KGDB
 	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	# Horrible source of confusion.  Die, die, die ...
 	select EMBEDDED
 	select RTC_LIB if !LEMOTE_FULOONG2E
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index cebcc3c..cbb45ed 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -59,6 +59,9 @@
 	.endm
 
 NESTED(_mcount, PT_SIZE, ra)
+	lw	t0, function_trace_stop
+	bnez	t0, ftrace_stub
+	 nop
 	PTR_LA	t0, ftrace_stub
 	PTR_L	t1, ftrace_trace_function /* Prepare t1 for (1) */
 	bne	t0, t1, static_trace
-- 
1.6.2.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v9 03/10] tracing: add an endian argument to scripts/recordmcount.pl
  2009-11-20 12:28 [PATCH v9 00/10] ftrace for MIPS Wu Zhangjin
  2009-11-20 12:34 ` [PATCH v9 01/10] tracing: add static function tracer support " Wu Zhangjin
  2009-11-20 12:34 ` [PATCH v9 02/10] tracing: enable HAVE_FUNCTION_TRACE_MCOUNT_TEST " Wu Zhangjin
@ 2009-11-20 12:34 ` Wu Zhangjin
  2009-11-20 17:20   ` Ralf Baechle
  2009-12-03 17:45   ` Steven Rostedt
  2009-11-20 12:34 ` [PATCH v9 04/10] tracing: add dynamic function tracer support for MIPS Wu Zhangjin
                   ` (6 subsequent siblings)
  9 siblings, 2 replies; 24+ messages in thread
From: Wu Zhangjin @ 2009-11-20 12:34 UTC (permalink / raw)
  To: Ralf Baechle, rostedt
  Cc: Nicholas Mc Guire, zhangfx, Wu Zhangjin, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips,
	Wu Zhangjin

From: Wu Zhangjin <wuzhangjin@gmail.com>

MIPS and some other architectures need this argument to handle
big/little endian respectively.

Signed-off-by: Wu Zhangjin <wuzj@lemote.com>
---
 scripts/Makefile.build  |    1 +
 scripts/recordmcount.pl |    6 +++---
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 341b589..0b94d2f 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -207,6 +207,7 @@ endif
 
 ifdef CONFIG_FTRACE_MCOUNT_RECORD
 cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
+	"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
 	"$(if $(CONFIG_64BIT),64,32)" \
 	"$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
 	"$(if $(part-of-module),1,0)" "$(@)";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index f0d1445..24604d4 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -113,13 +113,13 @@ $P =~ s@.*/@@g;
 
 my $V = '0.1';
 
-if ($#ARGV != 10) {
-	print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
+if ($#ARGV != 11) {
+	print "usage: $P arch endian bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
 	print "version: $V\n";
 	exit(1);
 }
 
-my ($arch, $bits, $objdump, $objcopy, $cc,
+my ($arch, $endian, $bits, $objdump, $objcopy, $cc,
     $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV;
 
 # This file refers to mcount and shouldn't be ftraced, so lets' ignore it
-- 
1.6.2.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v9 04/10] tracing: add dynamic function tracer support for MIPS
  2009-11-20 12:28 [PATCH v9 00/10] ftrace for MIPS Wu Zhangjin
                   ` (2 preceding siblings ...)
  2009-11-20 12:34 ` [PATCH v9 03/10] tracing: add an endian argument to scripts/recordmcount.pl Wu Zhangjin
@ 2009-11-20 12:34 ` Wu Zhangjin
  2009-11-20 17:23   ` Ralf Baechle
  2009-12-03 17:54   ` Steven Rostedt
  2009-11-20 12:34 ` [PATCH v9 05/10] tracing: add IRQENTRY_EXIT section " Wu Zhangjin
                   ` (5 subsequent siblings)
  9 siblings, 2 replies; 24+ messages in thread
From: Wu Zhangjin @ 2009-11-20 12:34 UTC (permalink / raw)
  To: Ralf Baechle, rostedt
  Cc: Nicholas Mc Guire, zhangfx, Wu Zhangjin, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

From: Wu Zhangjin <wuzhangjin@gmail.com>

With dynamic function tracer, by default, _mcount is defined as an
"empty" function, it returns directly without any more action . When
enabling it in user-space, it will jump to a real tracing
function(ftrace_caller), and do the real job for us.

Differ from the static function tracer, dynamic function tracer provides
two functions ftrace_make_call()/ftrace_make_nop() to enable/disable the
tracing of some indicated kernel functions(set_ftrace_filter).

In the -v4 version, the implementation of this support is basically the same as
X86 version does: _mcount is implemented as an empty function and ftrace_caller
is implemented as a real tracing function respectively.

But in this version, to support module tracing with the help of
-mlong-calls in arch/mips/Makefile:

MODFLAGS += -mlong-calls.

The stuff becomes a little more complex. We need to cope with two
different type of calling to _mcount.

For the kernel part, the calling to _mcount(result of "objdump -hdr
vmlinux"). is like this:

	108:   03e0082d        move    at,ra
	10c:   0c000000        jal     0 <fpcsr_pending>
                        10c: R_MIPS_26  _mcount
                        10c: R_MIPS_NONE        *ABS*
                        10c: R_MIPS_NONE        *ABS*
	110:   00020021        nop

For the module with -mlong-calls, it looks like this:

	c:	3c030000 	lui	v1,0x0
			c: R_MIPS_HI16	_mcount
			c: R_MIPS_NONE	*ABS*
			c: R_MIPS_NONE	*ABS*
	10:	64630000 	daddiu	v1,v1,0
			10: R_MIPS_LO16	_mcount
			10: R_MIPS_NONE	*ABS*
			10: R_MIPS_NONE	*ABS*
	14:	03e0082d 	move	at,ra
	18:	0060f809 	jalr	v1

In the kernel version, there is only one "_mcount" string for every
kernel function, so, we just need to match this one in mcount_regex of
scripts/recordmcount.pl, but in the module version, we need to choose
one of the two to match. Herein, I choose the first one with
"R_MIPS_HI16 _mcount".

and In the kernel verion, without module tracing support, we just need
to replace "jal _mcount" by "jal ftrace_caller" to do real tracing, and
filter the tracing of some kernel functions via replacing it by a nop
instruction.

but as we have described before, the instruction "jal ftrace_caller" only left
32bit length for the address of ftrace_caller, it will fail when calling from
the module space. so, herein, we must replace something else.

the basic idea is loading the address of ftrace_caller to v1 via changing these
two instructions:

	lui	v1,0x0
	addiu	v1,v1,0

If we want to enable the tracing, we need to replace the above instructions to:

	lui	v1, HI_16BIT_ftrace_caller
	addiu	v1, v1, LOW_16BIT_ftrace_caller

If we want to stop the tracing of the indicated kernel functions, we
just need to replace the "jalr v1" to a nop instruction. but we need to
replace two instructions and encode the above two instructions
oursevles.

Is there a simpler solution? Yes! Here it is, in this version, we put _mcount
and ftrace_caller together, which means the address of _mcount and
ftrace_caller is the same:

_mcount:
ftrace_caller:
	j	ftrace_stub
	 nop

	...(do real tracing here)...

ftrace_stub:
	jr	ra
	 move	ra, at

By default, the kernel functions call _mcount, and then jump to ftrace_stub and
return. and when we want to do real tracing, we just need to remove that "j
ftrace_stub", and it will run through the two "nop" instructions and then do
the real tracing job.

what about filtering job? we just need to do this:

	 lui v1, hi_16bit_of_mcount        <--> b 1f (0x10000004)
	 addiu v1, v1, low_16bit_of_mcount
	 move at, ra
	 jalr v1
	 nop
	 				     1f: (rec->ip + 12)

In linux-mips64, there will be some local symbols, whose name are
prefixed by $L, which need to be filtered. thanks goes to Steven for
writing the mips64-specific function_regex.

In a conclusion, with RISC, things becomes easier with such a "stupid"
trick, RISC is something like K.I.S.S, and also, there are lots of
"simple" tricks in the whole ftrace support, thanks goes to Steven and
the other folks for providing such a wonderful tracing framework!

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/Kconfig              |    2 +
 arch/mips/include/asm/ftrace.h |    9 +++
 arch/mips/kernel/Makefile      |    3 +-
 arch/mips/kernel/ftrace.c      |  112 ++++++++++++++++++++++++++++++++++++++++
 arch/mips/kernel/mcount.S      |   29 ++++++++++
 scripts/recordmcount.pl        |   54 +++++++++++++++++++
 6 files changed, 208 insertions(+), 1 deletions(-)
 create mode 100644 arch/mips/kernel/ftrace.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index a9bd992..147fbbc 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -6,6 +6,8 @@ config MIPS
 	select HAVE_ARCH_KGDB
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	select HAVE_DYNAMIC_FTRACE
+	select HAVE_FTRACE_MCOUNT_RECORD
 	# Horrible source of confusion.  Die, die, die ...
 	select EMBEDDED
 	select RTC_LIB if !LEMOTE_FULOONG2E
diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h
index 5f8ebcf..7094a40 100644
--- a/arch/mips/include/asm/ftrace.h
+++ b/arch/mips/include/asm/ftrace.h
@@ -19,6 +19,15 @@
 extern void _mcount(void);
 #define mcount _mcount
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	return addr;
+}
+
+struct dyn_arch_ftrace {
+};
+#endif /*  CONFIG_DYNAMIC_FTRACE */
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_FUNCTION_TRACER */
 #endif /* _ASM_MIPS_FTRACE_H */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 67ac1f2..236a972 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -9,6 +9,7 @@ obj-y		+= cpu-probe.o branch.o entry.o genex.o irq.o process.o \
 		   time.o topology.o traps.o unaligned.o watch.o
 
 ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
 endif
 
@@ -28,7 +29,7 @@ obj-$(CONFIG_SYNC_R4K)		+= sync-r4k.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
 
-obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o
+obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o ftrace.o
 
 obj-$(CONFIG_CPU_LOONGSON2)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_MIPS32)	+= r4k_fpu.o r4k_switch.o
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
new file mode 100644
index 0000000..5459a78
--- /dev/null
+++ b/arch/mips/kernel/ftrace.c
@@ -0,0 +1,112 @@
+/*
+ * Code for replacing ftrace calls with jumps.
+ *
+ * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
+ * Copyright (C) 2009 DSLab, Lanzhou University, China
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ *
+ * Thanks goes to Steven Rostedt for writing the original x86 version.
+ */
+
+#include <linux/uaccess.h>
+#include <linux/init.h>
+#include <linux/ftrace.h>
+
+#include <asm/cacheflush.h>
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+#define JAL 0x0c000000		/* jump & link: ip --> ra, jump to target */
+#define ADDR_MASK 0x03ffffff	/*  op_code|addr : 31...26|25 ....0 */
+#define jump_insn_encode(op_code, addr) \
+	((unsigned int)((op_code) | (((addr) >> 2) & ADDR_MASK)))
+
+static unsigned int ftrace_nop = 0x00000000;
+
+static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
+{
+	*(unsigned int *)ip = new_code;
+
+	flush_icache_range(ip, ip + 8);
+
+	return 0;
+}
+
+static int lui_v1;
+static int jal_mcount;
+
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned int new;
+	unsigned long ip = rec->ip;
+
+	/* We have compiled module with -mlong-calls, but compiled the kernel
+	 * without it, we need to cope with them respectively. */
+	if (ip & 0x40000000) {
+		/* record it for ftrace_make_call */
+		if (lui_v1 == 0)
+			lui_v1 = *(unsigned int *)ip;
+
+		/* lui v1, hi_16bit_of_mcount        --> b 1f (0x10000004)
+		 * addiu v1, v1, low_16bit_of_mcount
+		 * move at, ra
+		 * jalr v1
+		 * nop
+		 * 				     1f: (ip + 12)
+		 */
+		new = 0x10000004;
+	} else {
+		/* record/calculate it for ftrace_make_call */
+		if (jal_mcount == 0) {
+			/* We can record it directly like this:
+			 *     jal_mcount = *(unsigned int *)ip;
+			 * Herein, jump over the first two nop instructions */
+			jal_mcount = jump_insn_encode(JAL, (MCOUNT_ADDR + 8));
+		}
+
+		/* move at, ra
+		 * jalr v1		--> nop
+		 */
+		new = ftrace_nop;
+	}
+	return ftrace_modify_code(ip, new);
+}
+
+static int modified;	/* initialized as 0 by default */
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned int new;
+	unsigned long ip = rec->ip;
+
+	/* We just need to remove the "b ftrace_stub" at the fist time! */
+	if (modified == 0) {
+		modified = 1;
+		ftrace_modify_code(addr, ftrace_nop);
+	}
+	/* ip, module: 0xc0000000, kernel: 0x80000000 */
+	new = (ip & 0x40000000) ? lui_v1 : jal_mcount;
+
+	return ftrace_modify_code(ip, new);
+}
+
+#define FTRACE_CALL_IP ((unsigned long)(&ftrace_call))
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned int new;
+
+	new = jump_insn_encode(JAL, (unsigned long)func);
+
+	return ftrace_modify_code(FTRACE_CALL_IP, new);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	/* The return code is retured via data */
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif				/* CONFIG_DYNAMIC_FTRACE */
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index cbb45ed..ffc4259 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -58,6 +58,33 @@
 	 move ra, AT
 	.endm
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+NESTED(ftrace_caller, PT_SIZE, ra)
+	.globl _mcount
+_mcount:
+	b	ftrace_stub
+	 nop
+	lw	t0, function_trace_stop
+	bnez	t0, ftrace_stub
+	 nop
+
+	MCOUNT_SAVE_REGS
+
+	move	a0, ra		/* arg1: next ip, selfaddr */
+	.globl ftrace_call
+ftrace_call:
+	nop	/* a placeholder for the call to a real tracing function */
+	 move	a1, AT		/* arg2: the caller's next ip, parent */
+
+	MCOUNT_RESTORE_REGS
+	.globl ftrace_stub
+ftrace_stub:
+	RETURN_BACK
+	END(ftrace_caller)
+
+#else	/* ! CONFIG_DYNAMIC_FTRACE */
+
 NESTED(_mcount, PT_SIZE, ra)
 	lw	t0, function_trace_stop
 	bnez	t0, ftrace_stub
@@ -82,5 +109,7 @@ ftrace_stub:
 	RETURN_BACK
 	END(_mcount)
 
+#endif	/* ! CONFIG_DYNAMIC_FTRACE */
+
 	.set at
 	.set reorder
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 24604d4..9d80d0d 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -295,6 +295,60 @@ if ($arch eq "x86_64") {
     $ld .= " -m elf64_sparc";
     $cc .= " -m64";
     $objcopy .= " -O elf64-sparc";
+
+} elsif ($arch eq "mips") {
+    # To enable module support, we need to enable the -mlong-calls option
+    # of gcc for module, after using this option, we can not get the real
+    # offset of the calling to _mcount, but the offset of the lui
+    # instruction or the addiu one. herein, we record the address of the
+    # first one, and then we can replace this instruction by a branch
+    # instruction to jump over the profiling function to filter the
+    # indicated functions, or swith back to the lui instruction to trace
+    # them, which means dynamic tracing.
+    #
+    #       c:	3c030000 	lui	v1,0x0
+    #			c: R_MIPS_HI16	_mcount
+    #			c: R_MIPS_NONE	*ABS*
+    #			c: R_MIPS_NONE	*ABS*
+    #      10:	64630000 	daddiu	v1,v1,0
+    #			10: R_MIPS_LO16	_mcount
+    #			10: R_MIPS_NONE	*ABS*
+    #			10: R_MIPS_NONE	*ABS*
+    #      14:	03e0082d 	move	at,ra
+    #      18:	0060f809 	jalr	v1
+    #
+    # for the kernel:
+    #
+    #     10:   03e0082d        move    at,ra
+    #	  14:   0c000000        jal     0 <loongson_halt>
+    #                    14: R_MIPS_26   _mcount
+    #                    14: R_MIPS_NONE *ABS*
+    #                    14: R_MIPS_NONE *ABS*
+    #	 18:   00020021        nop
+    if ($is_module eq "0") {
+	    $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
+    } else {
+	    $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_HI16\\s+_mcount\$";
+    }
+    $objdump .= " -Melf-trad".$endian."mips ";
+
+    if ($endian eq "big") {
+	    $endian = " -EB ";
+	    $ld .= " -melf".$bits."btsmip";
+    } else {
+	    $endian = " -EL ";
+	    $ld .= " -melf".$bits."ltsmip";
+    }
+
+    $cc .= " -mno-abicalls -fno-pic -mabi=" . $bits . $endian;
+    $ld .= $endian;
+
+    if ($bits == 64) {
+	    $function_regex =
+		"^([0-9a-fA-F]+)\\s+<(.|[^\$]L.*?|\$[^L].*?|[^\$][^L].*?)>:";
+	    $type = ".dword";
+    }
+
 } else {
     die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
 }
-- 
1.6.2.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v9 05/10] tracing: add IRQENTRY_EXIT section for MIPS
  2009-11-20 12:28 [PATCH v9 00/10] ftrace for MIPS Wu Zhangjin
                   ` (3 preceding siblings ...)
  2009-11-20 12:34 ` [PATCH v9 04/10] tracing: add dynamic function tracer support for MIPS Wu Zhangjin
@ 2009-11-20 12:34 ` Wu Zhangjin
  2009-11-20 17:23   ` Ralf Baechle
  2009-11-20 12:34 ` [PATCH v9 06/10] tracing: add function graph tracer support " Wu Zhangjin
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 24+ messages in thread
From: Wu Zhangjin @ 2009-11-20 12:34 UTC (permalink / raw)
  To: Ralf Baechle, rostedt
  Cc: Nicholas Mc Guire, zhangfx, Wu Zhangjin, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

From: Wu Zhangjin <wuzhangjin@gmail.com>

This patch add a new section for MIPS to record the block of the hardirq
handling for function graph tracer(print_graph_irq) via adding the
__irq_entry annotation to the the entrypoints of the hardirqs(the block
with irq_enter()...irq_exit()).

Thanks goes to Steven & Frederic Weisbecker for their feedbacks.

Reviewed-by: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/include/asm/irq.h    |   29 ++---------------------------
 arch/mips/kernel/irq.c         |   30 ++++++++++++++++++++++++++++++
 arch/mips/kernel/smp.c         |    3 ++-
 arch/mips/kernel/smtc.c        |   21 ++++++++++++++-------
 arch/mips/kernel/vmlinux.lds.S |    1 +
 arch/mips/sgi-ip22/ip22-int.c  |    3 ++-
 arch/mips/sgi-ip22/ip22-time.c |    3 ++-
 7 files changed, 53 insertions(+), 37 deletions(-)

diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h
index 09b08d0..0696036 100644
--- a/arch/mips/include/asm/irq.h
+++ b/arch/mips/include/asm/irq.h
@@ -113,36 +113,11 @@ do {									\
 
 #endif
 
-/*
- * do_IRQ handles all normal device IRQ's (the special
- * SMP cross-CPU interrupts have their own specific
- * handlers).
- *
- * Ideally there should be away to get this into kernel/irq/handle.c to
- * avoid the overhead of a call for just a tiny function ...
- */
-#define do_IRQ(irq)							\
-do {									\
-	irq_enter();							\
-	__DO_IRQ_SMTC_HOOK(irq);					\
-	generic_handle_irq(irq);					\
-	irq_exit();							\
-} while (0)
+extern void do_IRQ(unsigned int irq);
 
 #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
-/*
- * To avoid inefficient and in some cases pathological re-checking of
- * IRQ affinity, we have this variant that skips the affinity check.
- */
-
 
-#define do_IRQ_no_affinity(irq)						\
-do {									\
-	irq_enter();							\
-	__NO_AFFINITY_IRQ_SMTC_HOOK(irq);				\
-	generic_handle_irq(irq);					\
-	irq_exit();							\
-} while (0)
+extern void do_IRQ_no_affinity(unsigned int irq);
 
 #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
 
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 7b845ba..dee8d5f 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -22,6 +22,7 @@
 #include <linux/seq_file.h>
 #include <linux/kallsyms.h>
 #include <linux/kgdb.h>
+#include <linux/ftrace.h>
 
 #include <asm/atomic.h>
 #include <asm/system.h>
@@ -150,3 +151,32 @@ void __init init_IRQ(void)
 		kgdb_early_setup = 1;
 #endif
 }
+
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+void __irq_entry do_IRQ(unsigned int irq)
+{
+	irq_enter();
+	__DO_IRQ_SMTC_HOOK(irq);
+	generic_handle_irq(irq);
+	irq_exit();
+}
+
+#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
+/*
+ * To avoid inefficient and in some cases pathological re-checking of
+ * IRQ affinity, we have this variant that skips the affinity check.
+ */
+
+void __irq_entry do_IRQ_no_affinity(unsigned int irq)
+{
+	irq_enter();
+	__NO_AFFINITY_IRQ_SMTC_HOOK(irq);
+	generic_handle_irq(irq);
+	irq_exit();
+}
+
+#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index e72e684..6cdca19 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -32,6 +32,7 @@
 #include <linux/cpumask.h>
 #include <linux/cpu.h>
 #include <linux/err.h>
+#include <linux/ftrace.h>
 
 #include <asm/atomic.h>
 #include <asm/cpu.h>
@@ -130,7 +131,7 @@ asmlinkage __cpuinit void start_secondary(void)
 /*
  * Call into both interrupt handlers, as we share the IPI for them
  */
-void smp_call_function_interrupt(void)
+void __irq_entry smp_call_function_interrupt(void)
 {
 	irq_enter();
 	generic_smp_call_function_single_interrupt();
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 24630fd..75034a8 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/module.h>
+#include <linux/ftrace.h>
 
 #include <asm/cpu.h>
 #include <asm/processor.h>
@@ -939,23 +940,29 @@ static void ipi_call_interrupt(void)
 
 DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
 
-void ipi_decode(struct smtc_ipi *pipi)
+static void __irq_entry smtc_clock_tick_interrupt(void)
 {
 	unsigned int cpu = smp_processor_id();
 	struct clock_event_device *cd;
+	int irq = MIPS_CPU_IRQ_BASE + 1;
+
+	irq_enter();
+	kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+	cd = &per_cpu(mips_clockevent_device, cpu);
+	cd->event_handler(cd);
+	irq_exit();
+}
+
+void ipi_decode(struct smtc_ipi *pipi)
+{
 	void *arg_copy = pipi->arg;
 	int type_copy = pipi->type;
-	int irq = MIPS_CPU_IRQ_BASE + 1;
 
 	smtc_ipi_nq(&freeIPIq, pipi);
 
 	switch (type_copy) {
 	case SMTC_CLOCK_TICK:
-		irq_enter();
-		kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
-		cd = &per_cpu(mips_clockevent_device, cpu);
-		cd->event_handler(cd);
-		irq_exit();
+		smtc_clock_tick_interrupt();
 		break;
 
 	case LINUX_SMP_IPI:
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 162b299..f25df73 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -46,6 +46,7 @@ SECTIONS
 		SCHED_TEXT
 		LOCK_TEXT
 		KPROBES_TEXT
+		IRQENTRY_TEXT
 		*(.text.*)
 		*(.fixup)
 		*(.gnu.warning)
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index 0ecd5fe..383f11d 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
+#include <linux/ftrace.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/sgi/hpc3.h>
@@ -150,7 +151,7 @@ static void indy_local1_irqdispatch(void)
 
 extern void ip22_be_interrupt(int irq);
 
-static void indy_buserror_irq(void)
+static void __irq_entry indy_buserror_irq(void)
 {
 	int irq = SGI_BUSERR_IRQ;
 
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index c8f7d23..603fc91 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/time.h>
+#include <linux/ftrace.h>
 
 #include <asm/cpu.h>
 #include <asm/mipsregs.h>
@@ -115,7 +116,7 @@ __init void plat_time_init(void)
 }
 
 /* Generic SGI handler for (spurious) 8254 interrupts */
-void indy_8254timer_irq(void)
+void __irq_entry indy_8254timer_irq(void)
 {
 	int irq = SGI_8254_0_IRQ;
 	ULONG cnt;
-- 
1.6.2.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v9 06/10] tracing: add function graph tracer support for MIPS
  2009-11-20 12:28 [PATCH v9 00/10] ftrace for MIPS Wu Zhangjin
                   ` (4 preceding siblings ...)
  2009-11-20 12:34 ` [PATCH v9 05/10] tracing: add IRQENTRY_EXIT section " Wu Zhangjin
@ 2009-11-20 12:34 ` Wu Zhangjin
  2009-11-20 17:24   ` Ralf Baechle
  2009-11-20 12:34 ` [PATCH v9 07/10] tracing: add dynamic function graph tracer " Wu Zhangjin
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 24+ messages in thread
From: Wu Zhangjin @ 2009-11-20 12:34 UTC (permalink / raw)
  To: Ralf Baechle, rostedt
  Cc: Nicholas Mc Guire, zhangfx, Wu Zhangjin, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

From: Wu Zhangjin <wuzhangjin@gmail.com>

The implementation of function graph tracer for MIPS is a little
different from X86.

in MIPS, gcc(with -pg) only transfer the caller's return address(at) and
the _mcount's return address(ra) to us.

For the kernel part without -mlong-calls:

move at, ra
jal _mcount

For the module part with -mlong-calls:

lui v1, hi16bit_of_mcount
addiu v1, v1, low16bit_of_mcount
move at, ra
jal _mcount

Without -mlong-calls,

if the function is a leaf, it will not save the return address(ra):

ffffffff80101298 <au1k_wait>:
ffffffff80101298:       67bdfff0        daddiu  sp,sp,-16
ffffffff8010129c:       ffbe0008        sd      s8,8(sp)
ffffffff801012a0:       03a0f02d        move    s8,sp
ffffffff801012a4:       03e0082d        move    at,ra
ffffffff801012a8:       0c042930        jal     ffffffff8010a4c0 <_mcount>
ffffffff801012ac:       00020021        nop

so, we can hijack it directly in _mcount, but if the function is non-leaf, the
return address is saved in the stack.

ffffffff80133030 <copy_process>:
ffffffff80133030:       67bdff50        daddiu  sp,sp,-176
ffffffff80133034:       ffbe00a0        sd      s8,160(sp)
ffffffff80133038:       03a0f02d        move    s8,sp
ffffffff8013303c:       ffbf00a8        sd      ra,168(sp)
ffffffff80133040:       ffb70098        sd      s7,152(sp)
ffffffff80133044:       ffb60090        sd      s6,144(sp)
ffffffff80133048:       ffb50088        sd      s5,136(sp)
ffffffff8013304c:       ffb40080        sd      s4,128(sp)
ffffffff80133050:       ffb30078        sd      s3,120(sp)
ffffffff80133054:       ffb20070        sd      s2,112(sp)
ffffffff80133058:       ffb10068        sd      s1,104(sp)
ffffffff8013305c:       ffb00060        sd      s0,96(sp)
ffffffff80133060:       03e0082d        move    at,ra
ffffffff80133064:       0c042930        jal     ffffffff8010a4c0 <_mcount>
ffffffff80133068:       00020021        nop

but we can not get the exact stack address(which saved ra) directly in
_mcount, we need to search the content of at register in the stack space
or search the "s{d,w} ra, offset(sp)" instruction in the text. 'Cause we
can not prove there is only a match in the stack space, so, we search
the text instead.

as we can see, if the first instruction above "move at, ra" is not a
store instruction, there should be a leaf function, so we hijack the at
register directly via putting &return_to_handler into it, otherwise, we
search the "s{d,w} ra, offset(sp)" instruction to get the stack offset,
and then the stack address. we use the above copy_process() as an
example, we at last find "ffbf00a8", 0xa8 is the stack offset, we plus
it with s8(fp), that is the stack address, we hijack the content via
writing the &return_to_handler in.

If with -mlong-calls, since there are two more instructions above "move
at, ra", so, we can move the pointer to the position above "lui v1,
hi16bit_of_mcount".

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/Kconfig         |    1 +
 arch/mips/kernel/ftrace.c |  106 +++++++++++++++++++++++++++++++++++++++++++++
 arch/mips/kernel/mcount.S |   42 ++++++++++++++++++
 3 files changed, 149 insertions(+), 0 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 147fbbc..de690fd 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -8,6 +8,7 @@ config MIPS
 	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_FUNCTION_GRAPH_TRACER
 	# Horrible source of confusion.  Die, die, die ...
 	select EMBEDDED
 	select RTC_LIB if !LEMOTE_FULOONG2E
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index 5459a78..65a3f8a 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -13,6 +13,8 @@
 #include <linux/ftrace.h>
 
 #include <asm/cacheflush.h>
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 
@@ -110,3 +112,107 @@ int __init ftrace_dyn_arch_init(void *data)
 	return 0;
 }
 #endif				/* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+#define S_RA_SP	(0xafbf << 16)	/* s{d,w} ra, offset(sp) */
+#define S_R_SP	(0xafb0 << 16)  /* s{d,w} R, offset(sp) */
+#define OFFSET_MASK	0xffff	/* stack offset range: 0 ~ PT_SIZE */
+
+unsigned long ftrace_get_parent_addr(unsigned long self_addr,
+				     unsigned long parent,
+				     unsigned long parent_addr,
+				     unsigned long fp)
+{
+	unsigned long sp, ip, ra;
+	unsigned int code;
+
+	/* in module or kernel? */
+	if (self_addr & 0x40000000) {
+		/* module: move to the instruction "lui v1, HI_16BIT_OF_MCOUNT" */
+		ip = self_addr - 20;
+	} else {
+		/* kernel: move to the instruction "move ra, at" */
+		ip = self_addr - 12;
+	}
+
+	/* search the text until finding the non-store instruction or "s{d,w}
+	 * ra, offset(sp)" instruction */
+	do {
+		ip -= 4;
+
+		/* get the code at "ip" */
+		code = *(unsigned int *)ip;
+
+		/* If we hit the non-store instruction before finding where the
+		 * ra is stored, then this is a leaf function and it does not
+		 * store the ra on the stack. */
+		if ((code & S_R_SP) != S_R_SP)
+			return parent_addr;
+
+	} while (((code & S_RA_SP) != S_RA_SP));
+
+	sp = fp + (code & OFFSET_MASK);
+	ra = *(unsigned long *)sp;
+
+	if (ra == parent)
+		return sp;
+
+	return 0;
+}
+
+/*
+ * Hook the return address and push it in the stack of return addrs
+ * in current thread info.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long fp)
+{
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	unsigned long return_hooker = (unsigned long)
+	    &return_to_handler;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/* "parent" is the stack address saved the return address of the caller
+	 * of _mcount, for a leaf function not save the return address in the
+	 * stack address, so, we "emulate" one in _mcount's stack space, and
+	 * hijack it directly, but for a non-leaf function, it will save the
+	 * return address to the its stack space, so, we can not hijack the
+	 * "parent" directly, but need to find the real stack address,
+	 * ftrace_get_parent_addr() does it!
+	 */
+
+	old = *parent;
+
+	parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old,
+							 (unsigned long)parent,
+							 fp);
+
+	/* If fails when getting the stack address of the non-leaf function's
+	 * ra, stop function graph tracer and return */
+	if (parent == 0) {
+		ftrace_graph_stop();
+		WARN_ON(1);
+		return;
+	}
+
+	*parent = return_hooker;
+
+	if (ftrace_push_return_trace(old, self_addr, &trace.depth, fp) ==
+	    -EBUSY) {
+		*parent = old;
+		return;
+	}
+
+	trace.func = self_addr;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		current->curr_ret_stack--;
+		*parent = old;
+	}
+}
+#endif				/* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index ffc4259..b50e38d 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -93,6 +93,16 @@ NESTED(_mcount, PT_SIZE, ra)
 	PTR_L	t1, ftrace_trace_function /* Prepare t1 for (1) */
 	bne	t0, t1, static_trace
 	 nop
+
+#ifdef	CONFIG_FUNCTION_GRAPH_TRACER
+	PTR_L	t2, ftrace_graph_return
+	bne	t0, t2, ftrace_graph_caller
+	 nop
+	PTR_LA	t0, ftrace_graph_entry_stub
+	PTR_L	t2, ftrace_graph_entry
+	bne	t0, t2, ftrace_graph_caller
+	 nop
+#endif
 	b	ftrace_stub
 	 nop
 
@@ -111,5 +121,37 @@ ftrace_stub:
 
 #endif	/* ! CONFIG_DYNAMIC_FTRACE */
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+NESTED(ftrace_graph_caller, PT_SIZE, ra)
+	MCOUNT_SAVE_REGS
+
+	PTR_LA	a0, PT_R1(sp)	/* arg1: &AT -> a0 */
+	move	a1, ra		/* arg2: next ip, selfaddr */
+	jal	prepare_ftrace_return
+	 move	a2, fp		/* arg3: frame pointer */
+
+	MCOUNT_RESTORE_REGS
+	RETURN_BACK
+	END(ftrace_graph_caller)
+
+	.align	2
+	.globl	return_to_handler
+return_to_handler:
+	PTR_SUBU	sp, PT_SIZE
+	PTR_S	v0, PT_R2(sp)
+
+	jal	ftrace_return_to_handler
+	 PTR_S	v1, PT_R3(sp)
+
+	/* restore the real parent address: v0 -> ra */
+	move	ra, v0
+
+	PTR_L	v0, PT_R2(sp)
+	PTR_L	v1, PT_R3(sp)
+	jr	ra
+	 PTR_ADDIU	sp, PT_SIZE
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
 	.set at
 	.set reorder
-- 
1.6.2.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v9 07/10] tracing: add dynamic function graph tracer for MIPS
  2009-11-20 12:28 [PATCH v9 00/10] ftrace for MIPS Wu Zhangjin
                   ` (5 preceding siblings ...)
  2009-11-20 12:34 ` [PATCH v9 06/10] tracing: add function graph tracer support " Wu Zhangjin
@ 2009-11-20 12:34 ` Wu Zhangjin
  2009-11-20 17:24   ` Ralf Baechle
  2009-11-20 12:34 ` [PATCH v9 08/10] tracing: make ftrace for MIPS work without -fno-omit-frame-pointer Wu Zhangjin
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 24+ messages in thread
From: Wu Zhangjin @ 2009-11-20 12:34 UTC (permalink / raw)
  To: Ralf Baechle, rostedt
  Cc: Nicholas Mc Guire, zhangfx, Wu Zhangjin, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

From: Wu Zhangjin <wuzhangjin@gmail.com>

This patch make function graph tracer work with dynamic function tracer.

To share the source code of dynamic function tracer(MCOUNT_SAVE_REGS),
and avoid restoring the whole saved registers, we need to restore the ra
register from the stack.

(NOTE: This not work with 32bit! need to ensure why!)

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/kernel/ftrace.c |   21 +++++++++++++++++++++
 arch/mips/kernel/mcount.S |   14 ++++++++++++--
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index 65a3f8a..e981a49 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -115,6 +115,27 @@ int __init ftrace_dyn_arch_init(void *data)
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+extern void ftrace_graph_call(void);
+#define JMP	0x08000000	/* jump to target directly */
+#define CALL_FTRACE_GRAPH_CALLER \
+	jump_insn_encode(JMP, (unsigned long)(&ftrace_graph_caller))
+#define FTRACE_GRAPH_CALL_IP	((unsigned long)(&ftrace_graph_call))
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_code(FTRACE_GRAPH_CALL_IP,
+				  CALL_FTRACE_GRAPH_CALLER);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, ftrace_nop);
+}
+
+#endif				/* !CONFIG_DYNAMIC_FTRACE */
+
 #define S_RA_SP	(0xafbf << 16)	/* s{d,w} ra, offset(sp) */
 #define S_R_SP	(0xafb0 << 16)  /* s{d,w} R, offset(sp) */
 #define OFFSET_MASK	0xffff	/* stack offset range: 0 ~ PT_SIZE */
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index b50e38d..98d4690 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -77,6 +77,13 @@ ftrace_call:
 	nop	/* a placeholder for the call to a real tracing function */
 	 move	a1, AT		/* arg2: the caller's next ip, parent */
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.globl ftrace_graph_call
+ftrace_graph_call:
+	nop
+	 nop
+#endif
+
 	MCOUNT_RESTORE_REGS
 	.globl ftrace_stub
 ftrace_stub:
@@ -124,10 +131,13 @@ ftrace_stub:
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
 NESTED(ftrace_graph_caller, PT_SIZE, ra)
+#ifdef CONFIG_DYNAMIC_FTRACE
+	PTR_L	a1, PT_R31(sp)	/* load the original ra from the stack */
+#else
 	MCOUNT_SAVE_REGS
-
-	PTR_LA	a0, PT_R1(sp)	/* arg1: &AT -> a0 */
 	move	a1, ra		/* arg2: next ip, selfaddr */
+#endif
+	PTR_LA	a0, PT_R1(sp)	/* arg1: &AT -> a0 */
 	jal	prepare_ftrace_return
 	 move	a2, fp		/* arg3: frame pointer */
 
-- 
1.6.2.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v9 08/10] tracing: make ftrace for MIPS work without -fno-omit-frame-pointer
  2009-11-20 12:28 [PATCH v9 00/10] ftrace for MIPS Wu Zhangjin
                   ` (6 preceding siblings ...)
  2009-11-20 12:34 ` [PATCH v9 07/10] tracing: add dynamic function graph tracer " Wu Zhangjin
@ 2009-11-20 12:34 ` Wu Zhangjin
  2009-11-20 17:24   ` Ralf Baechle
  2009-11-20 12:34 ` [PATCH v9 09/10] tracing: reserve $12(t0) for mcount-ra-address of gcc 4.5 Wu Zhangjin
  2009-11-20 12:34 ` [PATCH v9 10/10] tracing: make function graph tracer work with -mmcount-ra-address Wu Zhangjin
  9 siblings, 1 reply; 24+ messages in thread
From: Wu Zhangjin @ 2009-11-20 12:34 UTC (permalink / raw)
  To: Ralf Baechle, rostedt
  Cc: Nicholas Mc Guire, zhangfx, Wu Zhangjin, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

From: Wu Zhangjin <wuzhangjin@gmail.com>

When remove the -fno-omit-frame-pointer, gcc will not save the frame
pointer for us, we need to save one ourselves.

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/include/asm/ftrace.h |   57 ++++++++++++++++++++++++++++++++++++++++
 arch/mips/kernel/ftrace.c      |   56 ++++++++++++++++++++++++++++----------
 arch/mips/kernel/mcount.S      |    8 +++++
 3 files changed, 106 insertions(+), 15 deletions(-)

diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h
index 7094a40..3986cd8 100644
--- a/arch/mips/include/asm/ftrace.h
+++ b/arch/mips/include/asm/ftrace.h
@@ -19,6 +19,62 @@
 extern void _mcount(void);
 #define mcount _mcount
 
+#define safe_load(load, src, dst, error)		\
+do {							\
+	asm volatile (					\
+		"1: " load " %[" STR(dst) "], 0(%[" STR(src) "])\n"\
+		"   li %[" STR(error) "], 0\n"		\
+		"2:\n"					\
+							\
+		".section .fixup, \"ax\"\n"		\
+		"3: li %[" STR(error) "], 1\n"		\
+		"   j 2b\n"				\
+		".previous\n"				\
+							\
+		".section\t__ex_table,\"a\"\n\t"	\
+		STR(PTR) "\t1b, 3b\n\t"			\
+		".previous\n"				\
+							\
+		: [dst] "=&r" (dst), [error] "=r" (error)\
+		: [src] "r" (src)			\
+		: "memory"				\
+	);						\
+} while (0)
+
+#define safe_store(store, src, dst, error)	\
+do {						\
+	asm volatile (				\
+		"1: " store " %[" STR(src) "], 0(%[" STR(dst) "])\n"\
+		"   li %[" STR(error) "], 0\n"	\
+		"2:\n"				\
+						\
+		".section .fixup, \"ax\"\n"	\
+		"3: li %[" STR(error) "], 1\n"	\
+		"   j 2b\n"			\
+		".previous\n"			\
+						\
+		".section\t__ex_table,\"a\"\n\t"\
+		STR(PTR) "\t1b, 3b\n\t"		\
+		".previous\n"			\
+						\
+		: [error] "=r" (error)		\
+		: [dst] "r" (dst), [src] "r" (src)\
+		: "memory"			\
+	);					\
+} while (0)
+
+#define safe_load_code(dst, src, error) \
+	safe_load(STR(lw), src, dst, error)
+#define safe_store_code(src, dst, error) \
+	safe_store(STR(sw), src, dst, error)
+
+#define safe_load_stack(dst, src, error) \
+	safe_load(STR(PTR_L), src, dst, error)
+
+#define safe_store_stack(src, dst, error) \
+	safe_store(STR(PTR_S), src, dst, error)
+
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
@@ -27,6 +83,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 
 struct dyn_arch_ftrace {
 };
+
 #endif /*  CONFIG_DYNAMIC_FTRACE */
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_FUNCTION_TRACER */
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index e981a49..e363fc6 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -27,7 +27,13 @@ static unsigned int ftrace_nop = 0x00000000;
 
 static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
 {
-	*(unsigned int *)ip = new_code;
+	int faulted;
+
+	/* *(unsigned int *)ip = new_code; */
+	safe_store_code(new_code, ip, faulted);
+
+	if (unlikely(faulted))
+		return -EFAULT;
 
 	flush_icache_range(ip, ip + 8);
 
@@ -41,14 +47,20 @@ int ftrace_make_nop(struct module *mod,
 		    struct dyn_ftrace *rec, unsigned long addr)
 {
 	unsigned int new;
+	int faulted;
 	unsigned long ip = rec->ip;
 
 	/* We have compiled module with -mlong-calls, but compiled the kernel
 	 * without it, we need to cope with them respectively. */
 	if (ip & 0x40000000) {
 		/* record it for ftrace_make_call */
-		if (lui_v1 == 0)
-			lui_v1 = *(unsigned int *)ip;
+		if (lui_v1 == 0) {
+			/* lui_v1 = *(unsigned int *)ip; */
+			safe_load_code(lui_v1, ip, faulted);
+
+			if (unlikely(faulted))
+				return -EFAULT;
+		}
 
 		/* lui v1, hi_16bit_of_mcount        --> b 1f (0x10000004)
 		 * addiu v1, v1, low_16bit_of_mcount
@@ -147,6 +159,7 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
 {
 	unsigned long sp, ip, ra;
 	unsigned int code;
+	int faulted;
 
 	/* in module or kernel? */
 	if (self_addr & 0x40000000) {
@@ -162,8 +175,11 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
 	do {
 		ip -= 4;
 
-		/* get the code at "ip" */
-		code = *(unsigned int *)ip;
+		/* get the code at "ip": code = *(unsigned int *)ip; */
+		safe_load_code(code, ip, faulted);
+
+		if (unlikely(faulted))
+			return 0;
 
 		/* If we hit the non-store instruction before finding where the
 		 * ra is stored, then this is a leaf function and it does not
@@ -174,11 +190,14 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
 	} while (((code & S_RA_SP) != S_RA_SP));
 
 	sp = fp + (code & OFFSET_MASK);
-	ra = *(unsigned long *)sp;
+
+	/* ra = *(unsigned long *)sp; */
+	safe_load_stack(ra, sp, faulted);
+	if (unlikely(faulted))
+		return 0;
 
 	if (ra == parent)
 		return sp;
-
 	return 0;
 }
 
@@ -193,6 +212,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 	struct ftrace_graph_ent trace;
 	unsigned long return_hooker = (unsigned long)
 	    &return_to_handler;
+	int faulted;
 
 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
 		return;
@@ -206,21 +226,23 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 	 * ftrace_get_parent_addr() does it!
 	 */
 
-	old = *parent;
+	/* old = *parent; */
+	safe_load_stack(old, parent, faulted);
+	if (unlikely(faulted))
+		goto out;
 
 	parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old,
 							 (unsigned long)parent,
 							 fp);
-
 	/* If fails when getting the stack address of the non-leaf function's
 	 * ra, stop function graph tracer and return */
-	if (parent == 0) {
-		ftrace_graph_stop();
-		WARN_ON(1);
-		return;
-	}
+	if (parent == 0)
+		goto out;
 
-	*parent = return_hooker;
+	/* *parent = return_hooker; */
+	safe_store_stack(return_hooker, parent, faulted);
+	if (unlikely(faulted))
+		goto out;
 
 	if (ftrace_push_return_trace(old, self_addr, &trace.depth, fp) ==
 	    -EBUSY) {
@@ -235,5 +257,9 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		current->curr_ret_stack--;
 		*parent = old;
 	}
+	return;
+out:
+	ftrace_graph_stop();
+	WARN_ON(1);
 }
 #endif				/* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index 98d4690..bdfef2c 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -139,7 +139,15 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra)
 #endif
 	PTR_LA	a0, PT_R1(sp)	/* arg1: &AT -> a0 */
 	jal	prepare_ftrace_return
+#ifdef CONFIG_FRAME_POINTER
 	 move	a2, fp		/* arg3: frame pointer */
+#else
+#ifdef CONFIG_64BIT
+	 PTR_LA	a2, PT_SIZE(sp)
+#else
+	 PTR_LA	a2, (PT_SIZE+8)(sp)
+#endif
+#endif
 
 	MCOUNT_RESTORE_REGS
 	RETURN_BACK
-- 
1.6.2.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v9 09/10] tracing: reserve $12(t0) for mcount-ra-address of gcc 4.5
  2009-11-20 12:28 [PATCH v9 00/10] ftrace for MIPS Wu Zhangjin
                   ` (7 preceding siblings ...)
  2009-11-20 12:34 ` [PATCH v9 08/10] tracing: make ftrace for MIPS work without -fno-omit-frame-pointer Wu Zhangjin
@ 2009-11-20 12:34 ` Wu Zhangjin
  2009-11-20 17:25   ` Ralf Baechle
  2009-11-20 12:34 ` [PATCH v9 10/10] tracing: make function graph tracer work with -mmcount-ra-address Wu Zhangjin
  9 siblings, 1 reply; 24+ messages in thread
From: Wu Zhangjin @ 2009-11-20 12:34 UTC (permalink / raw)
  To: Ralf Baechle, rostedt
  Cc: Nicholas Mc Guire, zhangfx, Wu Zhangjin, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

From: Wu Zhangjin <wuzhangjin@gmail.com>

A new option -mmcount-ra-address for gcc 4.5 have been sent by David
Daney <ddaney@caviumnetworks.com> in the thread "MIPS: Add option to
pass return address location to _mcount", which help to record the
location of the return address(ra) for the function graph tracer of MIPS
to hijack the return address easier and safer. that option used the
$12(t0) register by default, so, we reserve it for it, and use t1,t2,t3
instead of t0,t1,t2.

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/kernel/mcount.S |   26 +++++++++++++-------------
 1 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index bdfef2c..522e91c 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -65,8 +65,8 @@ NESTED(ftrace_caller, PT_SIZE, ra)
 _mcount:
 	b	ftrace_stub
 	 nop
-	lw	t0, function_trace_stop
-	bnez	t0, ftrace_stub
+	lw	t1, function_trace_stop
+	bnez	t1, ftrace_stub
 	 nop
 
 	MCOUNT_SAVE_REGS
@@ -93,21 +93,21 @@ ftrace_stub:
 #else	/* ! CONFIG_DYNAMIC_FTRACE */
 
 NESTED(_mcount, PT_SIZE, ra)
-	lw	t0, function_trace_stop
-	bnez	t0, ftrace_stub
+	lw	t1, function_trace_stop
+	bnez	t1, ftrace_stub
 	 nop
-	PTR_LA	t0, ftrace_stub
-	PTR_L	t1, ftrace_trace_function /* Prepare t1 for (1) */
-	bne	t0, t1, static_trace
+	PTR_LA	t1, ftrace_stub
+	PTR_L	t2, ftrace_trace_function /* Prepare t2 for (1) */
+	bne	t1, t2, static_trace
 	 nop
 
 #ifdef	CONFIG_FUNCTION_GRAPH_TRACER
-	PTR_L	t2, ftrace_graph_return
-	bne	t0, t2, ftrace_graph_caller
+	PTR_L	t3, ftrace_graph_return
+	bne	t1, t3, ftrace_graph_caller
 	 nop
-	PTR_LA	t0, ftrace_graph_entry_stub
-	PTR_L	t2, ftrace_graph_entry
-	bne	t0, t2, ftrace_graph_caller
+	PTR_LA	t1, ftrace_graph_entry_stub
+	PTR_L	t3, ftrace_graph_entry
+	bne	t1, t3, ftrace_graph_caller
 	 nop
 #endif
 	b	ftrace_stub
@@ -117,7 +117,7 @@ static_trace:
 	MCOUNT_SAVE_REGS
 
 	move	a0, ra		/* arg1: next ip, selfaddr */
-	jalr	t1	/* (1) call *ftrace_trace_function */
+	jalr	t2		/* (1) call *ftrace_trace_function */
 	 move	a1, AT		/* arg2: the caller's next ip, parent */
 
 	MCOUNT_RESTORE_REGS
-- 
1.6.2.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v9 10/10] tracing: make function graph tracer work with -mmcount-ra-address
  2009-11-20 12:28 [PATCH v9 00/10] ftrace for MIPS Wu Zhangjin
                   ` (8 preceding siblings ...)
  2009-11-20 12:34 ` [PATCH v9 09/10] tracing: reserve $12(t0) for mcount-ra-address of gcc 4.5 Wu Zhangjin
@ 2009-11-20 12:34 ` Wu Zhangjin
  2009-11-20 17:25   ` Ralf Baechle
  9 siblings, 1 reply; 24+ messages in thread
From: Wu Zhangjin @ 2009-11-20 12:34 UTC (permalink / raw)
  To: Ralf Baechle, rostedt
  Cc: Nicholas Mc Guire, zhangfx, Wu Zhangjin, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

From: Wu Zhangjin <wuzhangjin@gmail.com>

That thread "MIPS: Add option to pass return address location to
_mcount" from "David Daney <ddaney@caviumnetworks.com>" have added a new
option -mmcount-ra-address to gcc(4.5) for MIPS to transfer the location
of the return address to _mcount.

Benefit from this new feature, function graph tracer on MIPS will be
easier and safer to hijack the return address of the kernel function,
which will save some overhead and make the whole thing more reliable.

In this patch, at first, try to enable the option -mmcount-ra-address in
arch/mips/Makefile with cc-option, if gcc support it, it will be
enabled, otherwise, no side effect.

and then, we need to support this new option of gcc 4.5 and also support
the old gcc versions.

with _mcount in the old gcc versions, it's not easy to get the location
of return address(tracing: add function graph tracer support for MIPS),
   so, we do it in a C function: ftrace_get_parent_addr(ftrace.c), but
   with -mmcount-ra-address, only several instructions need to get what
   we want, so, I put into asm(mcount.S). and also, as the $12(t0) is
   used by -mmcount-ra-address for transferring the localtion of return
   address to _mcount, we need to save it into the stack and restore it
   when enabled dynamic function tracer, 'Cause we have called
   "ftrace_call" before "ftrace_graph_caller", which may destroy
   $12(t0).

(Thanks to David for providing that -mcount-ra-address and giving the
 idea of KBUILD_MCOUNT_RA_ADDRESS, both of them have made the whole
 thing more beautiful!)

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/Makefile        |    7 +++++++
 arch/mips/kernel/ftrace.c |   24 +++++++++++++++++-------
 arch/mips/kernel/mcount.S |   14 ++++++++++++++
 3 files changed, 38 insertions(+), 7 deletions(-)

diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 0a2073e..50039e8 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -51,6 +51,13 @@ endif
 ifndef CONFIG_FUNCTION_TRACER
 cflags-y := -ffunction-sections
 endif
+ifdef CONFIG_FUNCTION_GRAPH_TRACER
+  ifndef KBUILD_MCOUNT_RA_ADDRESS
+    ifeq ($(call cc-option-yn,-mmcount-ra-address), y)
+      cflags-y += -mmcount-ra-address -DKBUILD_MCOUNT_RA_ADDRESS
+    endif
+  endif
+endif
 cflags-y += $(call cc-option, -mno-check-zero-division)
 
 ifdef CONFIG_32BIT
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index e363fc6..68b0670 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -148,6 +148,7 @@ int ftrace_disable_ftrace_graph_caller(void)
 
 #endif				/* !CONFIG_DYNAMIC_FTRACE */
 
+#ifndef KBUILD_MCOUNT_RA_ADDRESS
 #define S_RA_SP	(0xafbf << 16)	/* s{d,w} ra, offset(sp) */
 #define S_R_SP	(0xafb0 << 16)  /* s{d,w} R, offset(sp) */
 #define OFFSET_MASK	0xffff	/* stack offset range: 0 ~ PT_SIZE */
@@ -201,6 +202,8 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
 	return 0;
 }
 
+#endif
+
 /*
  * Hook the return address and push it in the stack of return addrs
  * in current thread info.
@@ -218,19 +221,26 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 
 	/* "parent" is the stack address saved the return address of the caller
-	 * of _mcount, for a leaf function not save the return address in the
-	 * stack address, so, we "emulate" one in _mcount's stack space, and
-	 * hijack it directly, but for a non-leaf function, it will save the
-	 * return address to the its stack space, so, we can not hijack the
-	 * "parent" directly, but need to find the real stack address,
+	 * of _mcount.
+	 *
+	 * if the gcc < 4.5, a leaf function does not save the return address
+	 * in the stack address, so, we "emulate" one in _mcount's stack space,
+	 * and hijack it directly, but for a non-leaf function, it save the
+	 * return address to the its own stack space, we can not hijack it
+	 * directly, but need to find the real stack address,
 	 * ftrace_get_parent_addr() does it!
+	 *
+	 * if gcc>= 4.5, with the new -mmcount-ra-address option, for a
+	 * non-leaf function, the location of the return address will be saved
+	 * to $12 for us, and for a leaf function, only put a zero into $12. we
+	 * do it in ftrace_graph_caller of mcount.S.
 	 */
 
 	/* old = *parent; */
 	safe_load_stack(old, parent, faulted);
 	if (unlikely(faulted))
 		goto out;
-
+#ifndef KBUILD_MCOUNT_RA_ADDRESS
 	parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old,
 							 (unsigned long)parent,
 							 fp);
@@ -238,7 +248,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 	 * ra, stop function graph tracer and return */
 	if (parent == 0)
 		goto out;
-
+#endif
 	/* *parent = return_hooker; */
 	safe_store_stack(return_hooker, parent, faulted);
 	if (unlikely(faulted))
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index 522e91c..0a9cfdb 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -70,6 +70,9 @@ _mcount:
 	 nop
 
 	MCOUNT_SAVE_REGS
+#ifdef KBUILD_MCOUNT_RA_ADDRESS
+	PTR_S	t0, PT_R12(sp)	/* t0 saved the location of the return address(at) by -mmcount-ra-address */
+#endif
 
 	move	a0, ra		/* arg1: next ip, selfaddr */
 	.globl ftrace_call
@@ -133,11 +136,22 @@ ftrace_stub:
 NESTED(ftrace_graph_caller, PT_SIZE, ra)
 #ifdef CONFIG_DYNAMIC_FTRACE
 	PTR_L	a1, PT_R31(sp)	/* load the original ra from the stack */
+#ifdef KBUILD_MCOUNT_RA_ADDRESS
+	PTR_L	t0, PT_R12(sp)	/* load the original t0 from the stack */
+#endif
 #else
 	MCOUNT_SAVE_REGS
 	move	a1, ra		/* arg2: next ip, selfaddr */
 #endif
+
+#ifdef KBUILD_MCOUNT_RA_ADDRESS
+	bnez	t0, 1f		/* non-leaf func: t0 saved the location of the return address */
+	 nop
+	PTR_LA	t0, PT_R1(sp)	/* leaf func: get the location of at(old ra) from our own stack */
+1:	move	a0, t0		/* arg1: the location of the return address */
+#else
 	PTR_LA	a0, PT_R1(sp)	/* arg1: &AT -> a0 */
+#endif
 	jal	prepare_ftrace_return
 #ifdef CONFIG_FRAME_POINTER
 	 move	a2, fp		/* arg3: frame pointer */
-- 
1.6.2.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 03/10] tracing: add an endian argument to scripts/recordmcount.pl
  2009-11-20 12:34 ` [PATCH v9 03/10] tracing: add an endian argument to scripts/recordmcount.pl Wu Zhangjin
@ 2009-11-20 17:20   ` Ralf Baechle
  2009-12-03 17:45   ` Steven Rostedt
  1 sibling, 0 replies; 24+ messages in thread
From: Ralf Baechle @ 2009-11-20 17:20 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: rostedt, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips,
	Wu Zhangjin

On Fri, Nov 20, 2009 at 08:34:31PM +0800, Wu Zhangjin wrote:

> From: Wu Zhangjin <wuzhangjin@gmail.com>
> 
> MIPS and some other architectures need this argument to handle
> big/little endian respectively.
> 
> Signed-off-by: Wu Zhangjin <wuzj@lemote.com>

This one is a bit problematic because you seem to have generated the
patch against linux-next but I'm applying it on the MIPS -queue tree and
some other changes on -next are now resulting in a conflict.  And
Steven Rostedt is going to merge a few more changes which he says will
conflict.

So I put this patch on the queue tree but may not propagate it immediately
to linux-next.

Thanks!

  Ralf

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 01/10] tracing: add static function tracer support for MIPS
  2009-11-20 12:34 ` [PATCH v9 01/10] tracing: add static function tracer support " Wu Zhangjin
@ 2009-11-20 17:22   ` Ralf Baechle
  0 siblings, 0 replies; 24+ messages in thread
From: Ralf Baechle @ 2009-11-20 17:22 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: rostedt, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

On Fri, Nov 20, 2009 at 08:34:29PM +0800, Wu Zhangjin wrote:

Queued for 2.6.33 but due to patch 3/3 I won't propagate this series
immediately to linux-next.

Thanks!

  Ralf

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 02/10] tracing: enable HAVE_FUNCTION_TRACE_MCOUNT_TEST for MIPS
  2009-11-20 12:34 ` [PATCH v9 02/10] tracing: enable HAVE_FUNCTION_TRACE_MCOUNT_TEST " Wu Zhangjin
@ 2009-11-20 17:22   ` Ralf Baechle
  0 siblings, 0 replies; 24+ messages in thread
From: Ralf Baechle @ 2009-11-20 17:22 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: rostedt, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

On Fri, Nov 20, 2009 at 08:34:30PM +0800, Wu Zhangjin wrote:

> There is an exisiting common ftrace_test_stop_func() in
> kernel/trace/ftrace.c, which is used to check the global variable
> ftrace_trace_stop to determine whether stop the function tracing.
> 
> This patch implepment the MIPS specific one to speedup the procedure.
> 
> Thanks goes to Zhang Le for Cleaning it up.
> 
> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>

Queued for 2.6.33 but due to patch 3/3 I won't propagate this series
immediately to linux-next.

Thanks!

  Ralf

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 04/10] tracing: add dynamic function tracer support for MIPS
  2009-11-20 12:34 ` [PATCH v9 04/10] tracing: add dynamic function tracer support for MIPS Wu Zhangjin
@ 2009-11-20 17:23   ` Ralf Baechle
  2009-12-03 17:54   ` Steven Rostedt
  1 sibling, 0 replies; 24+ messages in thread
From: Ralf Baechle @ 2009-11-20 17:23 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: rostedt, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

On Fri, Nov 20, 2009 at 08:34:32PM +0800, Wu Zhangjin wrote:

> From: Wu Zhangjin <wuzhangjin@gmail.com>
> 
> With dynamic function tracer, by default, _mcount is defined as an
> "empty" function, it returns directly without any more action . When
> enabling it in user-space, it will jump to a real tracing
> function(ftrace_caller), and do the real job for us.
> 
> Differ from the static function tracer, dynamic function tracer provides
> two functions ftrace_make_call()/ftrace_make_nop() to enable/disable the
> tracing of some indicated kernel functions(set_ftrace_filter).
> 
> In the -v4 version, the implementation of this support is basically the same as
> X86 version does: _mcount is implemented as an empty function and ftrace_caller
> is implemented as a real tracing function respectively.
> 
> But in this version, to support module tracing with the help of
> -mlong-calls in arch/mips/Makefile:
> 
> MODFLAGS += -mlong-calls.
> 
> The stuff becomes a little more complex. We need to cope with two
> different type of calling to _mcount.
> 
> For the kernel part, the calling to _mcount(result of "objdump -hdr
> vmlinux"). is like this:
> 
> 	108:   03e0082d        move    at,ra
> 	10c:   0c000000        jal     0 <fpcsr_pending>
>                         10c: R_MIPS_26  _mcount
>                         10c: R_MIPS_NONE        *ABS*
>                         10c: R_MIPS_NONE        *ABS*
> 	110:   00020021        nop
> 
> For the module with -mlong-calls, it looks like this:
> 
> 	c:	3c030000 	lui	v1,0x0
> 			c: R_MIPS_HI16	_mcount
> 			c: R_MIPS_NONE	*ABS*
> 			c: R_MIPS_NONE	*ABS*
> 	10:	64630000 	daddiu	v1,v1,0
> 			10: R_MIPS_LO16	_mcount
> 			10: R_MIPS_NONE	*ABS*
> 			10: R_MIPS_NONE	*ABS*
> 	14:	03e0082d 	move	at,ra
> 	18:	0060f809 	jalr	v1
> 
> In the kernel version, there is only one "_mcount" string for every
> kernel function, so, we just need to match this one in mcount_regex of
> scripts/recordmcount.pl, but in the module version, we need to choose
> one of the two to match. Herein, I choose the first one with
> "R_MIPS_HI16 _mcount".
> 
> and In the kernel verion, without module tracing support, we just need
> to replace "jal _mcount" by "jal ftrace_caller" to do real tracing, and
> filter the tracing of some kernel functions via replacing it by a nop
> instruction.
> 
> but as we have described before, the instruction "jal ftrace_caller" only left
> 32bit length for the address of ftrace_caller, it will fail when calling from
> the module space. so, herein, we must replace something else.
> 
> the basic idea is loading the address of ftrace_caller to v1 via changing these
> two instructions:
> 
> 	lui	v1,0x0
> 	addiu	v1,v1,0
> 
> If we want to enable the tracing, we need to replace the above instructions to:
> 
> 	lui	v1, HI_16BIT_ftrace_caller
> 	addiu	v1, v1, LOW_16BIT_ftrace_caller
> 
> If we want to stop the tracing of the indicated kernel functions, we
> just need to replace the "jalr v1" to a nop instruction. but we need to
> replace two instructions and encode the above two instructions
> oursevles.
> 
> Is there a simpler solution? Yes! Here it is, in this version, we put _mcount
> and ftrace_caller together, which means the address of _mcount and
> ftrace_caller is the same:
> 
> _mcount:
> ftrace_caller:
> 	j	ftrace_stub
> 	 nop
> 
> 	...(do real tracing here)...
> 
> ftrace_stub:
> 	jr	ra
> 	 move	ra, at
> 
> By default, the kernel functions call _mcount, and then jump to ftrace_stub and
> return. and when we want to do real tracing, we just need to remove that "j
> ftrace_stub", and it will run through the two "nop" instructions and then do
> the real tracing job.
> 
> what about filtering job? we just need to do this:
> 
> 	 lui v1, hi_16bit_of_mcount        <--> b 1f (0x10000004)
> 	 addiu v1, v1, low_16bit_of_mcount
> 	 move at, ra
> 	 jalr v1
> 	 nop
> 	 				     1f: (rec->ip + 12)
> 
> In linux-mips64, there will be some local symbols, whose name are
> prefixed by $L, which need to be filtered. thanks goes to Steven for
> writing the mips64-specific function_regex.
> 
> In a conclusion, with RISC, things becomes easier with such a "stupid"
> trick, RISC is something like K.I.S.S, and also, there are lots of
> "simple" tricks in the whole ftrace support, thanks goes to Steven and
> the other folks for providing such a wonderful tracing framework!
> 
> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>

Queued for 2.6.33 but due to patch 3/3 I won't propagate this series
immediately to linux-next.

Thanks!

  Ralf

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 05/10] tracing: add IRQENTRY_EXIT section for MIPS
  2009-11-20 12:34 ` [PATCH v9 05/10] tracing: add IRQENTRY_EXIT section " Wu Zhangjin
@ 2009-11-20 17:23   ` Ralf Baechle
  0 siblings, 0 replies; 24+ messages in thread
From: Ralf Baechle @ 2009-11-20 17:23 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: rostedt, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

On Fri, Nov 20, 2009 at 08:34:33PM +0800, Wu Zhangjin wrote:

> From: Wu Zhangjin <wuzhangjin@gmail.com>
> 
> This patch add a new section for MIPS to record the block of the hardirq
> handling for function graph tracer(print_graph_irq) via adding the
> __irq_entry annotation to the the entrypoints of the hardirqs(the block
> with irq_enter()...irq_exit()).
> 
> Thanks goes to Steven & Frederic Weisbecker for their feedbacks.
> 
> Reviewed-by: Frederic Weisbecker <fweisbec@gmail.com>
> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>

Queued for 2.6.33 but due to patch 3/3 I won't propagate this series
immediately to linux-next.

Thanks!

  Ralf

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 06/10] tracing: add function graph tracer support for MIPS
  2009-11-20 12:34 ` [PATCH v9 06/10] tracing: add function graph tracer support " Wu Zhangjin
@ 2009-11-20 17:24   ` Ralf Baechle
  0 siblings, 0 replies; 24+ messages in thread
From: Ralf Baechle @ 2009-11-20 17:24 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: rostedt, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

On Fri, Nov 20, 2009 at 08:34:34PM +0800, Wu Zhangjin wrote:

> The implementation of function graph tracer for MIPS is a little
> different from X86.
> 
> in MIPS, gcc(with -pg) only transfer the caller's return address(at) and
> the _mcount's return address(ra) to us.
> 
> For the kernel part without -mlong-calls:
> 
> move at, ra
> jal _mcount
> 
> For the module part with -mlong-calls:
> 
> lui v1, hi16bit_of_mcount
> addiu v1, v1, low16bit_of_mcount
> move at, ra
> jal _mcount
> 
> Without -mlong-calls,
> 
> if the function is a leaf, it will not save the return address(ra):
> 
> ffffffff80101298 <au1k_wait>:
> ffffffff80101298:       67bdfff0        daddiu  sp,sp,-16
> ffffffff8010129c:       ffbe0008        sd      s8,8(sp)
> ffffffff801012a0:       03a0f02d        move    s8,sp
> ffffffff801012a4:       03e0082d        move    at,ra
> ffffffff801012a8:       0c042930        jal     ffffffff8010a4c0 <_mcount>
> ffffffff801012ac:       00020021        nop
> 
> so, we can hijack it directly in _mcount, but if the function is non-leaf, the
> return address is saved in the stack.
> 
> ffffffff80133030 <copy_process>:
> ffffffff80133030:       67bdff50        daddiu  sp,sp,-176
> ffffffff80133034:       ffbe00a0        sd      s8,160(sp)
> ffffffff80133038:       03a0f02d        move    s8,sp
> ffffffff8013303c:       ffbf00a8        sd      ra,168(sp)
> ffffffff80133040:       ffb70098        sd      s7,152(sp)
> ffffffff80133044:       ffb60090        sd      s6,144(sp)
> ffffffff80133048:       ffb50088        sd      s5,136(sp)
> ffffffff8013304c:       ffb40080        sd      s4,128(sp)
> ffffffff80133050:       ffb30078        sd      s3,120(sp)
> ffffffff80133054:       ffb20070        sd      s2,112(sp)
> ffffffff80133058:       ffb10068        sd      s1,104(sp)
> ffffffff8013305c:       ffb00060        sd      s0,96(sp)
> ffffffff80133060:       03e0082d        move    at,ra
> ffffffff80133064:       0c042930        jal     ffffffff8010a4c0 <_mcount>
> ffffffff80133068:       00020021        nop
> 
> but we can not get the exact stack address(which saved ra) directly in
> _mcount, we need to search the content of at register in the stack space
> or search the "s{d,w} ra, offset(sp)" instruction in the text. 'Cause we
> can not prove there is only a match in the stack space, so, we search
> the text instead.
> 
> as we can see, if the first instruction above "move at, ra" is not a
> store instruction, there should be a leaf function, so we hijack the at
> register directly via putting &return_to_handler into it, otherwise, we
> search the "s{d,w} ra, offset(sp)" instruction to get the stack offset,
> and then the stack address. we use the above copy_process() as an
> example, we at last find "ffbf00a8", 0xa8 is the stack offset, we plus
> it with s8(fp), that is the stack address, we hijack the content via
> writing the &return_to_handler in.
> 
> If with -mlong-calls, since there are two more instructions above "move
> at, ra", so, we can move the pointer to the position above "lui v1,
> hi16bit_of_mcount".
> 
> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>

Queued for 2.6.33 but due to patch 3/3 I won't propagate this series
immediately to linux-next.

Thanks!

  Ralf

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 07/10] tracing: add dynamic function graph tracer for MIPS
  2009-11-20 12:34 ` [PATCH v9 07/10] tracing: add dynamic function graph tracer " Wu Zhangjin
@ 2009-11-20 17:24   ` Ralf Baechle
  2009-11-22  6:19     ` Wu Zhangjin
  0 siblings, 1 reply; 24+ messages in thread
From: Ralf Baechle @ 2009-11-20 17:24 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: rostedt, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

On Fri, Nov 20, 2009 at 08:34:35PM +0800, Wu Zhangjin wrote:

> From: Wu Zhangjin <wuzhangjin@gmail.com>
> 
> This patch make function graph tracer work with dynamic function tracer.
> 
> To share the source code of dynamic function tracer(MCOUNT_SAVE_REGS),
> and avoid restoring the whole saved registers, we need to restore the ra
> register from the stack.
> 
> (NOTE: This not work with 32bit! need to ensure why!)
> 
> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>

Queued for 2.6.33 but due to patch 3/3 I won't propagate this series
immediately to linux-next.

Thanks!

  Ralf

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 08/10] tracing: make ftrace for MIPS work without -fno-omit-frame-pointer
  2009-11-20 12:34 ` [PATCH v9 08/10] tracing: make ftrace for MIPS work without -fno-omit-frame-pointer Wu Zhangjin
@ 2009-11-20 17:24   ` Ralf Baechle
  0 siblings, 0 replies; 24+ messages in thread
From: Ralf Baechle @ 2009-11-20 17:24 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: rostedt, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

On Fri, Nov 20, 2009 at 08:34:36PM +0800, Wu Zhangjin wrote:

> When remove the -fno-omit-frame-pointer, gcc will not save the frame
> pointer for us, we need to save one ourselves.
> 
> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>

Queued for 2.6.33 but due to patch 3/3 I won't propagate this series
immediately to linux-next.

Thanks!

  Ralf

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 09/10] tracing: reserve $12(t0) for mcount-ra-address of gcc 4.5
  2009-11-20 12:34 ` [PATCH v9 09/10] tracing: reserve $12(t0) for mcount-ra-address of gcc 4.5 Wu Zhangjin
@ 2009-11-20 17:25   ` Ralf Baechle
  0 siblings, 0 replies; 24+ messages in thread
From: Ralf Baechle @ 2009-11-20 17:25 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: rostedt, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

On Fri, Nov 20, 2009 at 08:34:37PM +0800, Wu Zhangjin wrote:

> From: Wu Zhangjin <wuzhangjin@gmail.com>
> 
> A new option -mmcount-ra-address for gcc 4.5 have been sent by David
> Daney <ddaney@caviumnetworks.com> in the thread "MIPS: Add option to
> pass return address location to _mcount", which help to record the
> location of the return address(ra) for the function graph tracer of MIPS
> to hijack the return address easier and safer. that option used the
> $12(t0) register by default, so, we reserve it for it, and use t1,t2,t3
> instead of t0,t1,t2.
> 
> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>

Queued for 2.6.33 but due to patch 3/3 I won't propagate this series
immediately to linux-next.

Thanks!

  Ralf

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 10/10] tracing: make function graph tracer work with -mmcount-ra-address
  2009-11-20 12:34 ` [PATCH v9 10/10] tracing: make function graph tracer work with -mmcount-ra-address Wu Zhangjin
@ 2009-11-20 17:25   ` Ralf Baechle
  0 siblings, 0 replies; 24+ messages in thread
From: Ralf Baechle @ 2009-11-20 17:25 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: rostedt, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

On Fri, Nov 20, 2009 at 08:34:38PM +0800, Wu Zhangjin wrote:

> That thread "MIPS: Add option to pass return address location to
> _mcount" from "David Daney <ddaney@caviumnetworks.com>" have added a new
> option -mmcount-ra-address to gcc(4.5) for MIPS to transfer the location
> of the return address to _mcount.
> 
> Benefit from this new feature, function graph tracer on MIPS will be
> easier and safer to hijack the return address of the kernel function,
> which will save some overhead and make the whole thing more reliable.
> 
> In this patch, at first, try to enable the option -mmcount-ra-address in
> arch/mips/Makefile with cc-option, if gcc support it, it will be
> enabled, otherwise, no side effect.
> 
> and then, we need to support this new option of gcc 4.5 and also support
> the old gcc versions.
> 
> with _mcount in the old gcc versions, it's not easy to get the location
> of return address(tracing: add function graph tracer support for MIPS),
>    so, we do it in a C function: ftrace_get_parent_addr(ftrace.c), but
>    with -mmcount-ra-address, only several instructions need to get what
>    we want, so, I put into asm(mcount.S). and also, as the $12(t0) is
>    used by -mmcount-ra-address for transferring the localtion of return
>    address to _mcount, we need to save it into the stack and restore it
>    when enabled dynamic function tracer, 'Cause we have called
>    "ftrace_call" before "ftrace_graph_caller", which may destroy
>    $12(t0).
> 
> (Thanks to David for providing that -mcount-ra-address and giving the
>  idea of KBUILD_MCOUNT_RA_ADDRESS, both of them have made the whole
>  thing more beautiful!)
> 
> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>

Queued for 2.6.33 but due to patch 3/3 I won't propagate this series
immediately to linux-next.

Thanks!

  Ralf

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 07/10] tracing: add dynamic function graph tracer for MIPS
  2009-11-20 17:24   ` Ralf Baechle
@ 2009-11-22  6:19     ` Wu Zhangjin
  0 siblings, 0 replies; 24+ messages in thread
From: Wu Zhangjin @ 2009-11-22  6:19 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: rostedt, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

On Fri, 2009-11-20 at 17:24 +0000, Ralf Baechle wrote:
> On Fri, Nov 20, 2009 at 08:34:35PM +0800, Wu Zhangjin wrote:
> 
> > From: Wu Zhangjin <wuzhangjin@gmail.com>
> > 
> > This patch make function graph tracer work with dynamic function tracer.
> > 
> > To share the source code of dynamic function tracer(MCOUNT_SAVE_REGS),
> > and avoid restoring the whole saved registers, we need to restore the ra
> > register from the stack.
> > 
> > (NOTE: This not work with 32bit! need to ensure why!)
> > 

Hi, Ralf, Could you please remove the above "NOTE", just test your
-queue repository with the latest sched_clock() in 32bit, it works well.
so, that NOTE is out-of-date.

Thanks & Best Regards,
	Wu Zhangjin


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 03/10] tracing: add an endian argument to scripts/recordmcount.pl
  2009-11-20 12:34 ` [PATCH v9 03/10] tracing: add an endian argument to scripts/recordmcount.pl Wu Zhangjin
  2009-11-20 17:20   ` Ralf Baechle
@ 2009-12-03 17:45   ` Steven Rostedt
  1 sibling, 0 replies; 24+ messages in thread
From: Steven Rostedt @ 2009-12-03 17:45 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: Ralf Baechle, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips,
	Wu Zhangjin

On Fri, 2009-11-20 at 20:34 +0800, Wu Zhangjin wrote:
> From: Wu Zhangjin <wuzhangjin@gmail.com>
> 
> MIPS and some other architectures need this argument to handle
> big/little endian respectively.
> 
> Signed-off-by: Wu Zhangjin <wuzj@lemote.com>

I don't think I acked this version. But just to make it official:

Acked-by: Steven Rostedt <rostedt@goodmis.org>

-- Steve

> ---
>  scripts/Makefile.build  |    1 +
>  scripts/recordmcount.pl |    6 +++---
>  2 files changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/scripts/Makefile.build b/scripts/Makefile.build
> index 341b589..0b94d2f 100644
> --- a/scripts/Makefile.build
> +++ b/scripts/Makefile.build
> @@ -207,6 +207,7 @@ endif
>  
>  ifdef CONFIG_FTRACE_MCOUNT_RECORD
>  cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
> +	"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
>  	"$(if $(CONFIG_64BIT),64,32)" \
>  	"$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
>  	"$(if $(part-of-module),1,0)" "$(@)";
> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> index f0d1445..24604d4 100755
> --- a/scripts/recordmcount.pl
> +++ b/scripts/recordmcount.pl
> @@ -113,13 +113,13 @@ $P =~ s@.*/@@g;
>  
>  my $V = '0.1';
>  
> -if ($#ARGV != 10) {
> -	print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
> +if ($#ARGV != 11) {
> +	print "usage: $P arch endian bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
>  	print "version: $V\n";
>  	exit(1);
>  }
>  
> -my ($arch, $bits, $objdump, $objcopy, $cc,
> +my ($arch, $endian, $bits, $objdump, $objcopy, $cc,
>      $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV;
>  
>  # This file refers to mcount and shouldn't be ftraced, so lets' ignore it


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v9 04/10] tracing: add dynamic function tracer support for MIPS
  2009-11-20 12:34 ` [PATCH v9 04/10] tracing: add dynamic function tracer support for MIPS Wu Zhangjin
  2009-11-20 17:23   ` Ralf Baechle
@ 2009-12-03 17:54   ` Steven Rostedt
  1 sibling, 0 replies; 24+ messages in thread
From: Steven Rostedt @ 2009-12-03 17:54 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: Ralf Baechle, Nicholas Mc Guire, zhangfx, Ingo Molnar,
	Thomas Gleixner, Frederic Weisbecker, linux-kernel, linux-mips

On Fri, 2009-11-20 at 20:34 +0800, Wu Zhangjin wrote:
> From: Wu Zhangjin <wuzhangjin@gmail.com>
> 

> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
> ---
>  arch/mips/Kconfig              |    2 +
>  arch/mips/include/asm/ftrace.h |    9 +++
>  arch/mips/kernel/Makefile      |    3 +-
>  arch/mips/kernel/ftrace.c      |  112 ++++++++++++++++++++++++++++++++++++++++
>  arch/mips/kernel/mcount.S      |   29 ++++++++++


>  scripts/recordmcount.pl        |   54 +++++++++++++++++++


>  6 files changed, 208 insertions(+), 1 deletions(-)
>  create mode 100644 arch/mips/kernel/ftrace.c
> 



> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> index 24604d4..9d80d0d 100755
> --- a/scripts/recordmcount.pl
> +++ b/scripts/recordmcount.pl
> @@ -295,6 +295,60 @@ if ($arch eq "x86_64") {
>      $ld .= " -m elf64_sparc";
>      $cc .= " -m64";
>      $objcopy .= " -O elf64-sparc";
> +
> +} elsif ($arch eq "mips") {
> +    # To enable module support, we need to enable the -mlong-calls option
> +    # of gcc for module, after using this option, we can not get the real
> +    # offset of the calling to _mcount, but the offset of the lui
> +    # instruction or the addiu one. herein, we record the address of the
> +    # first one, and then we can replace this instruction by a branch
> +    # instruction to jump over the profiling function to filter the
> +    # indicated functions, or swith back to the lui instruction to trace
> +    # them, which means dynamic tracing.
> +    #
> +    #       c:	3c030000 	lui	v1,0x0
> +    #			c: R_MIPS_HI16	_mcount
> +    #			c: R_MIPS_NONE	*ABS*
> +    #			c: R_MIPS_NONE	*ABS*
> +    #      10:	64630000 	daddiu	v1,v1,0
> +    #			10: R_MIPS_LO16	_mcount
> +    #			10: R_MIPS_NONE	*ABS*
> +    #			10: R_MIPS_NONE	*ABS*
> +    #      14:	03e0082d 	move	at,ra
> +    #      18:	0060f809 	jalr	v1
> +    #
> +    # for the kernel:
> +    #
> +    #     10:   03e0082d        move    at,ra
> +    #	  14:   0c000000        jal     0 <loongson_halt>
> +    #                    14: R_MIPS_26   _mcount
> +    #                    14: R_MIPS_NONE *ABS*
> +    #                    14: R_MIPS_NONE *ABS*
> +    #	 18:   00020021        nop
> +    if ($is_module eq "0") {
> +	    $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
> +    } else {
> +	    $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_HI16\\s+_mcount\$";
> +    }
> +    $objdump .= " -Melf-trad".$endian."mips ";
> +
> +    if ($endian eq "big") {
> +	    $endian = " -EB ";
> +	    $ld .= " -melf".$bits."btsmip";
> +    } else {
> +	    $endian = " -EL ";
> +	    $ld .= " -melf".$bits."ltsmip";
> +    }
> +
> +    $cc .= " -mno-abicalls -fno-pic -mabi=" . $bits . $endian;
> +    $ld .= $endian;
> +
> +    if ($bits == 64) {
> +	    $function_regex =
> +		"^([0-9a-fA-F]+)\\s+<(.|[^\$]L.*?|\$[^L].*?|[^\$][^L].*?)>:";
> +	    $type = ".dword";
> +    }
> +
>  } else {
>      die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
>  }

This only adds MIPS arch support to recordmcount.pl, and does not touch
any other arch or generic code. Thus, I consider this arch specific
code.

Acked-by: Steven Rostedt <rostedt@goodmis.org>

-- Steve



^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2009-12-03 17:54 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-20 12:28 [PATCH v9 00/10] ftrace for MIPS Wu Zhangjin
2009-11-20 12:34 ` [PATCH v9 01/10] tracing: add static function tracer support " Wu Zhangjin
2009-11-20 17:22   ` Ralf Baechle
2009-11-20 12:34 ` [PATCH v9 02/10] tracing: enable HAVE_FUNCTION_TRACE_MCOUNT_TEST " Wu Zhangjin
2009-11-20 17:22   ` Ralf Baechle
2009-11-20 12:34 ` [PATCH v9 03/10] tracing: add an endian argument to scripts/recordmcount.pl Wu Zhangjin
2009-11-20 17:20   ` Ralf Baechle
2009-12-03 17:45   ` Steven Rostedt
2009-11-20 12:34 ` [PATCH v9 04/10] tracing: add dynamic function tracer support for MIPS Wu Zhangjin
2009-11-20 17:23   ` Ralf Baechle
2009-12-03 17:54   ` Steven Rostedt
2009-11-20 12:34 ` [PATCH v9 05/10] tracing: add IRQENTRY_EXIT section " Wu Zhangjin
2009-11-20 17:23   ` Ralf Baechle
2009-11-20 12:34 ` [PATCH v9 06/10] tracing: add function graph tracer support " Wu Zhangjin
2009-11-20 17:24   ` Ralf Baechle
2009-11-20 12:34 ` [PATCH v9 07/10] tracing: add dynamic function graph tracer " Wu Zhangjin
2009-11-20 17:24   ` Ralf Baechle
2009-11-22  6:19     ` Wu Zhangjin
2009-11-20 12:34 ` [PATCH v9 08/10] tracing: make ftrace for MIPS work without -fno-omit-frame-pointer Wu Zhangjin
2009-11-20 17:24   ` Ralf Baechle
2009-11-20 12:34 ` [PATCH v9 09/10] tracing: reserve $12(t0) for mcount-ra-address of gcc 4.5 Wu Zhangjin
2009-11-20 17:25   ` Ralf Baechle
2009-11-20 12:34 ` [PATCH v9 10/10] tracing: make function graph tracer work with -mmcount-ra-address Wu Zhangjin
2009-11-20 17:25   ` Ralf Baechle

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.