aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/ftrace.h14
-rw-r--r--arch/powerpc/kernel/ftrace.c67
2 files changed, 75 insertions, 6 deletions
diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h
index b298f7a631e6..17efecc2bf03 100644
--- a/arch/powerpc/include/asm/ftrace.h
+++ b/arch/powerpc/include/asm/ftrace.h
@@ -7,7 +7,19 @@
7 7
8#ifndef __ASSEMBLY__ 8#ifndef __ASSEMBLY__
9extern void _mcount(void); 9extern void _mcount(void);
10#endif 10
11#ifdef CONFIG_DYNAMIC_FTRACE
12static inline unsigned long ftrace_call_adjust(unsigned long addr)
13{
14 /* reloction of mcount call site is the same as the address */
15 return addr;
16}
17
18struct dyn_arch_ftrace {
19 /* nothing yet */
20};
21#endif /* CONFIG_DYNAMIC_FTRACE */
22#endif /* __ASSEMBLY__ */
11 23
12#endif 24#endif
13 25
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index f4b006ed0ab1..24c023a5cae8 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -33,12 +33,12 @@ static unsigned int ftrace_calc_offset(long ip, long addr)
33 return (int)(addr - ip); 33 return (int)(addr - ip);
34} 34}
35 35
36unsigned char *ftrace_nop_replace(void) 36static unsigned char *ftrace_nop_replace(void)
37{ 37{
38 return (char *)&ftrace_nop; 38 return (char *)&ftrace_nop;
39} 39}
40 40
41unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) 41static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
42{ 42{
43 static unsigned int op; 43 static unsigned int op;
44 44
@@ -68,7 +68,7 @@ unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
68# define _ASM_PTR " .long " 68# define _ASM_PTR " .long "
69#endif 69#endif
70 70
71int 71static int
72ftrace_modify_code(unsigned long ip, unsigned char *old_code, 72ftrace_modify_code(unsigned long ip, unsigned char *old_code,
73 unsigned char *new_code) 73 unsigned char *new_code)
74{ 74{
@@ -113,6 +113,62 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
113 return faulted; 113 return faulted;
114} 114}
115 115
116static int test_24bit_addr(unsigned long ip, unsigned long addr)
117{
118 long diff;
119
120 /*
121 * Can we get to addr from ip in 24 bits?
122 * (26 really, since we mulitply by 4 for 4 byte alignment)
123 */
124 diff = addr - ip;
125
126 /*
127 * Return true if diff is less than 1 << 25
128 * and greater than -1 << 26.
129 */
130 return (diff < (1 << 25)) && (diff > (-1 << 26));
131}
132
133int ftrace_make_nop(struct module *mod,
134 struct dyn_ftrace *rec, unsigned long addr)
135{
136 unsigned char *old, *new;
137
138 /*
139 * If the calling address is more that 24 bits away,
140 * then we had to use a trampoline to make the call.
141 * Otherwise just update the call site.
142 */
143 if (test_24bit_addr(rec->ip, addr)) {
144 /* within range */
145 old = ftrace_call_replace(rec->ip, addr);
146 new = ftrace_nop_replace();
147 return ftrace_modify_code(rec->ip, old, new);
148 }
149
150 return 0;
151}
152
153int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
154{
155 unsigned char *old, *new;
156
157 /*
158 * If the calling address is more that 24 bits away,
159 * then we had to use a trampoline to make the call.
160 * Otherwise just update the call site.
161 */
162 if (test_24bit_addr(rec->ip, addr)) {
163 /* within range */
164 old = ftrace_nop_replace();
165 new = ftrace_call_replace(rec->ip, addr);
166 return ftrace_modify_code(rec->ip, old, new);
167 }
168
169 return 0;
170}
171
116int ftrace_update_ftrace_func(ftrace_func_t func) 172int ftrace_update_ftrace_func(ftrace_func_t func)
117{ 173{
118 unsigned long ip = (unsigned long)(&ftrace_call); 174 unsigned long ip = (unsigned long)(&ftrace_call);
@@ -128,9 +184,10 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
128 184
129int __init ftrace_dyn_arch_init(void *data) 185int __init ftrace_dyn_arch_init(void *data)
130{ 186{
131 /* This is running in kstop_machine */ 187 /* caller expects data to be zero */
188 unsigned long *p = data;
132 189
133 ftrace_mcount_set(data); 190 *p = 0;
134 191
135 return 0; 192 return 0;
136} 193}