mips-specific ftrace support
Subsystems (5)
v2 cover 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 -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
PATCH v2 1/6 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v2 2/6 mips dynamic function tracer support
In reply to [email protected]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 | 17 +++- 6 files changed, 267 insertions(+), 3 deletions(-) create mode 100644 arch/mips/kernel/ftrace.c
arch/mips/Kconfig +3 -0
@@ -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
@@ -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
@@ -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
@@ -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 +14 -3
@@ -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 {
Signature · 1 line
1.6.0.4
Steven Rostedt
maintainerRe: [PATCH v2 2/6] mips dynamic function tracer support
Quoted 24 lines · On Fri, 29 May 2009, [email protected] wrote:
scripts/recordmcount.pl +11
-0@@ -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) { #
scripts/recordmcount.pl if ($#converts >= 0) { · line 460
Quoted 10 lines
scripts/recordmcount.pl +2
-2# 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
Quoted 16 lines
scripts/recordmcount.pl +1
-1# # 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 {Signature · 1 line
1.6.0.4
Re: [PATCH v2 2/6] mips dynamic function tracer support
Quoted 30 lines · Steven Rostedt
Quoted 29 lines · On Fri, 29 May 2009, [email protected] wrote:
scripts/recordmcount.pl +12
-1@@ -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`;
Quoted 9 lines
scripts/recordmcount.pl if ($#converts >= 0) { · line 460
Quoted 5 lines
scripts/recordmcount.pl +1
-1# # 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
Quoted 20 lines
-- Steve
Quoted 16 lines
scripts/recordmcount.pl +1
-1# # 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 {Signature · 1 line
1.6.0.4
Re: [PATCH v2 2/6] mips dynamic function tracer support
In reply to Steven RostedtQuoted 30 lines · Steven Rostedt
Quoted 29 lines · On Fri, 29 May 2009, [email protected] wrote:
scripts/recordmcount.pl +12
-1@@ -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`;
Quoted 10 lines
scripts/recordmcount.pl if ($#converts >= 0) { · line 460
Quoted 5 lines
scripts/recordmcount.pl +1
-1# # 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:
scripts/recordmcount.pl +2 -2
@@ -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
Re: [PATCH v2 2/6] mips dynamic function tracer support
Quoted 104 lines · Wu Zhangjin
Quoted 30 lines · Steven Rostedt
Quoted 29 lines · On Fri, 29 May 2009, [email protected] wrote:
scripts/recordmcount.pl +12
-1@@ -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`;Quoted 10 lines
scripts/recordmcount.pl if ($#converts >= 0) { · line 460
Quoted 5 lines
scripts/recordmcount.pl +1
-1# # 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 directoryso 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.oarch/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 directorydid 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.oarch/mips/kernel/.tmp_gl_irq_cpu.othe last string
.../.tmp_gl_irq_cpu.obecomes the input file, but it's not there, that is the warning.fix it like this:
scripts/recordmcount.pl +2
-2@@ -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;
Quoted 2 lines
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?
Quoted 2 lines
Best Wishes,
--- Wu Zhangjin
Re: [PATCH v2 2/6] mips dynamic function tracer support
In reply to [email protected]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
Quoted 379 lines · [email protected] wrote:
From: Wu Zhangjin <[email protected]>
dynamic function tracer need to replace "nop" to "jumps & links" and something reversely.
Reviewed-by Steven Rostedt <[email protected]>Signed-off-by Wu Zhangjin <[email protected]>--- 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.carch/mips/Kconfig +3
-0@@ -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_LIBarch/mips/include/asm/ftrace.h +10
-0@@ -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@@ -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.oarch/mips/kernel/ftrace.c new file +207
-0@@ -0,0 +1,207 @@ +/* +* Code for replacing ftrace calls with jumps. +* +* Copyright (C) 2007-2008 Steven Rostedt <[email protected]> +* Copyright (C) 2009 DSLab, Lanzhou University, China +* Author: Wu Zhangjin <[email protected]> +* +* 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 */ arch/mips/kernel/mcount.S +31
-0@@ -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 reorderscripts/recordmcount.pl +14
-3@@ -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 {
Re: [PATCH v2 2/6] mips dynamic function tracer support
hi,
sorry, I'm so late to reply your E-mail, a little busy these days.
Quoted 66 lines · Wang Liming
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_mcountHere "
_mcount" is a kernel symbol in 0x80000000~0x90000000, for example at0x8027a740.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 as0x8027a740), because offset is 32 bits(is0xc0000000-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
is0x8027a740and 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()-------------------
Quoted 7 lines
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
Re: [PATCH v2 2/6] mips dynamic function tracer support
Quoted 15 lines · wu zhangjin
hi,
sorry, I'm so late to reply your E-mail, a little busy these days.
Quoted 11 lines
} ----------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.
Quoted 6 lines
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.
Quoted 3 lines
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
Quoted 4 lines
best wishes,
Wu Zhangjin
Steven Rostedt
maintainerRe: [PATCH v2 2/6] mips dynamic function tracer support
Quoted 20 lines · Wang Liming
Quoted 19 lines · wu zhangjin
hi,
sorry, I'm so late to reply your E-mail, a little busy these days.
Quoted 12 lines
}
----------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.
Quoted 6 lines
Quoted 5 lines
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
Re: [PATCH v2 2/6] mips dynamic function tracer support
hi, Steven
Quoted 16 lines
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, -8Then 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
Quoted 6 lines
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
PATCH v2 3/6 add an endian argument to scripts/recordmcount.pl
In reply to [email protected]From: Wu Zhangjin <[email protected]>
mips architecture need this argument to handle big/little endian differently.
--- scripts/Makefile.build | 1 + scripts/recordmcount.pl | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-)
scripts/Makefile.build +1 -0
@@ -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 +14 -5
@@ -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";
Signature · 1 line
1.6.0.4
Steven Rostedt
maintainerRe: [PATCH v2 3/6] add an endian argument to scripts/recordmcount.pl
Quoted 4 lines · On Fri, 29 May 2009, [email protected] wrote:
From: Wu Zhangjin <[email protected]>
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
Quoted 3 lines
Reviewed-by Steven Rostedt <[email protected]>Signed-off-by Wu Zhangjin <[email protected]>
PATCH v2 4/6 mips function graph tracer support
In reply to [email protected]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 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.
--- 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(-)
arch/mips/Kconfig +1 -0
@@ -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 +72 -0
75 lines not on this page · raw message
arch/mips/kernel/mcount.S +57 -1
87 lines not on this page · raw message
arch/mips/kernel/vmlinux.lds.S +1 -0
@@ -36,6 +36,7 @@ SECTIONS SCHED_TEXT LOCK_TEXT KPROBES_TEXT + IRQENTRY_TEXT *(.text.*) *(.fixup) *(.gnu.warning)
Signature · 1 line
1.6.0.4
PATCH v2 5/6 mips specific clock function to get precise timestamp
In reply to [email protected]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
@@ -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
@@ -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
@@ -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
PATCH v2 6/6 mips specific system call tracer
In reply to [email protected]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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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