aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/ftrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/ftrace.c')
-rw-r--r--arch/arm/kernel/ftrace.c16
1 files changed, 7 insertions, 9 deletions
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;