aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2008-11-14 19:21:19 -0500
committerSteven Rostedt <srostedt@redhat.com>2008-11-20 13:51:40 -0500
commit8fd6e5a8c81e2e9b912ea33c8425a10729db469b (patch)
tree9ea9ee2e0cb72e20ab6af3ad307fd425bc2405b7
parent6d07bb47354174a9b52d3b03f9e38b069a93d341 (diff)
powerpc: ftrace, convert to new dynamic ftrace arch API
Impact: update to PowerPC ftrace arch API This patch converts PowerPC to use the new dynamic ftrace arch API. Thanks to Paul Mackennas for pointing out the mistakes of my original test_24bit_addr function. Signed-off-by: Steven Rostedt <srostedt@redhat.com>
-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}