powerpc/ppc64: ftrace, handle module trampolines for dyn ftrace
[safe/jmp/linux-2.6] / arch / powerpc / kernel / ftrace.c
1 /*
2  * Code for replacing ftrace calls with jumps.
3  *
4  * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
5  *
6  * Thanks goes out to P.A. Semi, Inc for supplying me with a PPC64 box.
7  *
8  */
9
10 #include <linux/spinlock.h>
11 #include <linux/hardirq.h>
12 #include <linux/uaccess.h>
13 #include <linux/module.h>
14 #include <linux/ftrace.h>
15 #include <linux/percpu.h>
16 #include <linux/init.h>
17 #include <linux/list.h>
18
19 #include <asm/cacheflush.h>
20 #include <asm/code-patching.h>
21 #include <asm/ftrace.h>
22
23 #if 0
24 #define DEBUGP printk
25 #else
26 #define DEBUGP(fmt , ...)       do { } while (0)
27 #endif
28
29 static unsigned int ftrace_nop = PPC_NOP_INSTR;
30
31 #ifdef CONFIG_PPC32
32 # define GET_ADDR(addr) addr
33 #else
34 /* PowerPC64's functions are data that points to the functions */
35 # define GET_ADDR(addr) (*(unsigned long *)addr)
36 #endif
37
38
39 static unsigned int ftrace_calc_offset(long ip, long addr)
40 {
41         return (int)(addr - ip);
42 }
43
44 static unsigned char *ftrace_nop_replace(void)
45 {
46         return (char *)&ftrace_nop;
47 }
48
49 static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
50 {
51         static unsigned int op;
52
53         /*
54          * It would be nice to just use create_function_call, but that will
55          * update the code itself. Here we need to just return the
56          * instruction that is going to be modified, without modifying the
57          * code.
58          */
59         addr = GET_ADDR(addr);
60
61         /* Set to "bl addr" */
62         op = 0x48000001 | (ftrace_calc_offset(ip, addr) & 0x03fffffc);
63
64         /*
65          * No locking needed, this must be called via kstop_machine
66          * which in essence is like running on a uniprocessor machine.
67          */
68         return (unsigned char *)&op;
69 }
70
71 #ifdef CONFIG_PPC64
72 # define _ASM_ALIGN     " .align 3 "
73 # define _ASM_PTR       " .llong "
74 #else
75 # define _ASM_ALIGN     " .align 2 "
76 # define _ASM_PTR       " .long "
77 #endif
78
79 static int
80 ftrace_modify_code(unsigned long ip, unsigned char *old_code,
81                    unsigned char *new_code)
82 {
83         unsigned char replaced[MCOUNT_INSN_SIZE];
84
85         /*
86          * Note: Due to modules and __init, code can
87          *  disappear and change, we need to protect against faulting
88          *  as well as code changing. We do this by using the
89          *  probe_kernel_* functions.
90          *
91          * No real locking needed, this code is run through
92          * kstop_machine, or before SMP starts.
93          */
94
95         /* read the text we want to modify */
96         if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
97                 return -EFAULT;
98
99         /* Make sure it is what we expect it to be */
100         if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0)
101                 return -EINVAL;
102
103         /* replace the text with the new text */
104         if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE))
105                 return -EPERM;
106
107         flush_icache_range(ip, ip + 8);
108
109         return 0;
110 }
111
112 /*
113  * Helper functions that are the same for both PPC64 and PPC32.
114  */
115 static int test_24bit_addr(unsigned long ip, unsigned long addr)
116 {
117         long diff;
118
119         /*
120          * Can we get to addr from ip in 24 bits?
121          *  (26 really, since we mulitply by 4 for 4 byte alignment)
122          */
123         diff = addr - ip;
124
125         /*
126          * Return true if diff is less than 1 << 25
127          *  and greater than -1 << 26.
128          */
129         return (diff < (1 << 25)) && (diff > (-1 << 26));
130 }
131
132 static int is_bl_op(unsigned int op)
133 {
134         return (op & 0xfc000003) == 0x48000001;
135 }
136
137 static int test_offset(unsigned long offset)
138 {
139         return (offset + 0x2000000 > 0x3ffffff) || ((offset & 3) != 0);
140 }
141
142 static unsigned long find_bl_target(unsigned long ip, unsigned int op)
143 {
144         static int offset;
145
146         offset = (op & 0x03fffffc);
147         /* make it signed */
148         if (offset & 0x02000000)
149                 offset |= 0xfe000000;
150
151         return ip + (long)offset;
152 }
153
154 static unsigned int branch_offset(unsigned long offset)
155 {
156         /* return "bl ip+offset" */
157         return 0x48000001 | (offset & 0x03fffffc);
158 }
159
160 #ifdef CONFIG_PPC64
161 static int
162 __ftrace_make_nop(struct module *mod,
163                   struct dyn_ftrace *rec, unsigned long addr)
164 {
165         unsigned char replaced[MCOUNT_INSN_SIZE * 2];
166         unsigned int *op = (unsigned *)&replaced;
167         unsigned char jmp[8];
168         unsigned long *ptr = (unsigned long *)&jmp;
169         unsigned long ip = rec->ip;
170         unsigned long tramp;
171         int offset;
172
173         /* read where this goes */
174         if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
175                 return -EFAULT;
176
177         /* Make sure that that this is still a 24bit jump */
178         if (!is_bl_op(*op)) {
179                 printk(KERN_ERR "Not expected bl: opcode is %x\n", *op);
180                 return -EINVAL;
181         }
182
183         /* lets find where the pointer goes */
184         tramp = find_bl_target(ip, *op);
185
186         /*
187          * On PPC64 the trampoline looks like:
188          * 0x3d, 0x82, 0x00, 0x00,    addis   r12,r2, <high>
189          * 0x39, 0x8c, 0x00, 0x00,    addi    r12,r12, <low>
190          *   Where the bytes 2,3,6 and 7 make up the 32bit offset
191          *   to the TOC that holds the pointer.
192          *   to jump to.
193          * 0xf8, 0x41, 0x00, 0x28,    std     r2,40(r1)
194          * 0xe9, 0x6c, 0x00, 0x20,    ld      r11,32(r12)
195          *   The actually address is 32 bytes from the offset
196          *   into the TOC.
197          * 0xe8, 0x4c, 0x00, 0x28,    ld      r2,40(r12)
198          */
199
200         DEBUGP("ip:%lx jumps to %lx r2: %lx", ip, tramp, mod->arch.toc);
201
202         /* Find where the trampoline jumps to */
203         if (probe_kernel_read(jmp, (void *)tramp, 8)) {
204                 printk(KERN_ERR "Failed to read %lx\n", tramp);
205                 return -EFAULT;
206         }
207
208         DEBUGP(" %08x %08x",
209                (unsigned)(*ptr >> 32),
210                (unsigned)*ptr);
211
212         offset = (unsigned)jmp[2] << 24 |
213                 (unsigned)jmp[3] << 16 |
214                 (unsigned)jmp[6] << 8 |
215                 (unsigned)jmp[7];
216
217         DEBUGP(" %x ", offset);
218
219         /* get the address this jumps too */
220         tramp = mod->arch.toc + offset + 32;
221         DEBUGP("toc: %lx", tramp);
222
223         if (probe_kernel_read(jmp, (void *)tramp, 8)) {
224                 printk(KERN_ERR "Failed to read %lx\n", tramp);
225                 return -EFAULT;
226         }
227
228         DEBUGP(" %08x %08x\n",
229                (unsigned)(*ptr >> 32),
230                (unsigned)*ptr);
231
232         /* This should match what was called */
233         if (*ptr != GET_ADDR(addr)) {
234                 printk(KERN_ERR "addr does not match %lx\n", *ptr);
235                 return -EINVAL;
236         }
237
238         /*
239          * We want to nop the line, but the next line is
240          *  0xe8, 0x41, 0x00, 0x28   ld r2,40(r1)
241          * This needs to be turned to a nop too.
242          */
243         if (probe_kernel_read(replaced, (void *)(ip+4), MCOUNT_INSN_SIZE))
244                 return -EFAULT;
245
246         if (*op != 0xe8410028) {
247                 printk(KERN_ERR "Next line is not ld! (%08x)\n", *op);
248                 return -EINVAL;
249         }
250
251         /*
252          * Milton Miller pointed out that we can not blindly do nops.
253          * If a task was preempted when calling a trace function,
254          * the nops will remove the way to restore the TOC in r2
255          * and the r2 TOC will get corrupted.
256          */
257
258         /*
259          * Replace:
260          *   bl <tramp>  <==== will be replaced with "b 1f"
261          *   ld r2,40(r1)
262          *  1:
263          */
264         op[0] = 0x48000008;     /* b +8 */
265
266         if (probe_kernel_write((void *)ip, replaced, MCOUNT_INSN_SIZE))
267                 return -EPERM;
268
269         return 0;
270 }
271
272 #else /* !PPC64 */
273 static int
274 __ftrace_make_nop(struct module *mod,
275                   struct dyn_ftrace *rec, unsigned long addr)
276 {
277         /* Ignore modules for PPC32 (for now) */
278         return 0;
279 }
280 #endif /* PPC64 */
281
282 int ftrace_make_nop(struct module *mod,
283                     struct dyn_ftrace *rec, unsigned long addr)
284 {
285         unsigned char *old, *new;
286         unsigned long ip = rec->ip;
287
288         /*
289          * If the calling address is more that 24 bits away,
290          * then we had to use a trampoline to make the call.
291          * Otherwise just update the call site.
292          */
293         if (test_24bit_addr(ip, addr)) {
294                 /* within range */
295                 old = ftrace_call_replace(ip, addr);
296                 new = ftrace_nop_replace();
297                 return ftrace_modify_code(ip, old, new);
298         }
299
300 #ifdef CONFIG_PPC64
301         /*
302          * Out of range jumps are called from modules.
303          * We should either already have a pointer to the module
304          * or it has been passed in.
305          */
306         if (!rec->arch.mod) {
307                 if (!mod) {
308                         printk(KERN_ERR "No module loaded addr=%lx\n",
309                                addr);
310                         return -EFAULT;
311                 }
312                 rec->arch.mod = mod;
313         } else if (mod) {
314                 if (mod != rec->arch.mod) {
315                         printk(KERN_ERR
316                                "Record mod %p not equal to passed in mod %p\n",
317                                rec->arch.mod, mod);
318                         return -EINVAL;
319                 }
320                 /* nothing to do if mod == rec->arch.mod */
321         } else
322                 mod = rec->arch.mod;
323 #endif /* CONFIG_PPC64 */
324
325         return __ftrace_make_nop(mod, rec, addr);
326
327 }
328
329 #ifdef CONFIG_PPC64
330 static int
331 __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
332 {
333         unsigned char replaced[MCOUNT_INSN_SIZE * 2];
334         unsigned int *op = (unsigned *)&replaced;
335         unsigned long ip = rec->ip;
336         unsigned long offset;
337
338         /* read where this goes */
339         if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE * 2))
340                 return -EFAULT;
341
342         /*
343          * It should be pointing to two nops or
344          *  b +8; ld r2,40(r1)
345          */
346         if (((op[0] != 0x48000008) || (op[1] != 0xe8410028)) &&
347             ((op[0] != PPC_NOP_INSTR) || (op[1] != PPC_NOP_INSTR))) {
348                 printk(KERN_ERR "Expected NOPs but have %x %x\n", op[0], op[1]);
349                 return -EINVAL;
350         }
351
352         /* If we never set up a trampoline to ftrace_caller, then bail */
353         if (!rec->arch.mod->arch.tramp) {
354                 printk(KERN_ERR "No ftrace trampoline\n");
355                 return -EINVAL;
356         }
357
358         /* now calculate a jump to the ftrace caller trampoline */
359         offset = rec->arch.mod->arch.tramp - ip;
360
361         if (test_offset(offset)) {
362                 printk(KERN_ERR "REL24 %li out of range!\n",
363                        (long int)offset);
364                 return -EINVAL;
365         }
366
367         /* Set to "bl addr" */
368         op[0] = branch_offset(offset);
369         /* ld r2,40(r1) */
370         op[1] = 0xe8410028;
371
372         DEBUGP("write to %lx\n", rec->ip);
373
374         if (probe_kernel_write((void *)ip, replaced, MCOUNT_INSN_SIZE * 2))
375                 return -EPERM;
376
377         return 0;
378 }
379 #else
380 static int
381 __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
382 {
383         /* PPC32 ignores modules for now */
384         return 0;
385 }
386 #endif /* CONFIG_PPC64 */
387
388 int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
389 {
390         unsigned char *old, *new;
391         unsigned long ip = rec->ip;
392
393         /*
394          * If the calling address is more that 24 bits away,
395          * then we had to use a trampoline to make the call.
396          * Otherwise just update the call site.
397          */
398         if (test_24bit_addr(ip, addr)) {
399                 /* within range */
400                 old = ftrace_nop_replace();
401                 new = ftrace_call_replace(ip, addr);
402                 return ftrace_modify_code(ip, old, new);
403         }
404
405 #ifdef CONFIG_PPC64
406         /*
407          * Out of range jumps are called from modules.
408          * Being that we are converting from nop, it had better
409          * already have a module defined.
410          */
411         if (!rec->arch.mod) {
412                 printk(KERN_ERR "No module loaded\n");
413                 return -EINVAL;
414         }
415 #endif
416
417         return __ftrace_make_call(rec, addr);
418 }
419
420 int ftrace_update_ftrace_func(ftrace_func_t func)
421 {
422         unsigned long ip = (unsigned long)(&ftrace_call);
423         unsigned char old[MCOUNT_INSN_SIZE], *new;
424         int ret;
425
426         memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
427         new = ftrace_call_replace(ip, (unsigned long)func);
428         ret = ftrace_modify_code(ip, old, new);
429
430         return ret;
431 }
432
433 int __init ftrace_dyn_arch_init(void *data)
434 {
435         /* caller expects data to be zero */
436         unsigned long *p = data;
437
438         *p = 0;
439
440         return 0;
441 }