diff options
| -rw-r--r-- | arch/blackfin/Kconfig | 1 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/ftrace.h | 14 | ||||
| -rw-r--r-- | arch/blackfin/kernel/Makefile | 1 | ||||
| -rw-r--r-- | arch/blackfin/kernel/bfin_ksyms.c | 5 | ||||
| -rw-r--r-- | arch/blackfin/kernel/ftrace-entry.S | 72 |
5 files changed, 92 insertions, 1 deletions
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index d03fd638e9aa..ea8d92c1d447 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig | |||
| @@ -19,6 +19,7 @@ config RWSEM_XCHGADD_ALGORITHM | |||
| 19 | 19 | ||
| 20 | config BLACKFIN | 20 | config BLACKFIN |
| 21 | def_bool y | 21 | def_bool y |
| 22 | select HAVE_FUNCTION_TRACER | ||
| 22 | select HAVE_IDE | 23 | select HAVE_IDE |
| 23 | select HAVE_KERNEL_GZIP | 24 | select HAVE_KERNEL_GZIP |
| 24 | select HAVE_KERNEL_BZIP2 | 25 | select HAVE_KERNEL_BZIP2 |
diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h index 40a8c178f10d..8643680f0f78 100644 --- a/arch/blackfin/include/asm/ftrace.h +++ b/arch/blackfin/include/asm/ftrace.h | |||
| @@ -1 +1,13 @@ | |||
| 1 | /* empty */ | 1 | /* |
| 2 | * Blackfin ftrace code | ||
| 3 | * | ||
| 4 | * Copyright 2009 Analog Devices Inc. | ||
| 5 | * Licensed under the GPL-2 or later. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef __ASM_BFIN_FTRACE_H__ | ||
| 9 | #define __ASM_BFIN_FTRACE_H__ | ||
| 10 | |||
| 11 | #define MCOUNT_INSN_SIZE 8 /* sizeof mcount call: LINK + CALL */ | ||
| 12 | |||
| 13 | #endif | ||
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index a66dda4f4b1f..d2ae285e5b6e 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile | |||
| @@ -15,6 +15,7 @@ else | |||
| 15 | obj-y += time.o | 15 | obj-y += time.o |
| 16 | endif | 16 | endif |
| 17 | 17 | ||
| 18 | obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o | ||
| 18 | obj-$(CONFIG_IPIPE) += ipipe.o | 19 | obj-$(CONFIG_IPIPE) += ipipe.o |
| 19 | obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o | 20 | obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o |
| 20 | obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o | 21 | obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o |
diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c index 53e893ff708a..aa05e638fb7c 100644 --- a/arch/blackfin/kernel/bfin_ksyms.c +++ b/arch/blackfin/kernel/bfin_ksyms.c | |||
| @@ -103,3 +103,8 @@ EXPORT_SYMBOL(__raw_smp_mark_barrier_asm); | |||
| 103 | EXPORT_SYMBOL(__raw_smp_check_barrier_asm); | 103 | EXPORT_SYMBOL(__raw_smp_check_barrier_asm); |
| 104 | #endif | 104 | #endif |
| 105 | #endif | 105 | #endif |
| 106 | |||
| 107 | #ifdef CONFIG_FUNCTION_TRACER | ||
| 108 | extern void _mcount(void); | ||
| 109 | EXPORT_SYMBOL(_mcount); | ||
| 110 | #endif | ||
diff --git a/arch/blackfin/kernel/ftrace-entry.S b/arch/blackfin/kernel/ftrace-entry.S new file mode 100644 index 000000000000..ce71487b515f --- /dev/null +++ b/arch/blackfin/kernel/ftrace-entry.S | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | /* | ||
| 2 | * mcount and friends -- ftrace stuff | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Analog Devices Inc. | ||
| 5 | * Licensed under the GPL-2 or later. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/linkage.h> | ||
| 9 | #include <asm/ftrace.h> | ||
| 10 | |||
| 11 | .text | ||
| 12 | |||
| 13 | /* GCC will have called us before setting up the function prologue, so we | ||
| 14 | * can clobber the normal scratch registers, but we need to make sure to | ||
| 15 | * save/restore the registers used for argument passing (R0-R2) in case | ||
| 16 | * the profiled function is using them. With data registers, R3 is the | ||
| 17 | * only one we can blow away. With pointer registers, we have P0-P2. | ||
| 18 | * | ||
| 19 | * Upon entry, the RETS will point to the top of the current profiled | ||
| 20 | * function. And since GCC setup the frame for us, the previous function | ||
| 21 | * will be waiting there. mmmm pie. | ||
| 22 | */ | ||
| 23 | ENTRY(__mcount) | ||
| 24 | /* save third function arg early so we can do testing below */ | ||
| 25 | [--sp] = r2; | ||
| 26 | |||
| 27 | /* load the function pointer to the tracer */ | ||
| 28 | p0.l = _ftrace_trace_function; | ||
| 29 | p0.h = _ftrace_trace_function; | ||
| 30 | r3 = [p0]; | ||
| 31 | |||
| 32 | /* optional micro optimization: don't call the stub tracer */ | ||
| 33 | r2.l = _ftrace_stub; | ||
| 34 | r2.h = _ftrace_stub; | ||
| 35 | cc = r2 == r3; | ||
| 36 | if ! cc jump .Ldo_trace; | ||
| 37 | |||
| 38 | r2 = [sp++]; | ||
| 39 | rts; | ||
| 40 | |||
| 41 | .Ldo_trace: | ||
| 42 | |||
| 43 | /* save first/second function arg and the return register */ | ||
| 44 | [--sp] = r0; | ||
| 45 | [--sp] = r1; | ||
| 46 | [--sp] = rets; | ||
| 47 | |||
| 48 | /* setup the tracer function */ | ||
| 49 | p0 = r3; | ||
| 50 | |||
| 51 | /* tracer(ulong frompc, ulong selfpc): | ||
| 52 | * frompc: the pc that did the call to ... | ||
| 53 | * selfpc: ... this location | ||
| 54 | * the selfpc itself will need adjusting for the mcount call | ||
| 55 | */ | ||
| 56 | r1 = rets; | ||
| 57 | r0 = [fp + 4]; | ||
| 58 | r1 += -MCOUNT_INSN_SIZE; | ||
| 59 | |||
| 60 | /* call the tracer */ | ||
| 61 | call (p0); | ||
| 62 | |||
| 63 | /* restore state and get out of dodge */ | ||
| 64 | rets = [sp++]; | ||
| 65 | r1 = [sp++]; | ||
| 66 | r0 = [sp++]; | ||
| 67 | r2 = [sp++]; | ||
| 68 | |||
| 69 | .globl _ftrace_stub | ||
| 70 | _ftrace_stub: | ||
| 71 | rts; | ||
| 72 | ENDPROC(__mcount) | ||
