All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/6] mips-specific ftrace support
@ 2009-05-29 14:58 wuzhangjin
  2009-05-29 15:02 ` [PATCH v2 1/6] mips static function tracer support wuzhangjin
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: wuzhangjin @ 2009-05-29 14:58 UTC (permalink / raw)
  To: linux-mips, linux-kernel
  Cc: Wu Zhangjin, Steven Rostedt, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire

From: Wu Zhangjin <wuzj@lemote.com>

ftrace is a mcount based kernel tracing tool/framework, which is originally
from RT_PREEMPT(http://rt.wiki.kernel.org).

ftrace is short for function tracer, this is its original name, but now, it
becomes a kernel tracing framework, lots of kernel tracers are built on it,
such as irqoff tracer, wakeup tracer and so forth.  these tracers are
arch-independent(?), but some of them are arch-dependent, such as the original
ftrace: function tracer, and dynamic function tracer, function graph tracer,
and also, system call tracer.

here is the mips porting of these four arch-dependent tracers, it will enable
the following new kernel config options in linux-mips system.

kernel hacking --->
           Tracers -->
                [*] Kernel Function Tracer
                [*]   Kernel Function Graph Tracer
                ...
                [*] Trace syscalls
                                ...
                [*] enable/disable ftrace tracepoints dynamically

in reality, because the timestamp getting function are arch-dependent, lots of
the tracers are arch-dependent. the arch-dependent part is that: sched_clock.
the original sched_clock in mips is jiffes based, only give 10ms precision in
1000HZ, which is not enough for ftrace. to get high-precise timestamp, we must
implement a new native_sched_clock via reading the MIPS clock counter, but
since it is only 32bit long, so, overflow should be handled carefully.

this -v2 patch series is based on the -v1 patch series and incorporates the
feedback from Steven Rostedt and Thomas Gleixner.

read the following document, and play with it:
        Documentation/trace/ftrace.txt

Wu Zhangjin (6):
  mips static function tracer support
  mips dynamic function tracer support
  add an endian argument to scripts/recordmcount.pl
  mips function graph tracer support
  mips specific clock function to get precise timestamp
  mips specific system call tracer

 arch/mips/Kconfig                   |    7 +
 arch/mips/Makefile                  |    2 +
 arch/mips/include/asm/ftrace.h      |   35 ++++-
 arch/mips/include/asm/ptrace.h      |    2 +
 arch/mips/include/asm/reg.h         |    5 +
 arch/mips/include/asm/syscall.h     |   84 +++++++++
 arch/mips/include/asm/thread_info.h |    5 +-
 arch/mips/kernel/Makefile           |   12 ++
 arch/mips/kernel/csrc-r4k.c         |    2 +-
 arch/mips/kernel/entry.S            |    2 +-
 arch/mips/kernel/ftrace.c           |  350 +++++++++++++++++++++++++++++++++++
 arch/mips/kernel/ftrace_clock.c     |   71 +++++++
 arch/mips/kernel/mcount.S           |  185 ++++++++++++++++++
 arch/mips/kernel/mips_ksyms.c       |    5 +
 arch/mips/kernel/ptrace.c           |   14 ++-
 arch/mips/kernel/scall64-o32.S      |    2 +-
 arch/mips/kernel/vmlinux.lds.S      |    1 +
 kernel/trace/trace_clock.c          |    2 +-
 scripts/Makefile.build              |    1 +
 scripts/recordmcount.pl             |   32 +++-
 20 files changed, 805 insertions(+), 14 deletions(-)
 create mode 100644 arch/mips/include/asm/syscall.h
 create mode 100644 arch/mips/kernel/ftrace.c
 create mode 100644 arch/mips/kernel/ftrace_clock.c
 create mode 100644 arch/mips/kernel/mcount.S


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

* [PATCH v2 1/6] mips static function tracer support
  2009-05-29 14:58 [PATCH v2 0/6] mips-specific ftrace support wuzhangjin
@ 2009-05-29 15:02 ` wuzhangjin
  2009-05-29 15:03 ` [PATCH v2 2/6] mips dynamic " wuzhangjin
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: wuzhangjin @ 2009-05-29 15:02 UTC (permalink / raw)
  To: linux-mips, linux-kernel
  Cc: Wu Zhangjin, Steven Rostedt, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire

From: Wu Zhangjin <wuzj@lemote.com>

if -pg of gcc is enabled. a calling to _mcount will be inserted to each
kernel function. so, there is a possibility to trace the functions in
_mcount.

here is the implementation of mips specific _mcount for static function
tracer.

-ffunction-sections option not works with -pg, so disable it if enables
FUNCTION_TRACER.

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

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 09b1287..d5c01ca 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -4,6 +4,8 @@ config MIPS
 	select HAVE_IDE
 	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
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index c4cae9e..f86fb15 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 e961221..559a820 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -8,6 +8,11 @@ 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
+# Do not profile debug and lowlevel utilities
+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 +29,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..268724e
--- /dev/null
+++ b/arch/mips/kernel/mcount.S
@@ -0,0 +1,98 @@
+/*
+ * the mips-specific _mcount implementation
+ *
+ * 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>
+ */
+
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/ftrace.h>
+
+	.text
+	.set noreorder
+	.set noat
+
+	/* since there is a "addiu sp,sp,-8" before "jal _mcount" in 32bit */
+	.macro RESTORE_SP_FOR_32BIT
+#ifdef CONFIG_32BIT
+	PTR_ADDIU	sp, 8
+#endif
+	.endm
+
+	.macro MCOUNT_SAVE_REGS
+	PTR_SUBU	sp, PT_SIZE
+	PTR_S	ra, PT_R31(sp)
+	PTR_S	$1, 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	$1, 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
+	PTR_ADDIU	sp, PT_SIZE
+.endm
+
+	.macro MCOUNT_SET_ARGS
+	move	a0, ra		/* arg1: next ip, selfaddr */
+	move	a1, $1		/* arg2: the caller's next ip, parent */
+	PTR_SUBU a0, MCOUNT_INSN_SIZE
+	.endm
+
+	.macro RETURN_BACK
+	jr ra
+	move ra, $1
+	.endm
+
+NESTED(_mcount, PT_SIZE, ra)
+	RESTORE_SP_FOR_32BIT
+	PTR_L	t0, function_trace_stop
+	bnez	t0, ftrace_stub
+	nop
+
+	PTR_LA	t0, ftrace_stub
+	PTR_L	t1, ftrace_trace_function /* please don't use t1 later, safe? */
+	bne	t0, t1, static_trace
+	nop
+
+	j	ftrace_stub
+	nop
+
+static_trace:
+	MCOUNT_SAVE_REGS
+
+	MCOUNT_SET_ARGS			/* call *ftrace_trace_function */
+	jalr	t1
+	nop
+
+	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.0.4


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

* [PATCH v2 2/6] mips dynamic function tracer support
  2009-05-29 14:58 [PATCH v2 0/6] mips-specific ftrace support wuzhangjin
  2009-05-29 15:02 ` [PATCH v2 1/6] mips static function tracer support wuzhangjin
@ 2009-05-29 15:03 ` wuzhangjin
  2009-05-29 15:24   ` Steven Rostedt
  2009-05-31  6:47   ` Wang Liming
  2009-05-29 15:04 ` [PATCH v2 3/6] add an endian argument to scripts/recordmcount.pl wuzhangjin
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 17+ messages in thread
From: wuzhangjin @ 2009-05-29 15:03 UTC (permalink / raw)
  To: linux-mips, linux-kernel
  Cc: Wu Zhangjin, Steven Rostedt, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire

From: Wu Zhangjin <wuzj@lemote.com>

dynamic function tracer need to replace "nop" to "jumps & links" and
something reversely.

Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Wu Zhangjin <wuzj@lemote.com>
---
 arch/mips/Kconfig              |    3 +
 arch/mips/include/asm/ftrace.h |   10 ++
 arch/mips/kernel/Makefile      |    2 +
 arch/mips/kernel/ftrace.c      |  207 ++++++++++++++++++++++++++++++++++++++++
 arch/mips/kernel/mcount.S      |   31 ++++++
 scripts/recordmcount.pl        |   17 +++-
 6 files changed, 267 insertions(+), 3 deletions(-)
 create mode 100644 arch/mips/kernel/ftrace.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index d5c01ca..0c00536 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -6,6 +6,9 @@ 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
+	select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
 	# Horrible source of confusion.  Die, die, die ...
 	select EMBEDDED
 	select RTC_LIB
diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h
index 5f8ebcf..b4970c9 100644
--- a/arch/mips/include/asm/ftrace.h
+++ b/arch/mips/include/asm/ftrace.h
@@ -19,6 +19,16 @@
 extern void _mcount(void);
 #define mcount _mcount
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/* reloction of mcount call site is the same as the address */
+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 559a820..8dabcc6 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -10,6 +10,7 @@ obj-y		+= cpu-probe.o branch.o entry.o genex.o irq.o process.o \
 
 ifdef CONFIG_FUNCTION_TRACER
 # Do not profile debug and lowlevel utilities
+CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
 endif
 
@@ -30,6 +31,7 @@ obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
 
 obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o
+obj-$(CONFIG_FUNCTION_TRACER)	+= 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..ad490cc
--- /dev/null
+++ b/arch/mips/kernel/ftrace.c
@@ -0,0 +1,207 @@
+/*
+ * 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/spinlock.h>
+#include <linux/hardirq.h>
+#include <linux/uaccess.h>
+#include <linux/percpu.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/ftrace.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/asm.h>
+#include <asm/unistd.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 */
+
+static unsigned int ftrace_nop = 0x00000000;
+
+static unsigned char *ftrace_call_replace(unsigned long op_code,
+					  unsigned long addr)
+{
+    static unsigned int op;
+
+    op = op_code | ((addr >> 2) & ADDR_MASK);
+
+    return (unsigned char *) &op;
+}
+
+static atomic_t nmi_running = ATOMIC_INIT(0);
+static int mod_code_status;	/* holds return value of text write */
+static int mod_code_write;	/* set when NMI should do the write */
+static void *mod_code_ip;	/* holds the IP to write to */
+static void *mod_code_newcode;	/* holds the text to write to the IP */
+
+static unsigned nmi_wait_count;
+static atomic_t nmi_update_count = ATOMIC_INIT(0);
+
+int ftrace_arch_read_dyn_info(char *buf, int size)
+{
+    int r;
+
+    r = snprintf(buf, size, "%u %u",
+		 nmi_wait_count, atomic_read(&nmi_update_count));
+    return r;
+}
+
+static void ftrace_mod_code(void)
+{
+    /*
+     * Yes, more than one CPU process can be writing to mod_code_status.
+     *    (and the code itself)
+     * But if one were to fail, then they all should, and if one were
+     * to succeed, then they all should.
+     */
+    mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode,
+					 MCOUNT_INSN_SIZE);
+
+    /* if we fail, then kill any new writers */
+    if (mod_code_status)
+		mod_code_write = 0;
+}
+
+void ftrace_nmi_enter(void)
+{
+    atomic_inc(&nmi_running);
+    /* Must have nmi_running seen before reading write flag */
+    smp_mb();
+    if (mod_code_write) {
+		ftrace_mod_code();
+		atomic_inc(&nmi_update_count);
+    }
+}
+
+void ftrace_nmi_exit(void)
+{
+    /* Finish all executions before clearing nmi_running */
+    smp_wmb();
+    atomic_dec(&nmi_running);
+}
+
+static void wait_for_nmi(void)
+{
+    int waited = 0;
+
+    while (atomic_read(&nmi_running)) {
+		waited = 1;
+		cpu_relax();
+    }
+
+    if (waited)
+		nmi_wait_count++;
+}
+
+static int do_ftrace_mod_code(unsigned long ip, void *new_code)
+{
+    mod_code_ip = (void *) ip;
+    mod_code_newcode = new_code;
+
+    /* The buffers need to be visible before we let NMIs write them */
+    smp_wmb();
+
+    mod_code_write = 1;
+
+    /* Make sure write bit is visible before we wait on NMIs */
+    smp_mb();
+
+    wait_for_nmi();
+
+    /* Make sure all running NMIs have finished before we write the code */
+    smp_mb();
+
+    ftrace_mod_code();
+
+    /* Make sure the write happens before clearing the bit */
+    smp_wmb();
+
+    mod_code_write = 0;
+
+    /* make sure NMIs see the cleared bit */
+    smp_mb();
+
+    wait_for_nmi();
+
+    return mod_code_status;
+}
+
+static unsigned char *ftrace_nop_replace(void)
+{
+    return (unsigned char *) &ftrace_nop;
+}
+
+static int
+ftrace_modify_code(unsigned long ip, unsigned char *old_code,
+		   unsigned char *new_code)
+{
+    unsigned char replaced[MCOUNT_INSN_SIZE];
+
+    /* read the text we want to modify */
+    if (probe_kernel_read(replaced, (void *) ip, MCOUNT_INSN_SIZE))
+		return -EFAULT;
+
+    /* Make sure it is what we expect it to be */
+    if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0)
+		return -EINVAL;
+
+    /* replace the text with the new text */
+    if (do_ftrace_mod_code(ip, new_code))
+		return -EPERM;
+
+    return 0;
+}
+
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+    unsigned char *new, *old;
+
+    old = ftrace_call_replace(JAL, addr);
+    new = ftrace_nop_replace();
+
+    return ftrace_modify_code(rec->ip, old, new);
+}
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+    unsigned char *new, *old;
+
+    old = ftrace_nop_replace();
+    new = ftrace_call_replace(JAL, addr);
+
+    return ftrace_modify_code(rec->ip, old, new);
+}
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+    unsigned long ip = (unsigned long) (&ftrace_call);
+    unsigned char old[MCOUNT_INSN_SIZE], *new;
+    int ret;
+
+    memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
+    new = ftrace_call_replace(JAL, (unsigned long) func);
+    ret = ftrace_modify_code(ip, old, new);
+
+    return ret;
+}
+
+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 268724e..ce8a0ba 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -67,6 +67,35 @@
 	move ra, $1
 	.endm
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+LEAF(_mcount)
+	RESTORE_SP_FOR_32BIT
+ 	RETURN_BACK
+ 	END(_mcount)
+
+NESTED(ftrace_caller, PT_SIZE, ra)
+	RESTORE_SP_FOR_32BIT
+	lw	t0, function_trace_stop
+	bnez	t0, ftrace_stub
+	nop
+
+	MCOUNT_SAVE_REGS
+
+	MCOUNT_SET_ARGS
+	.globl ftrace_call
+ftrace_call:
+	jal	ftrace_stub
+	nop
+
+	MCOUNT_RESTORE_REGS
+	.globl ftrace_stub
+ftrace_stub:
+	RETURN_BACK
+	END(ftrace_caller)
+
+#else	/* ! CONFIG_DYNAMIC_FTRACE */
+
 NESTED(_mcount, PT_SIZE, ra)
 	RESTORE_SP_FOR_32BIT
 	PTR_L	t0, function_trace_stop
@@ -94,5 +123,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 409596e..a5d2ace 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -213,6 +213,17 @@ if ($arch eq "x86_64") {
     if ($is_module eq "0") {
         $cc .= " -mconstant-gp";
     }
+
+} elsif ($arch eq "mips") {
+	$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
+	$ld .= " -melf".$bits."btsmip";
+
+	$cc .= " -mno-abicalls -fno-pic ";
+
+    if ($bits == 64) {
+		$type = ".dword";
+    }
+
 } else {
     die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
 }
@@ -441,12 +452,12 @@ if ($#converts >= 0) {
     #
     # Step 5: set up each local function as a global
     #
-    `$objcopy $globallist $inputfile $globalobj`;
+    `$objcopy $globallist $inputfile $globalobj 2>&1 >/dev/null`;
 
     #
     # Step 6: Link the global version to our list.
     #
-    `$ld -r $globalobj $mcount_o -o $globalmix`;
+    `$ld -r $globalobj $mcount_o -o $globalmix 2>&1 >/dev/null`;
 
     #
     # Step 7: Convert the local functions back into local symbols
@@ -454,7 +465,7 @@ if ($#converts >= 0) {
     `$objcopy $locallist $globalmix $inputfile`;
 
     # Remove the temp files
-    `$rm $globalobj $globalmix`;
+    `$rm $globalobj $globalmix 2>&1 >/dev/null`;
 
 } else {
 
-- 
1.6.0.4


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

* [PATCH v2 3/6] add an endian argument to scripts/recordmcount.pl
  2009-05-29 14:58 [PATCH v2 0/6] mips-specific ftrace support wuzhangjin
  2009-05-29 15:02 ` [PATCH v2 1/6] mips static function tracer support wuzhangjin
  2009-05-29 15:03 ` [PATCH v2 2/6] mips dynamic " wuzhangjin
@ 2009-05-29 15:04 ` wuzhangjin
  2009-05-29 15:21   ` Steven Rostedt
  2009-05-29 15:05 ` [PATCH v2 4/6] mips function graph tracer support wuzhangjin
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: wuzhangjin @ 2009-05-29 15:04 UTC (permalink / raw)
  To: linux-mips, linux-kernel
  Cc: Wu Zhangjin, Steven Rostedt, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire

From: Wu Zhangjin <wuzj@lemote.com>

mips architecture need this argument to handle big/little endian
differently.

Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Wu Zhangjin <wuzj@lemote.com>
---
 scripts/Makefile.build  |    1 +
 scripts/recordmcount.pl |   21 +++++++++++++++------
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 5c4b7a4..548d575 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -207,6 +207,7 @@ endif
 
 ifdef CONFIG_FTRACE_MCOUNT_RECORD
 cmd_record_mcount = 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 a5d2ace..57a2b6a 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -100,13 +100,13 @@ $P =~ s@.*/@@g;
 
 my $V = '0.1';
 
-if ($#ARGV < 7) {
-	print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
+if ($#ARGV < 8) {
+	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
@@ -216,9 +216,18 @@ if ($arch eq "x86_64") {
 
 } elsif ($arch eq "mips") {
 	$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
-	$ld .= " -melf".$bits."btsmip";
+	$objdump .= " -Melf-trad".$endian."mips ";
 
-	$cc .= " -mno-abicalls -fno-pic ";
+	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) {
 		$type = ".dword";
-- 
1.6.0.4


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

* [PATCH v2 4/6] mips function graph tracer support
  2009-05-29 14:58 [PATCH v2 0/6] mips-specific ftrace support wuzhangjin
                   ` (2 preceding siblings ...)
  2009-05-29 15:04 ` [PATCH v2 3/6] add an endian argument to scripts/recordmcount.pl wuzhangjin
@ 2009-05-29 15:05 ` wuzhangjin
  2009-05-29 15:05 ` [PATCH v2 5/6] mips specific clock function to get precise timestamp wuzhangjin
  2009-05-29 15:06 ` [PATCH v2 6/6] mips specific system call tracer wuzhangjin
  5 siblings, 0 replies; 17+ messages in thread
From: wuzhangjin @ 2009-05-29 15:05 UTC (permalink / raw)
  To: linux-mips, linux-kernel
  Cc: Wu Zhangjin, Steven Rostedt, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire

From: Wu Zhangjin <wuzj@lemote.com>

this works something like -finstrument-functions does, instead of using

                void __cyg_profile_func_enter (void *this_fn,
                                                  void *call_site);
                   void __cyg_profile_func_exit  (void *this_fn,
                                                  void *call_site);

-pg use _mcount, so some tricks are adoptive by the author of orignal function
graph tracer:

	the _mcount function will call prepare_function_return to save the
	parent_ip, ip and calltime in a tracing array, if success, the
	address of a hooker function named return_to_handler will be
	substitued to the parent_ip, so, after return from _mcount it will
	call the return_to_handler, not back to the parent_ip, but calling
	ftrace_return_to_handler to remember the rettime, and return the
	parent_ip to let return_to_handler go back to the real parent.

Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Wu Zhangjin <wuzj@lemote.com>
---
 arch/mips/Kconfig              |    1 +
 arch/mips/kernel/ftrace.c      |   72 ++++++++++++++++++++++++++++++++++++++++
 arch/mips/kernel/mcount.S      |   58 +++++++++++++++++++++++++++++++-
 arch/mips/kernel/vmlinux.lds.S |    1 +
 4 files changed, 131 insertions(+), 1 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 0c00536..ac1437e 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -9,6 +9,7 @@ config MIPS
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
+	select HAVE_FUNCTION_GRAPH_TRACER
 	# Horrible source of confusion.  Die, die, die ...
 	select EMBEDDED
 	select RTC_LIB
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index ad490cc..123cc09 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -205,3 +205,75 @@ int __init ftrace_dyn_arch_init(void *data)
     return 0;
 }
 #endif				/* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+#define JMP	0x08000000			/* jump to target directly */
+extern void ftrace_graph_call(void);
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+    unsigned long ip = (unsigned long) (&ftrace_graph_call);
+    unsigned char old[MCOUNT_INSN_SIZE], *new;
+    int ret;
+
+	/* j ftrace_stub */
+    memcpy(old, (unsigned long *) ip, MCOUNT_INSN_SIZE);
+    new = ftrace_call_replace(JMP, (unsigned long) ftrace_graph_caller);
+
+    ret = ftrace_modify_code(ip, old, new);
+
+    return ret;
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+    unsigned long ip = (unsigned long) (&ftrace_graph_call);
+    unsigned char old[MCOUNT_INSN_SIZE], *new;
+    int ret;
+
+	/* j ftrace_graph_caller */
+    memcpy(old, (unsigned long *) ip, MCOUNT_INSN_SIZE);
+    new = ftrace_call_replace(JMP, (unsigned long) ftrace_stub);
+
+    ret = ftrace_modify_code(ip, old, new);
+
+    return ret;
+}
+
+#endif				/* !CONFIG_DYNAMIC_FTRACE */
+
+/*
+ * Hook the return address and push it in the stack of return addrs
+ * in current thread info.
+ */
+
+unsigned long prepare_ftrace_return(unsigned long ip,
+				    unsigned long parent_ip)
+{
+    struct ftrace_graph_ent trace;
+
+    /* Nmi's are currently unsupported */
+    if (unlikely(in_nmi()))
+		goto out;
+
+    if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		goto out;
+
+    if (ftrace_push_return_trace(parent_ip, ip, &trace.depth) == -EBUSY)
+		goto out;
+
+    trace.func = ip;
+
+    /* Only trace if the calling function expects to */
+    if (!ftrace_graph_entry(&trace)) {
+		current->curr_ret_stack--;
+		goto out;
+    }
+    return (unsigned long) &return_to_handler;
+out:
+    return parent_ip;
+}
+#endif				/* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index ce8a0ba..bd58f16 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -28,6 +28,10 @@
 	PTR_SUBU	sp, PT_SIZE
 	PTR_S	ra, PT_R31(sp)
 	PTR_S	$1, PT_R1(sp)
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	PTR_S	v0, PT_R2(sp)
+	PTR_S	v1, PT_R3(sp)
+#endif
 	PTR_S	a0, PT_R4(sp)
 	PTR_S	a1, PT_R5(sp)
 	PTR_S	a2, PT_R6(sp)
@@ -43,6 +47,10 @@
 	.macro MCOUNT_RESTORE_REGS
 	PTR_L	ra, PT_R31(sp)
 	PTR_L	$1, PT_R1(sp)
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	PTR_L	v0, PT_R2(sp)
+	PTR_L	v1, PT_R3(sp)
+#endif
 	PTR_L	a0, PT_R4(sp)
 	PTR_L	a1, PT_R5(sp)
 	PTR_L	a2, PT_R6(sp)
@@ -89,6 +97,14 @@ ftrace_call:
 	nop
 
 	MCOUNT_RESTORE_REGS
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.globl ftrace_graph_call
+ftrace_graph_call:
+	j	ftrace_stub
+	nop
+#endif
+
 	.globl ftrace_stub
 ftrace_stub:
 	RETURN_BACK
@@ -106,7 +122,15 @@ NESTED(_mcount, PT_SIZE, ra)
 	PTR_L	t1, ftrace_trace_function /* please don't use t1 later, safe? */
 	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
 	j	ftrace_stub
 	nop
 
@@ -125,5 +149,37 @@ ftrace_stub:
 
 #endif	/* ! CONFIG_DYNAMIC_FTRACE */
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+NESTED(ftrace_graph_caller, PT_SIZE, ra)
+	MCOUNT_SAVE_REGS
+
+	MCOUNT_SET_ARGS
+	jal	prepare_ftrace_return
+	nop
+
+	/* overwrite the parent as &return_to_handler: v0 -> $1(at) */
+	PTR_S	v0, PT_R1(sp)
+
+	MCOUNT_RESTORE_REGS
+	RETURN_BACK
+	END(ftrace_graph_caller)
+
+	.align	2
+	.globl	return_to_handler
+return_to_handler:
+	MCOUNT_SAVE_REGS
+
+	jal	ftrace_return_to_handler
+	nop
+
+	/* restore the real parent address: v0 -> ra */
+	PTR_S	v0, PT_R31(sp)
+
+	MCOUNT_RESTORE_REGS
+	RETURN_BACK
+
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
 	.set at
 	.set reorder
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 58738c8..67435e5 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -36,6 +36,7 @@ SECTIONS
 		SCHED_TEXT
 		LOCK_TEXT
 		KPROBES_TEXT
+		IRQENTRY_TEXT
 		*(.text.*)
 		*(.fixup)
 		*(.gnu.warning)
-- 
1.6.0.4


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

* [PATCH v2 5/6] mips specific clock function to get precise timestamp
  2009-05-29 14:58 [PATCH v2 0/6] mips-specific ftrace support wuzhangjin
                   ` (3 preceding siblings ...)
  2009-05-29 15:05 ` [PATCH v2 4/6] mips function graph tracer support wuzhangjin
@ 2009-05-29 15:05 ` wuzhangjin
  2009-05-29 15:06 ` [PATCH v2 6/6] mips specific system call tracer wuzhangjin
  5 siblings, 0 replies; 17+ messages in thread
From: wuzhangjin @ 2009-05-29 15:05 UTC (permalink / raw)
  To: linux-mips, linux-kernel
  Cc: Wu Zhangjin, Steven Rostedt, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire

From: Wu Zhangjin <wuzj@lemote.com>

by default, trace_clock_local calling sched_clock(jiffies-based) to get
timestamp, in x86, there is a tsc(64bit) based sched_clock, but in mips,
the 'tsc'(clock counter) is only 32bit long, which will easily rollover,
and there is no existing high precise sched_clock in mips, we need to
get one ourselves.

to avoid invading the whole linux-mips, i do not want to implement a
tsc-based native_sched_clock instead of sched_clock like x86 does.
because, there is a need to handling rollover of the only 32-bit long
'tsc' of mips, which will need extra overhead. in reality, i have tried
to do it, but made the kernel hangs when booting, I'm not sure why it
not work.

so, I just implement a native_sched_clock in arch/mips/kernel/ftrace.c,
but not override the original sched_clock(). to get high precise
timestamp, we implement a native_trace_clock_local, which will not call
original sched_clock again, but native_sched_clock().

and what about the trace_clock and trace_clock_global function, should
we also implement a mips-secific one? I'm not sure.

Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Wu Zhangjin <wuzj@lemote.com>
---
 arch/mips/kernel/Makefile       |    2 +
 arch/mips/kernel/csrc-r4k.c     |    2 +-
 arch/mips/kernel/ftrace_clock.c |   71 +++++++++++++++++++++++++++++++++++++++
 kernel/trace/trace_clock.c      |    2 +-
 4 files changed, 75 insertions(+), 2 deletions(-)
 create mode 100644 arch/mips/kernel/ftrace_clock.c

diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 8dabcc6..44ec7e0 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -11,6 +11,7 @@ obj-y		+= cpu-probe.o branch.o entry.o genex.o irq.o process.o \
 ifdef CONFIG_FUNCTION_TRACER
 # Do not profile debug and lowlevel utilities
 CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_ftrace_clock.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
 endif
 
@@ -32,6 +33,7 @@ obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
 
 obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o
 obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o
+obj-$(CONFIG_NOP_TRACER)	+= ftrace_clock.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/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c
index e95a3cd..3da1c7a 100644
--- a/arch/mips/kernel/csrc-r4k.c
+++ b/arch/mips/kernel/csrc-r4k.c
@@ -10,7 +10,7 @@
 
 #include <asm/time.h>
 
-static cycle_t c0_hpt_read(struct clocksource *cs)
+static cycle_t notrace c0_hpt_read(struct clocksource *cs)
 {
 	return read_c0_count();
 }
diff --git a/arch/mips/kernel/ftrace_clock.c b/arch/mips/kernel/ftrace_clock.c
new file mode 100644
index 0000000..8ad896e
--- /dev/null
+++ b/arch/mips/kernel/ftrace_clock.c
@@ -0,0 +1,71 @@
+/*
+ * 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>
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/jiffies.h>
+#include <linux/clocksource.h>
+
+/*
+ * mips-specific high precise sched_clock() implementation,
+ *
+ * currently, this is only needed in ftrace, so not override the original
+ * sched_clock().
+ */
+
+unsigned long long native_sched_clock(void)
+{
+	u64 current_cycles;
+	static unsigned long old_jiffies;
+	static u64 time, old_cycles;
+
+	preempt_disable_notrace();
+    /* update timestamp to avoid missing the timer interrupt */
+	if (time_before(jiffies, old_jiffies)) {
+		old_jiffies = jiffies;
+		time = sched_clock();
+		old_cycles = clock->cycle_last;
+	}
+	current_cycles = clock->read(clock);
+
+	time = (time + cyc2ns(clock, (current_cycles - old_cycles)
+				& clock->mask));
+
+	old_cycles = current_cycles;
+	preempt_enable_no_resched_notrace();
+
+	return time;
+}
+
+/*
+ * native_trace_clock_local(): the simplest and least coherent tracing clock.
+ *
+ * Useful for tracing that does not cross to other CPUs nor
+ * does it go through idle events.
+ */
+u64 native_trace_clock_local(void)
+{
+	unsigned long flags;
+	u64 clock;
+
+	/*
+	 * herein, we use the above native_sched_clock() to get high precise
+	 * timestamp, because the original sched_clock in mips is jiffies based,
+	 * which not have enough precision.
+	 */
+	raw_local_irq_save(flags);
+	clock = native_sched_clock();
+	raw_local_irq_restore(flags);
+
+	return clock;
+}
+
+u64 trace_clock_local(void)
+		__attribute__((alias("native_trace_clock_local")));
+
diff --git a/kernel/trace/trace_clock.c b/kernel/trace/trace_clock.c
index b588fd8..78c98c8 100644
--- a/kernel/trace/trace_clock.c
+++ b/kernel/trace/trace_clock.c
@@ -26,7 +26,7 @@
  * Useful for tracing that does not cross to other CPUs nor
  * does it go through idle events.
  */
-u64 notrace trace_clock_local(void)
+u64 __attribute__((weak)) notrace trace_clock_local(void)
 {
 	unsigned long flags;
 	u64 clock;
-- 
1.6.0.4


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

* [PATCH v2 6/6] mips specific system call tracer
  2009-05-29 14:58 [PATCH v2 0/6] mips-specific ftrace support wuzhangjin
                   ` (4 preceding siblings ...)
  2009-05-29 15:05 ` [PATCH v2 5/6] mips specific clock function to get precise timestamp wuzhangjin
@ 2009-05-29 15:06 ` wuzhangjin
  5 siblings, 0 replies; 17+ messages in thread
From: wuzhangjin @ 2009-05-29 15:06 UTC (permalink / raw)
  To: linux-mips, linux-kernel
  Cc: Wu Zhangjin, Steven Rostedt, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire

From: Wu Zhangjin <wuzj@lemote.com>

FIXME: there are several different sys_call_entry in mips64, but
currently, i only use the the one in arch/mips/kernel/scall64-o32.S
so,if people not use o32 standard, it will not compiled normally.

the system call tracing demo in a debian system on
qemu-system-mipsel/malta:

debian-mips-malta:~# mount -t debugfs nodev /debug
debian-mips-malta:~# echo 20000 > /debug/tracing/buffer_size_kb
debian-mips-malta:~# cat /debug/tracing/available_tracers
syscall nop
debian-mips-malta:~# echo syscall > /debug/tracing/current_tracer
debian-mips-malta:~# echo 1 > /debug/tracing/tracing_enabled
debian-mips-malta:~# sleep 1
debian-mips-malta:~# echo 0 > /debug/tracing/tracing_enabled
debian-mips-malta:~# cat /debug/tracing/trace | head -20
           <...>-533   [000]    60.458291: sys_write(fd: 1, buf: 4fc408, count: 8)
           <...>-533   [000]    64.325614: sys_getrlimit(resource: 3, rlim: 530020)
           <...>-533   [000]    64.327089: sys_read(fd: 2, buf: 4fc008, count: 6)
           <...>-533   [000]    64.969663: sys_exit(error_code: 2)
           <...>-533   [000]    65.608794: sys_exit(error_code: 2)
           <...>-533   [000]    66.231796: sys_read(fd: 2, buf: 4fc008, count: 6)
           <...>-533   [000]    66.913687: sys_open(filename: 1, flags: 0, mode: a)
           <...>-533   [000]    66.914617: sys_exit(error_code: 1)
           <...>-533   [000]    70.797507: sys_exit(error_code: 503be8)
           <...>-536   [000]    70.833108: sys_exit(error_code: 2aac6cfc)
           <...>-536   [000]    70.833897: sys_exit(error_code: 2aac6540)
           <...>-536   [000]    70.835711: sys_exit(error_code: 2aac6cfc)
           <...>-536   [000]    70.840609: sys_lchown(filename: 3, user: 7fb08b38, group: 20)
           <...>-533   [000]    71.877785: sys_open(filename: ffffffff, flags: 7fcf08c8, mode: b)
           <...>-533   [000]    75.531122: sys_open(filename: 1, flags: 0, mode: a)

Signed-off-by: Wu Zhangjin <wuzj@lemote.com>
---
 arch/mips/Kconfig                   |    1 +
 arch/mips/include/asm/ptrace.h      |    2 +
 arch/mips/include/asm/reg.h         |    5 ++
 arch/mips/include/asm/syscall.h     |   84 +++++++++++++++++++++++++++++++++++
 arch/mips/include/asm/thread_info.h |    5 ++-
 arch/mips/kernel/Makefile           |    1 +
 arch/mips/kernel/entry.S            |    2 +-
 arch/mips/kernel/ftrace.c           |   71 +++++++++++++++++++++++++++++
 arch/mips/kernel/ptrace.c           |   14 +++++-
 arch/mips/kernel/scall64-o32.S      |    2 +-
 10 files changed, 182 insertions(+), 5 deletions(-)
 create mode 100644 arch/mips/include/asm/syscall.h

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index ac1437e..f488027 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -10,6 +10,7 @@ config MIPS
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
 	select HAVE_FUNCTION_GRAPH_TRACER
+	select HAVE_FTRACE_SYSCALLS
 	# Horrible source of confusion.  Die, die, die ...
 	select EMBEDDED
 	select RTC_LIB
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index ce47118..32e5b62 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -45,6 +45,8 @@ struct pt_regs {
 	unsigned long cp0_badvaddr;
 	unsigned long cp0_cause;
 	unsigned long cp0_epc;
+	/* Used for restarting system calls */
+	unsigned long orig_v0;
 #ifdef CONFIG_MIPS_MT_SMTC
 	unsigned long cp0_tcstatus;
 #endif /* CONFIG_MIPS_MT_SMTC */
diff --git a/arch/mips/include/asm/reg.h b/arch/mips/include/asm/reg.h
index 634b55d..93d66bc 100644
--- a/arch/mips/include/asm/reg.h
+++ b/arch/mips/include/asm/reg.h
@@ -65,6 +65,8 @@
 #define EF_CP0_CAUSE		43
 #define EF_UNUSED0		44
 
+#define EF_ORIG_V0		45
+
 #define EF_SIZE			180
 
 #endif
@@ -121,6 +123,9 @@
 #define EF_CP0_STATUS		36
 #define EF_CP0_CAUSE		37
 
+
+#define EF_ORIG_V0			38
+
 #define EF_SIZE			304	/* size in bytes */
 
 #endif /* CONFIG_64BIT */
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
new file mode 100644
index 0000000..b785098
--- /dev/null
+++ b/arch/mips/include/asm/syscall.h
@@ -0,0 +1,84 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * Copyright (C) 2008 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2009 DSLab, Lanzhou University, China
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * See asm-generic/syscall.h for descriptions of what we must do here.
+ */
+
+#ifndef _ASM_SYSCALL_H
+#define _ASM_SYSCALL_H	1
+
+#include <linux/sched.h>
+
+static inline long syscall_get_nr(struct task_struct *task,
+				  struct pt_regs *regs)
+{
+	/*        syscall   Exc-Code: 0 1000 00     v0 */
+	return ((regs->cp0_cause&0xff) == 0x20)  ? regs->regs[2] : -1L;
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+				    struct pt_regs *regs)
+{
+	regs->regs[2] = regs->orig_v0;
+}
+
+static inline long syscall_get_error(struct task_struct *task,
+				     struct pt_regs *regs)
+{
+	return regs->regs[2] ? -regs->regs[2] : 0;
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+					    struct pt_regs *regs)
+{
+	return regs->regs[2];
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+					    struct pt_regs *regs,
+					    int error, long val)
+{
+	if (error)
+		regs->regs[2] = -error;
+	else
+		regs->regs[2] = val;
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 unsigned long *args)
+{
+#ifdef CONFIG_32BIT
+	/* fixme: only 4 argument register available in mip32, so, how to handle
+	 * others?
+	 */
+	BUG_ON(i + n > 4);
+#else
+	BUG_ON(i + n > 6);
+#endif
+	memcpy(args, &regs->regs[4 + i], n * sizeof(args[0]));
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 const unsigned long *args)
+{
+#ifdef CONFIG_32BIT
+	BUG_ON(i + n > 4);
+#else
+	BUG_ON(i + n > 6);
+#endif
+	memcpy(&regs->regs[4 + i], args, n * sizeof(args[0]));
+}
+
+#endif	/* _ASM_SYSCALL_H */
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 143a481..1d55dc0 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -128,6 +128,7 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define TIF_32BIT_ADDR		23	/* 32-bit address space (o32/n32) */
 #define TIF_FPUBOUND		24	/* thread bound to FPU-full CPU set */
 #define TIF_LOAD_WATCH		25	/* If set, load watch registers */
+#define TIF_SYSCALL_FTRACE	27	/* for ftrace syscall instrumentation */
 #define TIF_SYSCALL_TRACE	31	/* syscall trace active */
 
 #ifdef CONFIG_MIPS32_O32
@@ -151,11 +152,13 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define _TIF_32BIT_ADDR		(1<<TIF_32BIT_ADDR)
 #define _TIF_FPUBOUND		(1<<TIF_FPUBOUND)
 #define _TIF_LOAD_WATCH		(1<<TIF_LOAD_WATCH)
+#define _TIF_SYSCALL_FTRACE	(1<<TIF_SYSCALL_FTRACE)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK		(0x0000ffef & ~_TIF_SECCOMP)
 /* work to do on any return to u-space */
-#define _TIF_ALLWORK_MASK	(0x8000ffff & ~_TIF_SECCOMP)
+#define _TIF_ALLWORK_MASK	\
+	((0x8000ffff & ~_TIF_SECCOMP) | _TIF_SYSCALL_FTRACE)
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 44ec7e0..1114c85 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
 
 obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o
 obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o
+obj-$(CONFIG_FTRACE_SYSCALLS)	+= ftrace.o
 obj-$(CONFIG_NOP_TRACER)	+= ftrace_clock.o
 
 obj-$(CONFIG_CPU_LOONGSON2)	+= r4k_fpu.o r4k_switch.o
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index ffa3310..786e4ef 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -167,7 +167,7 @@ work_notifysig:				# deal with pending signals and
 FEXPORT(syscall_exit_work_partial)
 	SAVE_STATIC
 syscall_exit_work:
-	li	t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
+	li	t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_FTRACE
 	and	t0, a2			# a2 is preloaded with TI_FLAGS
 	beqz	t0, work_pending	# trace bit set?
 	local_irq_enable		# could let do_syscall_trace()
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index 123cc09..56614e2 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -22,6 +22,8 @@
 #include <asm/asm.h>
 #include <asm/unistd.h>
 
+#include <trace/syscall.h>
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 #define JAL 0x0c000000	/* jump & link: ip --> ra, jump to target */
@@ -277,3 +279,72 @@ out:
     return parent_ip;
 }
 #endif				/* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_FTRACE_SYSCALLS
+
+extern unsigned long __start_syscalls_metadata[];
+extern unsigned long __stop_syscalls_metadata[];
+
+/* fixme: in mips64, there are different entries of sys_call_table when using
+ * different standards, in loongson2f based machines: Fuloong & Yeeloong, the
+ * system use o32 standard, so here, we only use the sys_call_table in
+ * arch/mips/kernel/scall64-o32.S */
+
+extern unsigned long *sys_call_table;
+
+static struct syscall_metadata **syscalls_metadata;
+
+static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
+{
+	struct syscall_metadata *start;
+	struct syscall_metadata *stop;
+	char str[KSYM_SYMBOL_LEN];
+
+
+	start = (struct syscall_metadata *)__start_syscalls_metadata;
+	stop = (struct syscall_metadata *)__stop_syscalls_metadata;
+	kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
+
+	for ( ; start < stop; start++) {
+		if (start->name && !strcmp(start->name, str))
+			return start;
+	}
+	return NULL;
+}
+
+struct syscall_metadata *syscall_nr_to_meta(int nr)
+{
+	if (!syscalls_metadata || nr >= __NR_Linux_syscalls || nr < 0)
+		return NULL;
+
+	return syscalls_metadata[nr];
+}
+
+void arch_init_ftrace_syscalls(void)
+{
+	int i;
+	struct syscall_metadata *meta;
+	unsigned long **psys_syscall_table = &sys_call_table;
+	static atomic_t refs;
+
+	if (atomic_inc_return(&refs) != 1)
+		goto end;
+
+	syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
+					__NR_Linux_syscalls, GFP_KERNEL);
+	if (!syscalls_metadata) {
+		WARN_ON(1);
+		return;
+	}
+
+	for (i = 0; i < __NR_Linux_syscalls; i++) {
+		meta = find_syscall_meta(psys_syscall_table[i]);
+		syscalls_metadata[i] = meta;
+	}
+	return;
+
+	/* Paranoid: avoid overflow */
+end:
+	atomic_dec(&refs);
+}
+#endif	/* CONFIG_FTRACE_SYSCALLS */
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 054861c..fa762dc 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -25,6 +25,7 @@
 #include <linux/security.h>
 #include <linux/audit.h>
 #include <linux/seccomp.h>
+#include <linux/ftrace.h>
 
 #include <asm/byteorder.h>
 #include <asm/cpu.h>
@@ -39,6 +40,7 @@
 #include <asm/bootinfo.h>
 #include <asm/reg.h>
 
+#include <trace/syscall.h>
 /*
  * Called by kernel/ptrace.c when detaching..
  *
@@ -60,7 +62,7 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data)
 	struct pt_regs *regs;
 	int i;
 
-	if (!access_ok(VERIFY_WRITE, data, 38 * 8))
+	if (!access_ok(VERIFY_WRITE, data, 39 * 8))
 		return -EIO;
 
 	regs = task_pt_regs(child);
@@ -73,6 +75,7 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data)
 	__put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
 	__put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
 	__put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
+	__put_user((long)regs->orig_v0, data + EF_ORIG_V0 - EF_R0);
 
 	return 0;
 }
@@ -87,7 +90,7 @@ int ptrace_setregs(struct task_struct *child, __s64 __user *data)
 	struct pt_regs *regs;
 	int i;
 
-	if (!access_ok(VERIFY_READ, data, 38 * 8))
+	if (!access_ok(VERIFY_READ, data, 39 * 8))
 		return -EIO;
 
 	regs = task_pt_regs(child);
@@ -97,6 +100,7 @@ int ptrace_setregs(struct task_struct *child, __s64 __user *data)
 	__get_user(regs->lo, data + EF_LO - EF_R0);
 	__get_user(regs->hi, data + EF_HI - EF_R0);
 	__get_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
+	__get_user(regs->orig_v0, data + EF_ORIG_V0 - EF_R0);
 
 	/* badvaddr, status, and cause may not be written.  */
 
@@ -575,6 +579,9 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
 	if (!(current->ptrace & PT_PTRACED))
 		goto out;
 
+	if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+		ftrace_syscall_exit(regs);
+
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
 		goto out;
 
@@ -594,6 +601,9 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
 	}
 
 out:
+	if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+		ftrace_syscall_enter(regs);
+
 	if (unlikely(current->audit_context) && !entryexit)
 		audit_syscall_entry(audit_arch(), regs->regs[0],
 				    regs->regs[4], regs->regs[5],
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index a5598b2..dd1f13a 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -202,7 +202,7 @@ einval:	li	v0, -ENOSYS
 
 	.align	3
 	.type	sys_call_table,@object
-sys_call_table:
+EXPORT(sys_call_table)
 	PTR	sys32_syscall			/* 4000 */
 	PTR	sys_exit
 	PTR	sys_fork
-- 
1.6.0.4


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

* Re: [PATCH v2 3/6] add an endian argument to scripts/recordmcount.pl
  2009-05-29 15:04 ` [PATCH v2 3/6] add an endian argument to scripts/recordmcount.pl wuzhangjin
@ 2009-05-29 15:21   ` Steven Rostedt
  0 siblings, 0 replies; 17+ messages in thread
From: Steven Rostedt @ 2009-05-29 15:21 UTC (permalink / raw)
  To: wuzhangjin
  Cc: linux-mips, linux-kernel, Wu Zhangjin, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire


On Fri, 29 May 2009, wuzhangjin@gmail.com wrote:

> From: Wu Zhangjin <wuzj@lemote.com>
> 
> mips architecture need this argument to handle big/little endian
> differently.

Actually, I was thinking that you add this before adding the mips code. 
That way we don't add a broken mips code first.

So could you swap this with patch 2?

-- Steve

> 
> Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
> Signed-off-by: Wu Zhangjin <wuzj@lemote.com>

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

* Re: [PATCH v2 2/6] mips dynamic function tracer support
  2009-05-29 15:03 ` [PATCH v2 2/6] mips dynamic " wuzhangjin
@ 2009-05-29 15:24   ` Steven Rostedt
  2009-05-29 16:06     ` Wu Zhangjin
  2009-05-29 17:22     ` Wu Zhangjin
  2009-05-31  6:47   ` Wang Liming
  1 sibling, 2 replies; 17+ messages in thread
From: Steven Rostedt @ 2009-05-29 15:24 UTC (permalink / raw)
  To: wuzhangjin
  Cc: linux-mips, linux-kernel, Wu Zhangjin, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire


On Fri, 29 May 2009, wuzhangjin@gmail.com wrote:
> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> index 409596e..a5d2ace 100755
> --- a/scripts/recordmcount.pl
> +++ b/scripts/recordmcount.pl
> @@ -213,6 +213,17 @@ if ($arch eq "x86_64") {
>      if ($is_module eq "0") {
>          $cc .= " -mconstant-gp";
>      }
> +
> +} elsif ($arch eq "mips") {
> +	$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
> +	$ld .= " -melf".$bits."btsmip";
> +
> +	$cc .= " -mno-abicalls -fno-pic ";
> +
> +    if ($bits == 64) {
> +		$type = ".dword";
> +    }
> +
>  } else {
>      die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
>  }
> @@ -441,12 +452,12 @@ if ($#converts >= 0) {
>      #
>      # Step 5: set up each local function as a global
>      #
> -    `$objcopy $globallist $inputfile $globalobj`;
> +    `$objcopy $globallist $inputfile $globalobj 2>&1 >/dev/null`;
>  
>      #
>      # Step 6: Link the global version to our list.
>      #
> -    `$ld -r $globalobj $mcount_o -o $globalmix`;
> +    `$ld -r $globalobj $mcount_o -o $globalmix 2>&1 >/dev/null`;

We still need to find out why these are giving errors. I don't like the 
idea of hiding errors that might be useful. The better way is to change 
the code to avoid having any warnings or errors.

-- Steve


>  
>      #
>      # Step 7: Convert the local functions back into local symbols
> @@ -454,7 +465,7 @@ if ($#converts >= 0) {
>      `$objcopy $locallist $globalmix $inputfile`;
>  
>      # Remove the temp files
> -    `$rm $globalobj $globalmix`;
> +    `$rm $globalobj $globalmix 2>&1 >/dev/null`;
>  
>  } else {
>  
> -- 
> 1.6.0.4
> 
> 

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

* Re: [PATCH v2 2/6] mips dynamic function tracer support
  2009-05-29 15:24   ` Steven Rostedt
@ 2009-05-29 16:06     ` Wu Zhangjin
  2009-05-29 17:22     ` Wu Zhangjin
  1 sibling, 0 replies; 17+ messages in thread
From: Wu Zhangjin @ 2009-05-29 16:06 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-mips, linux-kernel, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire

On Fri, 2009-05-29 at 11:24 -0400, Steven Rostedt wrote:
> On Fri, 29 May 2009, wuzhangjin@gmail.com wrote:
> > diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> > index 409596e..a5d2ace 100755
> > --- a/scripts/recordmcount.pl
> > +++ b/scripts/recordmcount.pl
> > @@ -213,6 +213,17 @@ if ($arch eq "x86_64") {
> >      if ($is_module eq "0") {
> >          $cc .= " -mconstant-gp";
> >      }
> > +
> > +} elsif ($arch eq "mips") {
> > +	$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
> > +	$ld .= " -melf".$bits."btsmip";
> > +
> > +	$cc .= " -mno-abicalls -fno-pic ";
> > +
> > +    if ($bits == 64) {
> > +		$type = ".dword";
> > +    }
> > +
> >  } else {
> >      die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
> >  }
> > @@ -441,12 +452,12 @@ if ($#converts >= 0) {
> >      #
> >      # Step 5: set up each local function as a global
> >      #
> > -    `$objcopy $globallist $inputfile $globalobj`;
> > +    `$objcopy $globallist $inputfile $globalobj 2>&1 >/dev/null`;
> >  
> >      #
> >      # Step 6: Link the global version to our list.
> >      #
> > -    `$ld -r $globalobj $mcount_o -o $globalmix`;
> > +    `$ld -r $globalobj $mcount_o -o $globalmix 2>&1 >/dev/null`;
> 
> We still need to find out why these are giving errors. I don't like the 
> idea of hiding errors that might be useful. The better way is to change 
> the code to avoid having any warnings or errors.

get it :-)
I'm tuning it currently. 

thanks!
Wu Zhangjin
> 
> -- Steve
> 
> 
> >  
> >      #
> >      # Step 7: Convert the local functions back into local symbols
> > @@ -454,7 +465,7 @@ if ($#converts >= 0) {
> >      `$objcopy $locallist $globalmix $inputfile`;
> >  
> >      # Remove the temp files
> > -    `$rm $globalobj $globalmix`;
> > +    `$rm $globalobj $globalmix 2>&1 >/dev/null`;
> >  
> >  } else {
> >  
> > -- 
> > 1.6.0.4
> > 
> > 


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

* Re: [PATCH v2 2/6] mips dynamic function tracer support
  2009-05-29 15:24   ` Steven Rostedt
  2009-05-29 16:06     ` Wu Zhangjin
@ 2009-05-29 17:22     ` Wu Zhangjin
  2009-05-29 18:36       ` Wu Zhangjin
  1 sibling, 1 reply; 17+ messages in thread
From: Wu Zhangjin @ 2009-05-29 17:22 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-mips, linux-kernel, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire

On Fri, 2009-05-29 at 11:24 -0400, Steven Rostedt wrote:
> On Fri, 29 May 2009, wuzhangjin@gmail.com wrote:
> > diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> > index 409596e..a5d2ace 100755
> > --- a/scripts/recordmcount.pl
> > +++ b/scripts/recordmcount.pl
> > @@ -213,6 +213,17 @@ if ($arch eq "x86_64") {
> >      if ($is_module eq "0") {
> >          $cc .= " -mconstant-gp";
> >      }
> > +
> > +} elsif ($arch eq "mips") {
> > +	$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
> > +	$ld .= " -melf".$bits."btsmip";
> > +
> > +	$cc .= " -mno-abicalls -fno-pic ";
> > +
> > +    if ($bits == 64) {
> > +		$type = ".dword";
> > +    }
> > +
> >  } else {
> >      die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
> >  }
> > @@ -441,12 +452,12 @@ if ($#converts >= 0) {
> >      #
> >      # Step 5: set up each local function as a global
> >      #
> > -    `$objcopy $globallist $inputfile $globalobj`;
> > +    `$objcopy $globallist $inputfile $globalobj 2>&1 >/dev/null`;
> >  
> >      #
> >      # Step 6: Link the global version to our list.
> >      #
> > -    `$ld -r $globalobj $mcount_o -o $globalmix`;
> > +    `$ld -r $globalobj $mcount_o -o $globalmix 2>&1 >/dev/null`;
> 
> We still need to find out why these are giving errors. I don't like the 
> idea of hiding errors that might be useful. The better way is to change 
> the code to avoid having any warnings or errors.
> 

ooh, there is really a bug in scripts/recordmcount.pl, just fixed it.

warnings like this(only in mips/64bit):

 CC      fs/proc/devices.o
mipsel-linux-gnu-objcopy: 'fs/proc/.tmp_gl_devices.o': No such file
mipsel-linux-gnu-ld: fs/proc/.tmp_gl_devices.o: No such file: No such
file or directory
rm: cannot remove `fs/proc/.tmp_gl_devices.o': No such file or directory
rm: cannot remove `fs/proc/.tmp_mx_devices.o': No such file or directory

so i checked the source code and let it print something:

     #
     # Step 5: set up each local function as a global
     #
+    print "$objcopy $globallist $inputfile $globalobj\n";
     `$objcopy $globallist $inputfile $globalobj`;

something like this is printed:

mipsel-linux-gnu-objcopy  --globalize-symbol $L12
arch/mips/kernel/irq_cpu.o arch/mips/kernel/.tmp_gl_irq_cpu.o
mipsel-linux-gnu-objcopy: 'arch/mips/kernel/.tmp_gl_irq_cpu.o': No such
file
mipsel-linux-gnu-ld: arch/mips/kernel/.tmp_gl_irq_cpu.o: No such file:
No such file or directory
rm: cannot remove `arch/mips/kernel/.tmp_gl_irq_cpu.o': No such file or
directory
rm: cannot remove `arch/mips/kernel/.tmp_mx_irq_cpu.o': No such file or
directory


did you see the symbol: $L12, which should be quoted, otherwise, it will
be interpreted as the value of a variable L12(the whole $L12 should be a
string), this $L12 will be an empty string. so, the whole command
becomes:

mipsel-linux-gnu-objcopy --globalize-symbol arch/mips/kernel/irq_cpu.o
arch/mips/kernel/.tmp_gl_irq_cpu.o

the last string .../.tmp_gl_irq_cpu.o becomes the input file, but it's
not there, that is the warning.

fix it like this:

diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 59ea43a..907110e 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -451,8 +451,8 @@ if ($#converts >= 0) {
     my $locallist = "";
 
     foreach my $con (@converts) {
-       $globallist .= " --globalize-symbol $con";
-       $locallist .= " --localize-symbol $con";
+       $globallist .= " --globalize-symbol \"$con\"";
+       $locallist .= " --localize-symbol \"$con\"";
     }
 
     my $globalobj = $dirname . "/.tmp_gl_" . $filename;

I will add this as the third patch, is it okay?

Best Wishes,
--- Wu Zhangjin


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

* Re: [PATCH v2 2/6] mips dynamic function tracer support
  2009-05-29 17:22     ` Wu Zhangjin
@ 2009-05-29 18:36       ` Wu Zhangjin
  0 siblings, 0 replies; 17+ messages in thread
From: Wu Zhangjin @ 2009-05-29 18:36 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-mips, linux-kernel, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire

On Sat, 2009-05-30 at 01:44 +0800, Wu Zhangjin wrote:
> On Fri, 2009-05-29 at 11:24 -0400, Steven Rostedt wrote:
> > On Fri, 29 May 2009, wuzhangjin@gmail.com wrote:
> > > diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> > > index 409596e..a5d2ace 100755
> > > --- a/scripts/recordmcount.pl
> > > +++ b/scripts/recordmcount.pl
> > > @@ -213,6 +213,17 @@ if ($arch eq "x86_64") {
> > >      if ($is_module eq "0") {
> > >          $cc .= " -mconstant-gp";
> > >      }
> > > +
> > > +} elsif ($arch eq "mips") {
> > > +	$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
> > > +	$ld .= " -melf".$bits."btsmip";
> > > +
> > > +	$cc .= " -mno-abicalls -fno-pic ";
> > > +
> > > +    if ($bits == 64) {
> > > +		$type = ".dword";
> > > +    }
> > > +
> > >  } else {
> > >      die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
> > >  }
> > > @@ -441,12 +452,12 @@ if ($#converts >= 0) {
> > >      #
> > >      # Step 5: set up each local function as a global
> > >      #
> > > -    `$objcopy $globallist $inputfile $globalobj`;
> > > +    `$objcopy $globallist $inputfile $globalobj 2>&1 >/dev/null`;
> > >  
> > >      #
> > >      # Step 6: Link the global version to our list.
> > >      #
> > > -    `$ld -r $globalobj $mcount_o -o $globalmix`;
> > > +    `$ld -r $globalobj $mcount_o -o $globalmix 2>&1 >/dev/null`;
> > 
> > We still need to find out why these are giving errors. I don't like the 
> > idea of hiding errors that might be useful. The better way is to change 
> > the code to avoid having any warnings or errors.
> > 
> 
> ooh, there is really a bug in scripts/recordmcount.pl, just fixed it.
> 
> warnings like this(only in mips/64bit):
> 
>  CC      fs/proc/devices.o
> mipsel-linux-gnu-objcopy: 'fs/proc/.tmp_gl_devices.o': No such file
> mipsel-linux-gnu-ld: fs/proc/.tmp_gl_devices.o: No such file: No such
> file or directory
> rm: cannot remove `fs/proc/.tmp_gl_devices.o': No such file or directory
> rm: cannot remove `fs/proc/.tmp_mx_devices.o': No such file or directory
> 
> so i checked the source code and let it print something:
> 
>      #
>      # Step 5: set up each local function as a global
>      #
> +    print "$objcopy $globallist $inputfile $globalobj\n";
>      `$objcopy $globallist $inputfile $globalobj`;
> 
> something like this is printed:
> 
> mipsel-linux-gnu-objcopy  --globalize-symbol $L12
> arch/mips/kernel/irq_cpu.o arch/mips/kernel/.tmp_gl_irq_cpu.o
> mipsel-linux-gnu-objcopy: 'arch/mips/kernel/.tmp_gl_irq_cpu.o': No such
> file
> mipsel-linux-gnu-ld: arch/mips/kernel/.tmp_gl_irq_cpu.o: No such file:
> No such file or directory
> rm: cannot remove `arch/mips/kernel/.tmp_gl_irq_cpu.o': No such file or
> directory
> rm: cannot remove `arch/mips/kernel/.tmp_mx_irq_cpu.o': No such file or
> directory
> 
> 
> did you see the symbol: $L12, which should be quoted, otherwise, it will
> be interpreted as the value of a variable L12(the whole $L12 should be a
> string), this $L12 will be an empty string. so, the whole command
> becomes:
> 
> mipsel-linux-gnu-objcopy --globalize-symbol arch/mips/kernel/irq_cpu.o
> arch/mips/kernel/.tmp_gl_irq_cpu.o
> 
> the last string .../.tmp_gl_irq_cpu.o becomes the input file, but it's
> not there, that is the warning.
> 
> fix it like this:
> 
> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> index 59ea43a..907110e 100755
> --- a/scripts/recordmcount.pl
> +++ b/scripts/recordmcount.pl
> @@ -451,8 +451,8 @@ if ($#converts >= 0) {
>      my $locallist = "";
>  
>      foreach my $con (@converts) {
> -       $globallist .= " --globalize-symbol $con";
> -       $locallist .= " --localize-symbol $con";
> +       $globallist .= " --globalize-symbol \"$con\"";
> +       $locallist .= " --localize-symbol \"$con\"";
>      }
>  
>      my $globalobj = $dirname . "/.tmp_gl_" . $filename;
> 
> I will add this as the third patch, is it okay?
> 

sorry, this fix not work, can not link the kernel:

arch/mips/kernel/built-in.o:(__mcount_loc+0x3a0): undefined reference to
`$L12'
arch/mips/kernel/built-in.o:(__mcount_loc+0x3a8): undefined reference to
`$L12'

I think we should ignore these symbols, should we?

> Best Wishes,
> --- Wu Zhangjin


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

* Re: [PATCH v2 2/6] mips dynamic function tracer support
  2009-05-29 15:03 ` [PATCH v2 2/6] mips dynamic " wuzhangjin
  2009-05-29 15:24   ` Steven Rostedt
@ 2009-05-31  6:47   ` Wang Liming
  2009-06-02 16:15     ` wu zhangjin
  1 sibling, 1 reply; 17+ messages in thread
From: Wang Liming @ 2009-05-31  6:47 UTC (permalink / raw)
  To: wuzhangjin
  Cc: linux-mips, linux-kernel, Wu Zhangjin, Steven Rostedt,
	Ralf Baechle, Ingo Molnar, Andrew Morton, Frederic Weisbecker,
	Thomas Gleixner, Nicholas Mc Guire

hi Wu,

I have one question about dynamic ftrace support for modules on mips arch.
I have also ported a dynamic ftrace of mips before, but when I using modules 
with dynamic ftrace enabled in mips, I have following error:

# insmod ./usbcore
module usbcore: relocation overflow
insmod: cannot insert './usbcore.ko': invalid module format
#

I have no time to test your patch, but I think your patch also has this problem.

Below I explain possibility of this problem in details:

We know that on mips, kernel symbol will locate in 0x80000000~0x90000000, and 
modules' symbol will locate in >0xc0000000.

On mips, gcc will insert following assembler code before every functions:

     move    at,ra
     jal     0 <usb_ifnum_to_if>
     10: R_MIPS_26   _mcount


Here "_mcount" is a kernel symbol in 0x80000000~0x90000000, for
example at 0x8027a740.

When loading a module, kernel should relocate "jal 0" instruction to jump to the 
kernel's "_mcount" address, 0x8027a740. But "jal 0" is a 26 bits offset jump
instruction, it only can be relocated to jump to modules' symbol address
space(>0xc0000000) and it can't be relocated to jump to kernel symbol address
space(such as 0x8027a740), because offset is 32 bits(is 0xc0000000 -
0x80000000). We can't modify this instruction to jump to a 32 offset address
except that we modify gcc compiler to insert other assembler codes.

So, when installing modules, the kernel will try to relocate "jal 0" instruction
  to instruction of jumping to >0xc0000000, but it finds that _mcount's address
is 0x8027a740 and then print error indicated that it can't be reloacted.

The following source code is the checking place:


----------arch/mips/kernel/module.c:apply_r_mips_26_rel()-------------------

static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
{
     ...
     if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
                 printk(KERN_ERR
                        "module %s: relocation overflow, v:%x, location:%x\n",
                        me->name, v, (unsigned long)location);
                 return -ENOEXEC;
         }

     *location = (*location & ~0x03ffffff) |
                     ((*location + (v >> 2)) & 0x03ffffff);

}
----------arch/mips/kernel/module.c:apply_r_mips_26_rel()-------------------

v is kernel _mcount's address, location is the address of the instrution that 
should be relocated;

To resolve this problem, we may need to do more work, either on gcc or on the 
kernel. So I want to hear your test result and if you have solution, please let 
me know.

Thanks a lot!

Liming Wang

wuzhangjin@gmail.com wrote:
> From: Wu Zhangjin <wuzj@lemote.com>
> 
> dynamic function tracer need to replace "nop" to "jumps & links" and
> something reversely.
> 
> Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
> Signed-off-by: Wu Zhangjin <wuzj@lemote.com>
> ---
>  arch/mips/Kconfig              |    3 +
>  arch/mips/include/asm/ftrace.h |   10 ++
>  arch/mips/kernel/Makefile      |    2 +
>  arch/mips/kernel/ftrace.c      |  207 ++++++++++++++++++++++++++++++++++++++++
>  arch/mips/kernel/mcount.S      |   31 ++++++
>  scripts/recordmcount.pl        |   17 +++-
>  6 files changed, 267 insertions(+), 3 deletions(-)
>  create mode 100644 arch/mips/kernel/ftrace.c
> 
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index d5c01ca..0c00536 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -6,6 +6,9 @@ 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
> +	select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
>  	# Horrible source of confusion.  Die, die, die ...
>  	select EMBEDDED
>  	select RTC_LIB
> diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h
> index 5f8ebcf..b4970c9 100644
> --- a/arch/mips/include/asm/ftrace.h
> +++ b/arch/mips/include/asm/ftrace.h
> @@ -19,6 +19,16 @@
>  extern void _mcount(void);
>  #define mcount _mcount
>  
> +#ifdef CONFIG_DYNAMIC_FTRACE
> +/* reloction of mcount call site is the same as the address */
> +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 559a820..8dabcc6 100644
> --- a/arch/mips/kernel/Makefile
> +++ b/arch/mips/kernel/Makefile
> @@ -10,6 +10,7 @@ obj-y		+= cpu-probe.o branch.o entry.o genex.o irq.o process.o \
>  
>  ifdef CONFIG_FUNCTION_TRACER
>  # Do not profile debug and lowlevel utilities
> +CFLAGS_REMOVE_ftrace.o = -pg
>  CFLAGS_REMOVE_early_printk.o = -pg
>  endif
>  
> @@ -30,6 +31,7 @@ obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
>  obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
>  
>  obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o
> +obj-$(CONFIG_FUNCTION_TRACER)	+= 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..ad490cc
> --- /dev/null
> +++ b/arch/mips/kernel/ftrace.c
> @@ -0,0 +1,207 @@
> +/*
> + * 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/spinlock.h>
> +#include <linux/hardirq.h>
> +#include <linux/uaccess.h>
> +#include <linux/percpu.h>
> +#include <linux/sched.h>
> +#include <linux/init.h>
> +#include <linux/list.h>
> +#include <linux/ftrace.h>
> +
> +#include <asm/cacheflush.h>
> +#include <asm/ftrace.h>
> +#include <asm/asm.h>
> +#include <asm/unistd.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 */
> +
> +static unsigned int ftrace_nop = 0x00000000;
> +
> +static unsigned char *ftrace_call_replace(unsigned long op_code,
> +					  unsigned long addr)
> +{
> +    static unsigned int op;
> +
> +    op = op_code | ((addr >> 2) & ADDR_MASK);
> +
> +    return (unsigned char *) &op;
> +}
> +
> +static atomic_t nmi_running = ATOMIC_INIT(0);
> +static int mod_code_status;	/* holds return value of text write */
> +static int mod_code_write;	/* set when NMI should do the write */
> +static void *mod_code_ip;	/* holds the IP to write to */
> +static void *mod_code_newcode;	/* holds the text to write to the IP */
> +
> +static unsigned nmi_wait_count;
> +static atomic_t nmi_update_count = ATOMIC_INIT(0);
> +
> +int ftrace_arch_read_dyn_info(char *buf, int size)
> +{
> +    int r;
> +
> +    r = snprintf(buf, size, "%u %u",
> +		 nmi_wait_count, atomic_read(&nmi_update_count));
> +    return r;
> +}
> +
> +static void ftrace_mod_code(void)
> +{
> +    /*
> +     * Yes, more than one CPU process can be writing to mod_code_status.
> +     *    (and the code itself)
> +     * But if one were to fail, then they all should, and if one were
> +     * to succeed, then they all should.
> +     */
> +    mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode,
> +					 MCOUNT_INSN_SIZE);
> +
> +    /* if we fail, then kill any new writers */
> +    if (mod_code_status)
> +		mod_code_write = 0;
> +}
> +
> +void ftrace_nmi_enter(void)
> +{
> +    atomic_inc(&nmi_running);
> +    /* Must have nmi_running seen before reading write flag */
> +    smp_mb();
> +    if (mod_code_write) {
> +		ftrace_mod_code();
> +		atomic_inc(&nmi_update_count);
> +    }
> +}
> +
> +void ftrace_nmi_exit(void)
> +{
> +    /* Finish all executions before clearing nmi_running */
> +    smp_wmb();
> +    atomic_dec(&nmi_running);
> +}
> +
> +static void wait_for_nmi(void)
> +{
> +    int waited = 0;
> +
> +    while (atomic_read(&nmi_running)) {
> +		waited = 1;
> +		cpu_relax();
> +    }
> +
> +    if (waited)
> +		nmi_wait_count++;
> +}
> +
> +static int do_ftrace_mod_code(unsigned long ip, void *new_code)
> +{
> +    mod_code_ip = (void *) ip;
> +    mod_code_newcode = new_code;
> +
> +    /* The buffers need to be visible before we let NMIs write them */
> +    smp_wmb();
> +
> +    mod_code_write = 1;
> +
> +    /* Make sure write bit is visible before we wait on NMIs */
> +    smp_mb();
> +
> +    wait_for_nmi();
> +
> +    /* Make sure all running NMIs have finished before we write the code */
> +    smp_mb();
> +
> +    ftrace_mod_code();
> +
> +    /* Make sure the write happens before clearing the bit */
> +    smp_wmb();
> +
> +    mod_code_write = 0;
> +
> +    /* make sure NMIs see the cleared bit */
> +    smp_mb();
> +
> +    wait_for_nmi();
> +
> +    return mod_code_status;
> +}
> +
> +static unsigned char *ftrace_nop_replace(void)
> +{
> +    return (unsigned char *) &ftrace_nop;
> +}
> +
> +static int
> +ftrace_modify_code(unsigned long ip, unsigned char *old_code,
> +		   unsigned char *new_code)
> +{
> +    unsigned char replaced[MCOUNT_INSN_SIZE];
> +
> +    /* read the text we want to modify */
> +    if (probe_kernel_read(replaced, (void *) ip, MCOUNT_INSN_SIZE))
> +		return -EFAULT;
> +
> +    /* Make sure it is what we expect it to be */
> +    if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0)
> +		return -EINVAL;
> +
> +    /* replace the text with the new text */
> +    if (do_ftrace_mod_code(ip, new_code))
> +		return -EPERM;
> +
> +    return 0;
> +}
> +
> +int ftrace_make_nop(struct module *mod,
> +		    struct dyn_ftrace *rec, unsigned long addr)
> +{
> +    unsigned char *new, *old;
> +
> +    old = ftrace_call_replace(JAL, addr);
> +    new = ftrace_nop_replace();
> +
> +    return ftrace_modify_code(rec->ip, old, new);
> +}
> +
> +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> +{
> +    unsigned char *new, *old;
> +
> +    old = ftrace_nop_replace();
> +    new = ftrace_call_replace(JAL, addr);
> +
> +    return ftrace_modify_code(rec->ip, old, new);
> +}
> +
> +int ftrace_update_ftrace_func(ftrace_func_t func)
> +{
> +    unsigned long ip = (unsigned long) (&ftrace_call);
> +    unsigned char old[MCOUNT_INSN_SIZE], *new;
> +    int ret;
> +
> +    memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
> +    new = ftrace_call_replace(JAL, (unsigned long) func);
> +    ret = ftrace_modify_code(ip, old, new);
> +
> +    return ret;
> +}
> +
> +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 268724e..ce8a0ba 100644
> --- a/arch/mips/kernel/mcount.S
> +++ b/arch/mips/kernel/mcount.S
> @@ -67,6 +67,35 @@
>  	move ra, $1
>  	.endm
>  
> +#ifdef CONFIG_DYNAMIC_FTRACE
> +
> +LEAF(_mcount)
> +	RESTORE_SP_FOR_32BIT
> + 	RETURN_BACK
> + 	END(_mcount)
> +
> +NESTED(ftrace_caller, PT_SIZE, ra)
> +	RESTORE_SP_FOR_32BIT
> +	lw	t0, function_trace_stop
> +	bnez	t0, ftrace_stub
> +	nop
> +
> +	MCOUNT_SAVE_REGS
> +
> +	MCOUNT_SET_ARGS
> +	.globl ftrace_call
> +ftrace_call:
> +	jal	ftrace_stub
> +	nop
> +
> +	MCOUNT_RESTORE_REGS
> +	.globl ftrace_stub
> +ftrace_stub:
> +	RETURN_BACK
> +	END(ftrace_caller)
> +
> +#else	/* ! CONFIG_DYNAMIC_FTRACE */
> +
>  NESTED(_mcount, PT_SIZE, ra)
>  	RESTORE_SP_FOR_32BIT
>  	PTR_L	t0, function_trace_stop
> @@ -94,5 +123,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 409596e..a5d2ace 100755
> --- a/scripts/recordmcount.pl
> +++ b/scripts/recordmcount.pl
> @@ -213,6 +213,17 @@ if ($arch eq "x86_64") {
>      if ($is_module eq "0") {
>          $cc .= " -mconstant-gp";
>      }
> +
> +} elsif ($arch eq "mips") {
> +	$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
> +	$ld .= " -melf".$bits."btsmip";
> +
> +	$cc .= " -mno-abicalls -fno-pic ";
> +
> +    if ($bits == 64) {
> +		$type = ".dword";
> +    }
> +
>  } else {
>      die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
>  }
> @@ -441,12 +452,12 @@ if ($#converts >= 0) {
>      #
>      # Step 5: set up each local function as a global
>      #
> -    `$objcopy $globallist $inputfile $globalobj`;
> +    `$objcopy $globallist $inputfile $globalobj 2>&1 >/dev/null`;
>  
>      #
>      # Step 6: Link the global version to our list.
>      #
> -    `$ld -r $globalobj $mcount_o -o $globalmix`;
> +    `$ld -r $globalobj $mcount_o -o $globalmix 2>&1 >/dev/null`;
>  
>      #
>      # Step 7: Convert the local functions back into local symbols
> @@ -454,7 +465,7 @@ if ($#converts >= 0) {
>      `$objcopy $locallist $globalmix $inputfile`;
>  
>      # Remove the temp files
> -    `$rm $globalobj $globalmix`;
> +    `$rm $globalobj $globalmix 2>&1 >/dev/null`;
>  
>  } else {
>  


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

* Re: [PATCH v2 2/6] mips dynamic function tracer support
  2009-05-31  6:47   ` Wang Liming
@ 2009-06-02 16:15     ` wu zhangjin
  2009-06-03  6:05       ` Wang Liming
  0 siblings, 1 reply; 17+ messages in thread
From: wu zhangjin @ 2009-06-02 16:15 UTC (permalink / raw)
  To: Wang Liming
  Cc: linux-mips, linux-kernel, Wu Zhangjin, Steven Rostedt,
	Ralf Baechle, Ingo Molnar, Andrew Morton, Frederic Weisbecker,
	Thomas Gleixner, Nicholas Mc Guire

hi,

sorry, I'm so late to reply your E-mail, a little busy these days.

On Sun, May 31, 2009 at 2:47 PM, Wang Liming <liming.wang@windriver.com> wrote:
> hi Wu,
>
> I have one question about dynamic ftrace support for modules on mips arch.
> I have also ported a dynamic ftrace of mips before, but when I using modules
> with dynamic ftrace enabled in mips, I have following error:
>
> # insmod ./usbcore
> module usbcore: relocation overflow
> insmod: cannot insert './usbcore.ko': invalid module format
> #
>
> I have no time to test your patch, but I think your patch also has this
> problem.
>
> Below I explain possibility of this problem in details:
>
> We know that on mips, kernel symbol will locate in 0x80000000~0x90000000,
> and modules' symbol will locate in >0xc0000000.
>
> On mips, gcc will insert following assembler code before every functions:
>
>    move    at,ra
>    jal     0 <usb_ifnum_to_if>
>    10: R_MIPS_26   _mcount
>
>
> Here "_mcount" is a kernel symbol in 0x80000000~0x90000000, for
> example at 0x8027a740.
>
> When loading a module, kernel should relocate "jal 0" instruction to jump to
> the kernel's "_mcount" address, 0x8027a740. But "jal 0" is a 26 bits offset
> jump
> instruction, it only can be relocated to jump to modules' symbol address
> space(>0xc0000000) and it can't be relocated to jump to kernel symbol
> address
> space(such as 0x8027a740), because offset is 32 bits(is 0xc0000000 -
> 0x80000000). We can't modify this instruction to jump to a 32 offset address
> except that we modify gcc compiler to insert other assembler codes.
>
> So, when installing modules, the kernel will try to relocate "jal 0"
> instruction
>  to instruction of jumping to >0xc0000000, but it finds that _mcount's
> address
> is 0x8027a740 and then print error indicated that it can't be reloacted.
>
> The following source code is the checking place:
>
>
> ----------arch/mips/kernel/module.c:apply_r_mips_26_rel()-------------------
>
> static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
> {
>    ...
>    if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
>                printk(KERN_ERR
>                       "module %s: relocation overflow, v:%x, location:%x\n",
>                       me->name, v, (unsigned long)location);
>                return -ENOEXEC;
>        }
>
>    *location = (*location & ~0x03ffffff) |
>                    ((*location + (v >> 2)) & 0x03ffffff);
>
> }
> ----------arch/mips/kernel/module.c:apply_r_mips_26_rel()-------------------
>
> v is kernel _mcount's address, location is the address of the instrution
> that should be relocated;
>
> To resolve this problem, we may need to do more work, either on gcc or on
> the kernel. So I want to hear your test result and if you have solution,
> please let me know.
>

yes, current version of mips-specific dynamic ftrace not support modules yet.

there is similar solution implemented in PowerPC(something named trampoline),
although I did not look into it, but I'm sure we can implement the
mips-specific one
via imitating it.

and currently, I'm planning to fix it in the -v3 of mips-specific
ftrace support.

best wishes,
Wu Zhangjin

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

* Re: [PATCH v2 2/6] mips dynamic function tracer support
  2009-06-02 16:15     ` wu zhangjin
@ 2009-06-03  6:05       ` Wang Liming
  2009-06-03 12:47         ` Steven Rostedt
  0 siblings, 1 reply; 17+ messages in thread
From: Wang Liming @ 2009-06-03  6:05 UTC (permalink / raw)
  To: wu zhangjin
  Cc: linux-mips, linux-kernel, Wu Zhangjin, Steven Rostedt,
	Ralf Baechle, Ingo Molnar, Andrew Morton, Frederic Weisbecker,
	Thomas Gleixner, Nicholas Mc Guire

wu zhangjin wrote:
> hi,
> 
> sorry, I'm so late to reply your E-mail, a little busy these days.
>>
>> }
>> ----------arch/mips/kernel/module.c:apply_r_mips_26_rel()-------------------
>>
>> v is kernel _mcount's address, location is the address of the instrution
>> that should be relocated;
>>
>> To resolve this problem, we may need to do more work, either on gcc or on
>> the kernel. So I want to hear your test result and if you have solution,
>> please let me know.
>>
> 
> yes, current version of mips-specific dynamic ftrace not support modules yet.
> 
> there is similar solution implemented in PowerPC(something named trampoline),
> although I did not look into it, but I'm sure we can implement the
> mips-specific one
> via imitating it.
Good hit. I may have a look on Powerpc implementation.

> 
> and currently, I'm planning to fix it in the -v3 of mips-specific
> ftrace support.
OK. I'm looking forward to your -v3 patches.

Thanks.
Liming Wang
> 
> best wishes,
> Wu Zhangjin
> 


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

* Re: [PATCH v2 2/6] mips dynamic function tracer support
  2009-06-03  6:05       ` Wang Liming
@ 2009-06-03 12:47         ` Steven Rostedt
  2009-06-04 11:20           ` Wu Zhangjin
  0 siblings, 1 reply; 17+ messages in thread
From: Steven Rostedt @ 2009-06-03 12:47 UTC (permalink / raw)
  To: Wang Liming
  Cc: wu zhangjin, linux-mips, linux-kernel, Wu Zhangjin, Ralf Baechle,
	Ingo Molnar, Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire


On Wed, 3 Jun 2009, Wang Liming wrote:

> wu zhangjin wrote:
> > hi,
> > 
> > sorry, I'm so late to reply your E-mail, a little busy these days.
> > > 
> > > }
> > > 
> > > ----------arch/mips/kernel/module.c:apply_r_mips_26_rel()-------------------
> > > 
> > > v is kernel _mcount's address, location is the address of the instrution
> > > that should be relocated;
> > > 
> > > To resolve this problem, we may need to do more work, either on gcc or on
> > > the kernel. So I want to hear your test result and if you have solution,
> > > please let me know.
> > > 
> > 
> > yes, current version of mips-specific dynamic ftrace not support modules
> > yet.
> > 
> > there is similar solution implemented in PowerPC(something named
> > trampoline),
> > although I did not look into it, but I'm sure we can implement the
> > mips-specific one
> > via imitating it.
> Good hit. I may have a look on Powerpc implementation.

Note, PowerPC uses a trampoline from modules to kernel core. I think MIPS 
just calls mcount differently. That is, it does a full 32bit address call
(64 bit for 64 bit archs?). Something like:

	lui	v1, _mcount
	addiu	v1, v1, _mcount
	jalr	v1
	addiu	sp, sp, -8

Then a nop would not do. Due to preemption, we can not modify more than 
one line. But you could modify it to:

	b	1f
	addiu	v1, v1, _mcount
	jalr	v1
	addiu	sp, sp, -8
1:

Clobbering v1 should not be an issue since it is already used to store 
_mcount. That is, we still do the addiu v1,v1,_mcount with that branch. 
But v1 should be ignored.

-- Steve


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

* Re: [PATCH v2 2/6] mips dynamic function tracer support
  2009-06-03 12:47         ` Steven Rostedt
@ 2009-06-04 11:20           ` Wu Zhangjin
  0 siblings, 0 replies; 17+ messages in thread
From: Wu Zhangjin @ 2009-06-04 11:20 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Wang Liming, linux-mips, linux-kernel, Ralf Baechle, Ingo Molnar,
	Andrew Morton, Frederic Weisbecker, Thomas Gleixner,
	Nicholas Mc Guire

hi, Steven

> Note, PowerPC uses a trampoline from modules to kernel core. I think MIPS 
> just calls mcount differently. That is, it does a full 32bit address call
> (64 bit for 64 bit archs?). Something like:
> 
> 	lui	v1, _mcount
> 	addiu	v1, v1, _mcount
> 	jalr	v1
> 	addiu	sp, sp, -8
> 
> Then a nop would not do. Due to preemption, we can not modify more than 
> one line. But you could modify it to:
> 
> 	b	1f
> 	addiu	v1, v1, _mcount
> 	jalr	v1
> 	addiu	sp, sp, -8
> 1:
> 
> Clobbering v1 should not be an issue since it is already used to store 
> _mcount. That is, we still do the addiu v1,v1,_mcount with that branch. 
> But v1 should be ignored.
> 

sorry, I'm not clear what you said above, could you give more
explanation on it, thanks! 

I think "jal _mcount" itself will not work in static and dynamic ftrace.
something like what you described above should be used instead. perhaps
a PATCH can be sent to gcc or we use some tricks in kernel.

if we not use the method of modifying the kernel code in run time(avoid
preemption?), can we link something as following to the modules:

_mcount_trampoline:
	PTR_LA	t0, _mcount
	jalr	t0

and then we replace the original "jal _mcount" in every module to "jal
_mcount_trampoline" with a perl script.

this solution maybe work for static ftrace. does it?

but in dynamic ftrace, when ftrace is enabled and set_filter_function is
set, the place of filtered function will be substituted to "jal
ftrace_caller", this will not work since ftrace_caller is a function
like _mcount, which will not reached in modules. so, this ftrace_caller
should be substituted to something like this:

ftrace_caller_trampoline:
	PTR_LA	t0, ftrace_caller
	jalr	t0

and ftrace_caller_trampoline should be linked to modules too. or we
substituted it to the above _mcount_trampoline, but change "PTR_LA t0,
_mcount" to "PTR_LA t0, ftrace_caller".

does this work?

thanks!
Wu Zhangjin


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

end of thread, other threads:[~2009-06-04 11:22 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-29 14:58 [PATCH v2 0/6] mips-specific ftrace support wuzhangjin
2009-05-29 15:02 ` [PATCH v2 1/6] mips static function tracer support wuzhangjin
2009-05-29 15:03 ` [PATCH v2 2/6] mips dynamic " wuzhangjin
2009-05-29 15:24   ` Steven Rostedt
2009-05-29 16:06     ` Wu Zhangjin
2009-05-29 17:22     ` Wu Zhangjin
2009-05-29 18:36       ` Wu Zhangjin
2009-05-31  6:47   ` Wang Liming
2009-06-02 16:15     ` wu zhangjin
2009-06-03  6:05       ` Wang Liming
2009-06-03 12:47         ` Steven Rostedt
2009-06-04 11:20           ` Wu Zhangjin
2009-05-29 15:04 ` [PATCH v2 3/6] add an endian argument to scripts/recordmcount.pl wuzhangjin
2009-05-29 15:21   ` Steven Rostedt
2009-05-29 15:05 ` [PATCH v2 4/6] mips function graph tracer support wuzhangjin
2009-05-29 15:05 ` [PATCH v2 5/6] mips specific clock function to get precise timestamp wuzhangjin
2009-05-29 15:06 ` [PATCH v2 6/6] mips specific system call tracer wuzhangjin

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.