aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/armksyms.c10
-rw-r--r--arch/arm/kernel/entry-common.S4
-rw-r--r--arch/arm/kernel/ftrace.c16
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);
48extern void fpundefinstr(void); 49extern void fpundefinstr(void);
49extern void fp_enter(void); 50extern void fp_enter(void);
50 51
51#ifdef CONFIG_FTRACE
52extern void mcount(void);
53EXPORT_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
188EXPORT_SYMBOL(copy_page); 184EXPORT_SYMBOL(copy_page);
185
186#ifdef CONFIG_FTRACE
187EXPORT_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)
104ENTRY(mcount) 105ENTRY(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
109mcount_call: 111mcount_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
119ftrace_call: 122ftrace_call:
@@ -134,6 +137,7 @@ ENTRY(mcount)
134trace: 137trace:
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;