diff options
| author | David Miller <davem@davemloft.net> | 2008-05-14 01:06:59 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-23 16:36:13 -0400 |
| commit | d05f5f9906740474eb768823004ffcd775b12ca6 (patch) | |
| tree | 50eb1fb79355a076c51962ddb5e8a75b8fb76972 | |
| parent | aa5e5ceaf52a882a29d9b86531a20733f5116066 (diff) | |
sparc64: add ftrace support.
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
| -rw-r--r-- | arch/sparc64/Kconfig | 1 | ||||
| -rw-r--r-- | arch/sparc64/Kconfig.debug | 2 | ||||
| -rw-r--r-- | arch/sparc64/kernel/Makefile | 1 | ||||
| -rw-r--r-- | arch/sparc64/kernel/ftrace.c | 99 | ||||
| -rw-r--r-- | arch/sparc64/lib/mcount.S | 58 |
5 files changed, 156 insertions, 5 deletions
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index eb36f3b746b8..a480df6e6012 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig | |||
| @@ -11,6 +11,7 @@ config SPARC | |||
| 11 | config SPARC64 | 11 | config SPARC64 |
| 12 | bool | 12 | bool |
| 13 | default y | 13 | default y |
| 14 | select HAVE_FTRACE | ||
| 14 | select HAVE_IDE | 15 | select HAVE_IDE |
| 15 | select HAVE_LMB | 16 | select HAVE_LMB |
| 16 | select HAVE_ARCH_KGDB | 17 | select HAVE_ARCH_KGDB |
diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug index 6a4d28a4076d..d6d32d178fc8 100644 --- a/arch/sparc64/Kconfig.debug +++ b/arch/sparc64/Kconfig.debug | |||
| @@ -33,7 +33,7 @@ config DEBUG_PAGEALLOC | |||
| 33 | 33 | ||
| 34 | config MCOUNT | 34 | config MCOUNT |
| 35 | bool | 35 | bool |
| 36 | depends on STACK_DEBUG | 36 | depends on STACK_DEBUG || FTRACE |
| 37 | default y | 37 | default y |
| 38 | 38 | ||
| 39 | config FRAME_POINTER | 39 | config FRAME_POINTER |
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index ec4f5ebb1ca6..418b5782096e 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile | |||
| @@ -14,6 +14,7 @@ obj-y := process.o setup.o cpu.o idprom.o \ | |||
| 14 | power.o sbus.o sparc64_ksyms.o chmc.o \ | 14 | power.o sbus.o sparc64_ksyms.o chmc.o \ |
| 15 | visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o | 15 | visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o |
| 16 | 16 | ||
| 17 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | ||
| 17 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 18 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
| 18 | obj-$(CONFIG_PCI) += ebus.o pci_common.o \ | 19 | obj-$(CONFIG_PCI) += ebus.o pci_common.o \ |
| 19 | pci_psycho.o pci_sabre.o pci_schizo.o \ | 20 | pci_psycho.o pci_sabre.o pci_schizo.o \ |
diff --git a/arch/sparc64/kernel/ftrace.c b/arch/sparc64/kernel/ftrace.c new file mode 100644 index 000000000000..f449e6df6c4a --- /dev/null +++ b/arch/sparc64/kernel/ftrace.c | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | #include <linux/spinlock.h> | ||
| 2 | #include <linux/hardirq.h> | ||
| 3 | #include <linux/ftrace.h> | ||
| 4 | #include <linux/percpu.h> | ||
| 5 | #include <linux/init.h> | ||
| 6 | #include <linux/list.h> | ||
| 7 | |||
| 8 | static const u32 ftrace_nop = 0x01000000; | ||
| 9 | |||
| 10 | notrace int ftrace_ip_converted(unsigned long ip) | ||
| 11 | { | ||
| 12 | u32 insn = *(u32 *) ip; | ||
| 13 | |||
| 14 | return (insn == ftrace_nop); | ||
| 15 | } | ||
| 16 | |||
| 17 | notrace unsigned char *ftrace_nop_replace(void) | ||
| 18 | { | ||
| 19 | return (char *)&ftrace_nop; | ||
| 20 | } | ||
| 21 | |||
| 22 | notrace unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) | ||
| 23 | { | ||
| 24 | static u32 call; | ||
| 25 | s32 off; | ||
| 26 | |||
| 27 | off = ((s32)addr - (s32)ip); | ||
| 28 | call = 0x40000000 | ((u32)off >> 2); | ||
| 29 | |||
| 30 | return (unsigned char *) &call; | ||
| 31 | } | ||
| 32 | |||
| 33 | notrace int | ||
| 34 | ftrace_modify_code(unsigned long ip, unsigned char *old_code, | ||
| 35 | unsigned char *new_code) | ||
| 36 | { | ||
| 37 | u32 old = *(u32 *)old_code; | ||
| 38 | u32 new = *(u32 *)new_code; | ||
| 39 | u32 replaced; | ||
| 40 | int faulted; | ||
| 41 | |||
| 42 | __asm__ __volatile__( | ||
| 43 | "1: cas [%[ip]], %[old], %[new]\n" | ||
| 44 | " flush %[ip]\n" | ||
| 45 | " mov 0, %[faulted]\n" | ||
| 46 | "2:\n" | ||
| 47 | " .section .fixup,#alloc,#execinstr\n" | ||
| 48 | " .align 4\n" | ||
| 49 | "3: sethi %%hi(2b), %[faulted]\n" | ||
| 50 | " jmpl %[faulted] + %%lo(2b), %%g0\n" | ||
| 51 | " mov 1, %[faulted]\n" | ||
| 52 | " .previous\n" | ||
| 53 | " .section __ex_table,\"a\"\n" | ||
| 54 | " .align 4\n" | ||
| 55 | " .word 1b, 3b\n" | ||
| 56 | " .previous\n" | ||
| 57 | : "=r" (replaced), [faulted] "=r" (faulted) | ||
| 58 | : [new] "0" (new), [old] "r" (old), [ip] "r" (ip) | ||
| 59 | : "memory"); | ||
| 60 | |||
| 61 | if (replaced != old && replaced != new) | ||
| 62 | faulted = 2; | ||
| 63 | |||
| 64 | return faulted; | ||
| 65 | } | ||
| 66 | |||
| 67 | notrace int ftrace_update_ftrace_func(ftrace_func_t func) | ||
| 68 | { | ||
| 69 | unsigned long ip = (unsigned long)(&ftrace_call); | ||
| 70 | unsigned char old[4], *new; | ||
| 71 | |||
| 72 | memcpy(old, &ftrace_call, 4); | ||
| 73 | new = ftrace_call_replace(ip, (unsigned long)func); | ||
| 74 | return ftrace_modify_code(ip, old, new); | ||
| 75 | } | ||
| 76 | |||
| 77 | notrace int ftrace_mcount_set(unsigned long *data) | ||
| 78 | { | ||
| 79 | unsigned long ip = (long)(&mcount_call); | ||
| 80 | unsigned long *addr = data; | ||
| 81 | unsigned char old[4], *new; | ||
| 82 | |||
| 83 | /* | ||
| 84 | * Replace the mcount stub with a pointer to the | ||
| 85 | * ip recorder function. | ||
| 86 | */ | ||
| 87 | memcpy(old, &mcount_call, 4); | ||
| 88 | new = ftrace_call_replace(ip, *addr); | ||
| 89 | *addr = ftrace_modify_code(ip, old, new); | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | |||
| 95 | int __init ftrace_dyn_arch_init(void *data) | ||
| 96 | { | ||
| 97 | ftrace_mcount_set(data); | ||
| 98 | return 0; | ||
| 99 | } | ||
diff --git a/arch/sparc64/lib/mcount.S b/arch/sparc64/lib/mcount.S index 9e4534b485c7..7735a7a60533 100644 --- a/arch/sparc64/lib/mcount.S +++ b/arch/sparc64/lib/mcount.S | |||
| @@ -28,10 +28,13 @@ ovstack: | |||
| 28 | .skip OVSTACKSIZE | 28 | .skip OVSTACKSIZE |
| 29 | #endif | 29 | #endif |
| 30 | .text | 30 | .text |
| 31 | .align 32 | 31 | .align 32 |
| 32 | .globl mcount, _mcount | 32 | .globl _mcount |
| 33 | mcount: | 33 | .type _mcount,#function |
| 34 | .globl mcount | ||
| 35 | .type mcount,#function | ||
| 34 | _mcount: | 36 | _mcount: |
| 37 | mcount: | ||
| 35 | #ifdef CONFIG_STACK_DEBUG | 38 | #ifdef CONFIG_STACK_DEBUG |
| 36 | /* | 39 | /* |
| 37 | * Check whether %sp is dangerously low. | 40 | * Check whether %sp is dangerously low. |
| @@ -55,6 +58,53 @@ _mcount: | |||
| 55 | or %g3, %lo(panicstring), %o0 | 58 | or %g3, %lo(panicstring), %o0 |
| 56 | call prom_halt | 59 | call prom_halt |
| 57 | nop | 60 | nop |
| 61 | 1: | ||
| 62 | #endif | ||
| 63 | #ifdef CONFIG_FTRACE | ||
| 64 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
| 65 | mov %o7, %o0 | ||
| 66 | .globl mcount_call | ||
| 67 | mcount_call: | ||
| 68 | call ftrace_stub | ||
| 69 | mov %o0, %o7 | ||
| 70 | #else | ||
| 71 | sethi %hi(ftrace_trace_function), %g1 | ||
| 72 | sethi %hi(ftrace_stub), %g2 | ||
| 73 | ldx [%g1 + %lo(ftrace_trace_function)], %g1 | ||
| 74 | or %g2, %lo(ftrace_stub), %g2 | ||
| 75 | cmp %g1, %g2 | ||
| 76 | be,pn %icc, 1f | ||
| 77 | mov %i7, %o1 | ||
| 78 | jmpl %g1, %g0 | ||
| 79 | mov %o7, %o0 | ||
| 80 | /* not reached */ | ||
| 81 | 1: | ||
| 58 | #endif | 82 | #endif |
| 59 | 1: retl | 83 | #endif |
| 84 | retl | ||
| 60 | nop | 85 | nop |
| 86 | .size _mcount,.-_mcount | ||
| 87 | .size mcount,.-mcount | ||
| 88 | |||
| 89 | #ifdef CONFIG_FTRACE | ||
| 90 | .globl ftrace_stub | ||
| 91 | .type ftrace_stub,#function | ||
| 92 | ftrace_stub: | ||
| 93 | retl | ||
| 94 | nop | ||
| 95 | .size ftrace_stub,.-ftrace_stub | ||
| 96 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
| 97 | .globl ftrace_caller | ||
| 98 | .type ftrace_caller,#function | ||
| 99 | ftrace_caller: | ||
| 100 | mov %i7, %o1 | ||
| 101 | mov %o7, %o0 | ||
| 102 | .globl ftrace_call | ||
| 103 | ftrace_call: | ||
| 104 | call ftrace_stub | ||
| 105 | mov %o0, %o7 | ||
| 106 | retl | ||
| 107 | nop | ||
| 108 | .size ftrace_caller,.-ftrace_caller | ||
| 109 | #endif | ||
| 110 | #endif | ||
