diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/armksyms.c | 10 | ||||
-rw-r--r-- | arch/arm/kernel/entry-common.S | 4 | ||||
-rw-r--r-- | arch/arm/kernel/ftrace.c | 16 |
3 files changed, 16 insertions, 14 deletions
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 3b132215cbf8..cc7b246e9652 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
19 | #include <asm/system.h> | 19 | #include <asm/system.h> |
20 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
21 | #include <asm/ftrace.h> | ||
21 | 22 | ||
22 | /* | 23 | /* |
23 | * libgcc functions - functions that are used internally by the | 24 | * libgcc functions - functions that are used internally by the |
@@ -48,11 +49,6 @@ extern void __aeabi_ulcmp(void); | |||
48 | extern void fpundefinstr(void); | 49 | extern void fpundefinstr(void); |
49 | extern void fp_enter(void); | 50 | extern void fp_enter(void); |
50 | 51 | ||
51 | #ifdef CONFIG_FTRACE | ||
52 | extern void mcount(void); | ||
53 | EXPORT_SYMBOL(mcount); | ||
54 | #endif | ||
55 | |||
56 | /* | 52 | /* |
57 | * This has a special calling convention; it doesn't | 53 | * This has a special calling convention; it doesn't |
58 | * modify any of the usual registers, except for LR. | 54 | * modify any of the usual registers, except for LR. |
@@ -186,3 +182,7 @@ EXPORT_SYMBOL(_find_next_bit_be); | |||
186 | #endif | 182 | #endif |
187 | 183 | ||
188 | EXPORT_SYMBOL(copy_page); | 184 | EXPORT_SYMBOL(copy_page); |
185 | |||
186 | #ifdef CONFIG_FTRACE | ||
187 | EXPORT_SYMBOL(mcount); | ||
188 | #endif | ||
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 8f79a4789ed4..84694e88b428 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -9,6 +9,7 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <asm/unistd.h> | 11 | #include <asm/unistd.h> |
12 | #include <asm/ftrace.h> | ||
12 | #include <asm/arch/entry-macro.S> | 13 | #include <asm/arch/entry-macro.S> |
13 | 14 | ||
14 | #include "entry-header.S" | 15 | #include "entry-header.S" |
@@ -104,6 +105,7 @@ ENTRY(ret_from_fork) | |||
104 | ENTRY(mcount) | 105 | ENTRY(mcount) |
105 | stmdb sp!, {r0-r3, lr} | 106 | stmdb sp!, {r0-r3, lr} |
106 | mov r0, lr | 107 | mov r0, lr |
108 | sub r0, r0, #MCOUNT_INSN_SIZE | ||
107 | 109 | ||
108 | .globl mcount_call | 110 | .globl mcount_call |
109 | mcount_call: | 111 | mcount_call: |
@@ -114,6 +116,7 @@ ENTRY(ftrace_caller) | |||
114 | stmdb sp!, {r0-r3, lr} | 116 | stmdb sp!, {r0-r3, lr} |
115 | ldr r1, [fp, #-4] | 117 | ldr r1, [fp, #-4] |
116 | mov r0, lr | 118 | mov r0, lr |
119 | sub r0, r0, #MCOUNT_INSN_SIZE | ||
117 | 120 | ||
118 | .globl ftrace_call | 121 | .globl ftrace_call |
119 | ftrace_call: | 122 | ftrace_call: |
@@ -134,6 +137,7 @@ ENTRY(mcount) | |||
134 | trace: | 137 | trace: |
135 | ldr r1, [fp, #-4] | 138 | ldr r1, [fp, #-4] |
136 | mov r0, lr | 139 | mov r0, lr |
140 | sub r0, r0, #MCOUNT_INSN_SIZE | ||
137 | mov lr, pc | 141 | mov lr, pc |
138 | mov pc, r2 | 142 | mov pc, r2 |
139 | ldmia sp!, {r0-r3, pc} | 143 | ldmia sp!, {r0-r3, pc} |
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index 22f3d6e309f9..76d50e6091bc 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c | |||
@@ -12,9 +12,10 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/ftrace.h> | 14 | #include <linux/ftrace.h> |
15 | |||
15 | #include <asm/cacheflush.h> | 16 | #include <asm/cacheflush.h> |
17 | #include <asm/ftrace.h> | ||
16 | 18 | ||
17 | #define INSN_SIZE 4 | ||
18 | #define PC_OFFSET 8 | 19 | #define PC_OFFSET 8 |
19 | #define BL_OPCODE 0xeb000000 | 20 | #define BL_OPCODE 0xeb000000 |
20 | #define BL_OFFSET_MASK 0x00ffffff | 21 | #define BL_OFFSET_MASK 0x00ffffff |
@@ -32,10 +33,10 @@ unsigned char *ftrace_call_replace(unsigned long pc, unsigned long addr) | |||
32 | { | 33 | { |
33 | long offset; | 34 | long offset; |
34 | 35 | ||
35 | offset = (long)addr - (long)(pc - INSN_SIZE + PC_OFFSET); | 36 | offset = (long)addr - (long)(pc + PC_OFFSET); |
36 | if (unlikely(offset < -33554432 || offset > 33554428)) { | 37 | if (unlikely(offset < -33554432 || offset > 33554428)) { |
37 | /* Can't generate branches that far (from ARM ARM). Ftrace | 38 | /* Can't generate branches that far (from ARM ARM). Ftrace |
38 | * doesn't generate branches outside of core kernel text. | 39 | * doesn't generate branches outside of kernel text. |
39 | */ | 40 | */ |
40 | WARN_ON_ONCE(1); | 41 | WARN_ON_ONCE(1); |
41 | return NULL; | 42 | return NULL; |
@@ -52,7 +53,6 @@ int ftrace_modify_code(unsigned long pc, unsigned char *old_code, | |||
52 | 53 | ||
53 | old = *(unsigned long *)old_code; | 54 | old = *(unsigned long *)old_code; |
54 | new = *(unsigned long *)new_code; | 55 | new = *(unsigned long *)new_code; |
55 | pc -= INSN_SIZE; | ||
56 | 56 | ||
57 | __asm__ __volatile__ ( | 57 | __asm__ __volatile__ ( |
58 | "1: ldr %1, [%2] \n" | 58 | "1: ldr %1, [%2] \n" |
@@ -77,7 +77,7 @@ int ftrace_modify_code(unsigned long pc, unsigned char *old_code, | |||
77 | : "memory"); | 77 | : "memory"); |
78 | 78 | ||
79 | if (!err && (replaced == old)) | 79 | if (!err && (replaced == old)) |
80 | flush_icache_range(pc, pc + INSN_SIZE); | 80 | flush_icache_range(pc, pc + MCOUNT_INSN_SIZE); |
81 | 81 | ||
82 | return err; | 82 | return err; |
83 | } | 83 | } |
@@ -89,8 +89,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func) | |||
89 | unsigned char *new; | 89 | unsigned char *new; |
90 | 90 | ||
91 | pc = (unsigned long)&ftrace_call; | 91 | pc = (unsigned long)&ftrace_call; |
92 | pc += INSN_SIZE; | 92 | memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE); |
93 | memcpy(&old, &ftrace_call, INSN_SIZE); | ||
94 | new = ftrace_call_replace(pc, (unsigned long)func); | 93 | new = ftrace_call_replace(pc, (unsigned long)func); |
95 | ret = ftrace_modify_code(pc, (unsigned char *)&old, new); | 94 | ret = ftrace_modify_code(pc, (unsigned char *)&old, new); |
96 | return ret; | 95 | return ret; |
@@ -103,8 +102,7 @@ int ftrace_mcount_set(unsigned long *data) | |||
103 | unsigned char *new; | 102 | unsigned char *new; |
104 | 103 | ||
105 | pc = (unsigned long)&mcount_call; | 104 | pc = (unsigned long)&mcount_call; |
106 | pc += INSN_SIZE; | 105 | memcpy(&old, &mcount_call, MCOUNT_INSN_SIZE); |
107 | memcpy(&old, &mcount_call, INSN_SIZE); | ||
108 | new = ftrace_call_replace(pc, *addr); | 106 | new = ftrace_call_replace(pc, *addr); |
109 | *addr = ftrace_modify_code(pc, (unsigned char *)&old, new); | 107 | *addr = ftrace_modify_code(pc, (unsigned char *)&old, new); |
110 | return 0; | 108 | return 0; |