microblaze: ftrace: add static function tracer
If -pg of gcc is enabled with CONFIG_FUNCTION_TRACER=y. a calling to _mcount will be inserted into each kernel function. so, there is a possibility to trace the kernel functions in _mcount. This patch add the specific _mcount support for static function tracing. by default, ftrace_trace_function is initialized as ftrace_stub(an empty function), so, the default _mcount will introduce very little overhead. after enabling ftrace in user-space, it will jump to a real tracing function and do static function tracing for us. Commit message from Wu Zhangjin <wuzhangjin@gmail.com> Signed-off-by: Michal Simek <monstr@monstr.eu>
This commit is contained in:
Родитель
a3cd613b2e
Коммит
2fd7c761a2
|
@ -6,6 +6,7 @@ mainmenu "Linux/Microblaze Kernel Configuration"
|
||||||
config MICROBLAZE
|
config MICROBLAZE
|
||||||
def_bool y
|
def_bool y
|
||||||
select HAVE_LMB
|
select HAVE_LMB
|
||||||
|
select HAVE_FUNCTION_TRACER
|
||||||
select USB_ARCH_HAS_EHCI
|
select USB_ARCH_HAS_EHCI
|
||||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||||
|
|
||||||
|
|
|
@ -1 +1,15 @@
|
||||||
|
#ifndef _ASM_MICROBLAZE_FTRACE
|
||||||
|
#define _ASM_MICROBLAZE_FTRACE
|
||||||
|
|
||||||
|
#ifdef CONFIG_FUNCTION_TRACER
|
||||||
|
|
||||||
|
#define MCOUNT_ADDR ((long)(_mcount))
|
||||||
|
#define MCOUNT_INSN_SIZE 8 /* sizeof mcount call */
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
extern void _mcount(void);
|
||||||
|
extern void ftrace_call_graph(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONFIG_FUNCTION_TRACER */
|
||||||
|
#endif /* _ASM_MICROBLAZE_FTRACE */
|
||||||
|
|
|
@ -2,6 +2,16 @@
|
||||||
# Makefile
|
# Makefile
|
||||||
#
|
#
|
||||||
|
|
||||||
|
ifdef CONFIG_FUNCTION_TRACER
|
||||||
|
# Do not trace early boot code and low level code
|
||||||
|
CFLAGS_REMOVE_timer.o = -pg
|
||||||
|
CFLAGS_REMOVE_intc.o = -pg
|
||||||
|
CFLAGS_REMOVE_early_printk.o = -pg
|
||||||
|
CFLAGS_REMOVE_selfmod.o = -pg
|
||||||
|
CFLAGS_REMOVE_heartbeat.o = -pg
|
||||||
|
CFLAGS_REMOVE_ftrace.o = -pg
|
||||||
|
endif
|
||||||
|
|
||||||
extra-y := head.o vmlinux.lds
|
extra-y := head.o vmlinux.lds
|
||||||
|
|
||||||
obj-y += exceptions.o \
|
obj-y += exceptions.o \
|
||||||
|
@ -17,5 +27,6 @@ obj-$(CONFIG_HEART_BEAT) += heartbeat.o
|
||||||
obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o
|
obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o
|
||||||
obj-$(CONFIG_MMU) += misc.o
|
obj-$(CONFIG_MMU) += misc.o
|
||||||
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
||||||
|
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o
|
||||||
|
|
||||||
obj-y += entry$(MMU).o
|
obj-y += entry$(MMU).o
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
# Build the appropriate CPU version support
|
# Build the appropriate CPU version support
|
||||||
#
|
#
|
||||||
|
|
||||||
|
ifdef CONFIG_FUNCTION_TRACER
|
||||||
|
CFLAGS_REMOVE_cache.o = -pg
|
||||||
|
endif
|
||||||
|
|
||||||
EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
|
EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
|
||||||
-DCPU_REV=$(CPU_REV)
|
-DCPU_REV=$(CPU_REV)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* Low-level ftrace handling
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
|
||||||
|
* Copyright (C) 2009 PetaLogix
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
|
#define NOALIGN_ENTRY(name) .globl name; name:
|
||||||
|
|
||||||
|
/* FIXME MS: I think that I don't need to save all regs */
|
||||||
|
#define SAVE_REGS \
|
||||||
|
addik r1, r1, -120; \
|
||||||
|
swi r2, r1, 4; \
|
||||||
|
swi r3, r1, 8; \
|
||||||
|
swi r4, r1, 12; \
|
||||||
|
swi r5, r1, 116; \
|
||||||
|
swi r6, r1, 16; \
|
||||||
|
swi r7, r1, 20; \
|
||||||
|
swi r8, r1, 24; \
|
||||||
|
swi r9, r1, 28; \
|
||||||
|
swi r10, r1, 32; \
|
||||||
|
swi r11, r1, 36; \
|
||||||
|
swi r12, r1, 40; \
|
||||||
|
swi r13, r1, 44; \
|
||||||
|
swi r14, r1, 48; \
|
||||||
|
swi r16, r1, 52; \
|
||||||
|
swi r17, r1, 56; \
|
||||||
|
swi r18, r1, 60; \
|
||||||
|
swi r19, r1, 64; \
|
||||||
|
swi r20, r1, 68; \
|
||||||
|
swi r21, r1, 72; \
|
||||||
|
swi r22, r1, 76; \
|
||||||
|
swi r23, r1, 80; \
|
||||||
|
swi r24, r1, 84; \
|
||||||
|
swi r25, r1, 88; \
|
||||||
|
swi r26, r1, 92; \
|
||||||
|
swi r27, r1, 96; \
|
||||||
|
swi r28, r1, 100; \
|
||||||
|
swi r29, r1, 104; \
|
||||||
|
swi r30, r1, 108; \
|
||||||
|
swi r31, r1, 112;
|
||||||
|
|
||||||
|
#define RESTORE_REGS \
|
||||||
|
lwi r2, r1, 4; \
|
||||||
|
lwi r3, r1, 8; \
|
||||||
|
lwi r4, r1, 12; \
|
||||||
|
lwi r5, r1, 116; \
|
||||||
|
lwi r6, r1, 16; \
|
||||||
|
lwi r7, r1, 20; \
|
||||||
|
lwi r8, r1, 24; \
|
||||||
|
lwi r9, r1, 28; \
|
||||||
|
lwi r10, r1, 32; \
|
||||||
|
lwi r11, r1, 36; \
|
||||||
|
lwi r12, r1, 40; \
|
||||||
|
lwi r13, r1, 44; \
|
||||||
|
lwi r14, r1, 48; \
|
||||||
|
lwi r16, r1, 52; \
|
||||||
|
lwi r17, r1, 56; \
|
||||||
|
lwi r18, r1, 60; \
|
||||||
|
lwi r19, r1, 64; \
|
||||||
|
lwi r20, r1, 68; \
|
||||||
|
lwi r21, r1, 72; \
|
||||||
|
lwi r22, r1, 76; \
|
||||||
|
lwi r23, r1, 80; \
|
||||||
|
lwi r24, r1, 84; \
|
||||||
|
lwi r25, r1, 88; \
|
||||||
|
lwi r26, r1, 92; \
|
||||||
|
lwi r27, r1, 96; \
|
||||||
|
lwi r28, r1, 100; \
|
||||||
|
lwi r29, r1, 104; \
|
||||||
|
lwi r30, r1, 108; \
|
||||||
|
lwi r31, r1, 112; \
|
||||||
|
addik r1, r1, 120;
|
||||||
|
|
||||||
|
ENTRY(ftrace_stub)
|
||||||
|
rtsd r15, 8;
|
||||||
|
nop;
|
||||||
|
|
||||||
|
ENTRY(_mcount)
|
||||||
|
SAVE_REGS
|
||||||
|
swi r15, r1, 0;
|
||||||
|
/* MS: test function trace if is taken or not */
|
||||||
|
lwi r20, r0, ftrace_trace_function;
|
||||||
|
addik r6, r0, ftrace_stub;
|
||||||
|
cmpu r5, r20, r6; /* ftrace_trace_function != ftrace_stub */
|
||||||
|
beqid r5, end; /* MS: not taken -> jump over */
|
||||||
|
nop;
|
||||||
|
/* static normal trace */
|
||||||
|
lwi r6, r1, 120; /* MS: load parent addr */
|
||||||
|
addik r5, r15, 0; /* MS: load current function addr */
|
||||||
|
/* MS: here is dependency on previous code */
|
||||||
|
brald r15, r20; /* MS: jump to ftrace handler */
|
||||||
|
nop;
|
||||||
|
end:
|
||||||
|
lwi r15, r1, 0;
|
||||||
|
RESTORE_REGS
|
||||||
|
|
||||||
|
rtsd r15, 8; /* MS: jump back */
|
||||||
|
nop;
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
#include <linux/ftrace.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -47,3 +48,7 @@ extern void __umodsi3(void);
|
||||||
EXPORT_SYMBOL(__umodsi3);
|
EXPORT_SYMBOL(__umodsi3);
|
||||||
extern char *_ebss;
|
extern char *_ebss;
|
||||||
EXPORT_SYMBOL_GPL(_ebss);
|
EXPORT_SYMBOL_GPL(_ebss);
|
||||||
|
#ifdef CONFIG_FUNCTION_TRACER
|
||||||
|
extern void _mcount(void);
|
||||||
|
EXPORT_SYMBOL(_mcount);
|
||||||
|
#endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче