aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/ftrace.c
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 /arch/powerpc/kernel/ftrace.c
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>
Diffstat (limited to 'arch/powerpc/kernel/ftrace.c')
-rw-r--r--arch/powerpc/kernel/ftrace.c67
1 files changed, 62 insertions, 5 deletions
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}