Skip to contentSkip to conversation

mips-specific ftrace support

PATCH Superseded Wu Zhangjin 3 participants 11 messages Jun 14, 2009 – Jun 15, 2009

Subsystems (5)
Kbuild MIPS Tracing ptrace support +1 more subsystems
lore
Share & tools
lore
#0 lore raw

PATCH v3 1/1 mips-specific ftrace support

From: Wu Zhangjin <[email protected]>

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 -v3 patch series is based on the -v2 patch series and incorporates the feedback from Steven Rostedt and Thomas Gleixner.

!!NOTE!!

this -v3 not support modules yet, really hope this can be fixed in -v4 patch.

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

Wu Zhangjin (7):
mips static function tracer support
add an endian argument to scripts/recordmcount.pl mips dynamic function tracer support
filter local function prefixed by $L
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           |  344 +++++++++++++++++++++++++++++++++++
 arch/mips/kernel/ftrace_clock.c     |   71 +++++++
 arch/mips/kernel/mcount.S           |  184 +++++++++++++++++++
 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             |   30 +++-
 20 files changed, 799 insertions(+), 11 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
#1 lore raw

PATCH v3 1/1 mips static function tracer support

From: Wu Zhangjin <[email protected]>

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.

---
 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
arch/mips/Kconfig +2 -0
index 25f3b0a..2e2fdbe 100644
@@ -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
arch/mips/Makefile +2 -0
index c4cae9e..f86fb15 100644
@@ -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
arch/mips/include/asm/ftrace.h +24 -1
index 40a8c17..5f8ebcf 100644
@@ -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 <[email protected]>
+ */
+
+#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 */
arch/mips/kernel/Makefile +7 -0
index e961221..559a820 100644
@@ -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
arch/mips/kernel/mcount.S new file +98 -0

98 lines not on this page · raw message

arch/mips/kernel/mips_ksyms.c +5 -0
index 225755d..1d04807 100644
@@ -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
Signature · 1 line
1.6.0.4
#2 lore raw

PATCH v3 1/1 add an endian argument to scripts/recordmcount.pl

In reply to Wu Zhangjin

From: Wu Zhangjin <[email protected]>

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

---
 scripts/Makefile.build  |    1 +
 scripts/recordmcount.pl |    6 +++---
 2 files changed, 4 insertions(+), 3 deletions(-)
scripts/Makefile.build +1 -0
index 5c4b7a4..548d575 100644
@@ -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)" "$(@)";
scripts/recordmcount.pl +3 -3
index 0fae7da..f1e3e9c 100755
@@ -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
Signature · 1 line
1.6.0.4
#3 lore raw

PATCH v3 1/1 mips dynamic function tracer support

In reply to Wu Zhangjin

From: Wu Zhangjin <[email protected]>

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

---
 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        |   20 ++++
 6 files changed, 273 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/kernel/ftrace.c
arch/mips/Kconfig +3 -0
index 2e2fdbe..0857239 100644
@@ -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
arch/mips/include/asm/ftrace.h +10 -0
index 5f8ebcf..b4970c9 100644
@@ -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 */
arch/mips/kernel/Makefile +2 -0
index 559a820..8dabcc6 100644
@@ -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
arch/mips/kernel/ftrace.c new file +207 -0

207 lines not on this page · raw message

arch/mips/kernel/mcount.S +31 -0
index 268724e..723ace2 100644
@@ -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
scripts/recordmcount.pl +20 -0
index f1e3e9c..533d3bf 100755
@@ -213,6 +213,26 @@ 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\$";
+	$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) {
+		$type = ".dword";
+    }
+
 } else {
     die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
 }
Signature · 1 line
1.6.0.4
#4 lore raw

PATCH v3 1/1 filter local function prefixed by $L

In reply to Wu Zhangjin

From: Wu Zhangjin <[email protected]>

this patch fixed the warning as following:

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

the real reason of above warning is that the $Lxx local functions will be treated as global symbols, so, should be filtered.

---
 scripts/recordmcount.pl |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
scripts/recordmcount.pl +4 -0
index 533d3bf..542cb04 100755
@@ -343,6 +343,10 @@ sub update_funcs
 	if (!$use_locals) {
 	    return;
 	}
+	# filter $LXXX tags
+	if ("$ref_func" =~ m/\$L/) {
+		return;
+	}
 	$convert{$ref_func} = 1;
     }
 
Signature · 1 line
1.6.0.4
#5 lore raw

Re: [PATCH v3] filter local function prefixed by $L

Quoted 23 lines · Wu Zhangjin

From: Wu Zhangjin <[email protected]>

this patch fixed the warning as following:

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

the real reason of above warning is that the $Lxx local functions will be treated as global symbols, so, should be filtered.

---
 scripts/recordmcount.pl |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
scripts/recordmcount.pl +0 -0
index 533d3bf..542cb04 100755

scripts/recordmcount.pl sub update_funcs · line 349

Quoted 7 lines
scripts/recordmcount.pl +4 -0
@@ -343,6 +343,10 @@ sub update_funcs
 	if (!$use_locals) {
 	    return;
 	}
+	# filter $LXXX tags
+	if ("$ref_func" =~ m/\$L/) {
+		return;
+	}

Certainly this is true for mips. I doubt it is for all architectures targed by Linux.

David Daney

maintainer
#6 lore raw

Re: [PATCH v3] filter local function prefixed by $L

Quoted 19 lines · David Daney
Quoted 18 lines · Wu Zhangjin

From: Wu Zhangjin <[email protected]>

this patch fixed the warning as following:

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

the real reason of above warning is that the $Lxx local functions will be treated as global symbols, so, should be filtered.

---
 scripts/recordmcount.pl |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
Quoted 15 lines

scripts/recordmcount.pl sub update_funcs · line 349

Quoted 12 lines
scripts/recordmcount.pl +4 -0
index 533d3bf..542cb04 100755
@@ -343,6 +343,10 @@ sub update_funcs
 	if (!$use_locals) {
 	    return;
 	}
+	# filter $LXXX tags
+	if ("$ref_func" =~ m/\$L/) {
+		return;
+	}

Certainly this is true for mips. I doubt it is for all architectures targed by Linux.

Yes, that should probably go into a mips only change. Unless you can reproduce it on all other archs, or at least x86.

You could also do this in the function_regex variable.

"^([0-9a-fA-F]+)\\s+<(.|[^\$]L.*?|\$[^L].*?|[^\$][^L].*?)>:"

There may even be a better way, but I'm not in the mood to look it up ;-)

-- Steve

#7 lore raw

Re: [PATCH v3] filter local function prefixed by $L

Quoted 21 lines · Steven Rostedt
Quoted 19 lines · David Daney
Quoted 18 lines · Wu Zhangjin

From: Wu Zhangjin <[email protected]>

this patch fixed the warning as following:

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

the real reason of above warning is that the $Lxx local functions will be treated as global symbols, so, should be filtered.

---
 scripts/recordmcount.pl |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
Quoted 16 lines
Quoted 7 lines
Quoted 7 lines
scripts/recordmcount.pl +0 -0
index 533d3bf..542cb04 100755
@@ -343,6 +343,10 @@ sub update_funcs
 	if (!$use_locals) {
 	    return;
Quoted 8 lines

scripts/recordmcount.pl sub update_funcs · line 349

Quoted 5 lines
scripts/recordmcount.pl +4 -0
 	}
+	# filter $LXXX tags
+	if ("$ref_func" =~ m/\$L/) {
+		return;
+	}

Certainly this is true for mips. I doubt it is for all architectures targed by Linux.

have tried to use function_regex instead, but for I'm poor in playing with regular expression of perl. at last, i use something easier like above. and I _guess_ this problem maybe exist in some other platforms, so just put it there.

Quoted 7 lines

Yes, that should probably go into a mips only change. Unless you can reproduce it on all other archs, or at least x86.

You could also do this in the function_regex variable.

"^([0-9a-fA-F]+)\\s+<(.|[^\$]L.*?|\$[^L].*?|[^\$][^L].*?)>:"

works well, and this seems mips64-specific, so, I moved this specific function_regex to "if ($bits == 64) { ... }".

Quoted 1 line

There may even be a better way, but I'm not in the mood to look it up ;-)

seems not that easy to understand :-)

-- Wu Zhangjin

#8 lore raw

PATCH v3 1/1 mips function graph tracer support

In reply to Wu Zhangjin

From: Wu Zhangjin <[email protected]>

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 &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.

---
 arch/mips/Kconfig              |    1 +
 arch/mips/kernel/ftrace.c      |   66 ++++++++++++++++++++++++++++++++++++++++
 arch/mips/kernel/mcount.S      |   61 +++++++++++++++++++++++++++++++++++--
 arch/mips/kernel/vmlinux.lds.S |    1 +
 4 files changed, 126 insertions(+), 3 deletions(-)
arch/mips/Kconfig +1 -0
index 0857239..5ac9f45 100644
@@ -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
arch/mips/kernel/ftrace.c +66 -0

69 lines not on this page · raw message

arch/mips/kernel/mcount.S +58 -3

107 lines not on this page · raw message

arch/mips/kernel/vmlinux.lds.S +1 -0
index 58738c8..67435e5 100644
@@ -36,6 +36,7 @@ SECTIONS
 		SCHED_TEXT
 		LOCK_TEXT
 		KPROBES_TEXT
+		IRQENTRY_TEXT
 		*(.text.*)
 		*(.fixup)
 		*(.gnu.warning)
Signature · 1 line
1.6.0.4
#9 lore raw

PATCH v3 1/1 mips specific clock function to get precise timestamp

In reply to Wu Zhangjin

From: Wu Zhangjin <[email protected]>

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.

---
 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
arch/mips/kernel/Makefile +2 -0
index 8dabcc6..44ec7e0 100644
@@ -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
arch/mips/kernel/csrc-r4k.c +1 -1
index e95a3cd..3da1c7a 100644
@@ -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();
 }
arch/mips/kernel/ftrace_clock.c new file +71 -0

71 lines not on this page · raw message

kernel/trace/trace_clock.c +1 -1
index b588fd8..78c98c8 100644
@@ -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;
Signature · 1 line
1.6.0.4
#10 lore raw

PATCH v3 1/1 mips specific system call tracer

In reply to Wu Zhangjin

From: Wu Zhangjin <[email protected]>

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)
---
 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
arch/mips/Kconfig +1 -0
index 5ac9f45..a4a5af5 100644
@@ -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
arch/mips/include/asm/ptrace.h +2 -0
index ce47118..32e5b62 100644
@@ -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 */
arch/mips/include/asm/reg.h +5 -0
index 634b55d..93d66bc 100644
@@ -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 */
arch/mips/include/asm/syscall.h new file +84 -0

84 lines not on this page · raw message

arch/mips/include/asm/thread_info.h +4 -1
index 143a481..1d55dc0 100644
@@ -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__ */
 
arch/mips/kernel/Makefile +1 -0
index 44ec7e0..1114c85 100644
@@ -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
arch/mips/kernel/entry.S +1 -1
index ffa3310..786e4ef 100644
@@ -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()
arch/mips/kernel/ftrace.c +71 -0

80 lines not on this page · raw message

arch/mips/kernel/ptrace.c +12 -2
index 054861c..fa762dc 100644
@@ -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],
arch/mips/kernel/scall64-o32.S +1 -1
index a5598b2..dd1f13a 100644
@@ -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
Signature · 1 line
1.6.0.4