powerpc/ppc32: ftrace, dynamic ftrace to handle modules
[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         unsigned char replaced[MCOUNT_INSN_SIZE];
278         unsigned int *op = (unsigned *)&replaced;
279         unsigned char jmp[8];
280         unsigned int *ptr = (unsigned int *)&jmp;
281         unsigned long ip = rec->ip;
282         unsigned long tramp;
283         int offset;
284
285         if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
286                 return -EFAULT;
287
288         /* Make sure that that this is still a 24bit jump */
289         if (!is_bl_op(*op)) {
290                 printk(KERN_ERR "Not expected bl: opcode is %x\n", *op);
291                 return -EINVAL;
292         }
293
294         /* lets find where the pointer goes */
295         tramp = find_bl_target(ip, *op);
296
297         /*
298          * On PPC32 the trampoline looks like:
299          * lis r11,sym@ha
300          * addi r11,r11,sym@l
301          * mtctr r11
302          * bctr
303          */
304
305         DEBUGP("ip:%lx jumps to %lx", ip, tramp);
306
307         /* Find where the trampoline jumps to */
308         if (probe_kernel_read(jmp, (void *)tramp, 8)) {
309                 printk(KERN_ERR "Failed to read %lx\n", tramp);
310                 return -EFAULT;
311         }
312
313         DEBUGP(" %08x %08x ", ptr[0], ptr[1]);
314
315         tramp = (ptr[1] & 0xffff) |
316                 ((ptr[0] & 0xffff) << 16);
317         if (tramp & 0x8000)
318                 tramp -= 0x10000;
319
320         DEBUGP(" %x ", tramp);
321
322         if (tramp != addr) {
323                 printk(KERN_ERR
324                        "Trampoline location %08lx does not match addr\n",
325                        tramp);
326                 return -EINVAL;
327         }
328
329         op[0] = PPC_NOP_INSTR;
330
331         if (probe_kernel_write((void *)ip, replaced, MCOUNT_INSN_SIZE))
332                 return -EPERM;
333
334         return 0;
335 }
336 #endif /* PPC64 */
337
338 int ftrace_make_nop(struct module *mod,
339                     struct dyn_ftrace *rec, unsigned long addr)
340 {
341         unsigned char *old, *new;
342         unsigned long ip = rec->ip;
343
344         /*
345          * If the calling address is more that 24 bits away,
346          * then we had to use a trampoline to make the call.
347          * Otherwise just update the call site.
348          */
349         if (test_24bit_addr(ip, addr)) {
350                 /* within range */
351                 old = ftrace_call_replace(ip, addr);
352                 new = ftrace_nop_replace();
353                 return ftrace_modify_code(ip, old, new);
354         }
355
356         /*
357          * Out of range jumps are called from modules.
358          * We should either already have a pointer to the module
359          * or it has been passed in.
360          */
361         if (!rec->arch.mod) {
362                 if (!mod) {
363                         printk(KERN_ERR "No module loaded addr=%lx\n",
364                                addr);
365                         return -EFAULT;
366                 }
367                 rec->arch.mod = mod;
368         } else if (mod) {
369                 if (mod != rec->arch.mod) {
370                         printk(KERN_ERR
371                                "Record mod %p not equal to passed in mod %p\n",
372                                rec->arch.mod, mod);
373                         return -EINVAL;
374                 }
375                 /* nothing to do if mod == rec->arch.mod */
376         } else
377                 mod = rec->arch.mod;
378
379         return __ftrace_make_nop(mod, rec, addr);
380
381 }
382
383 #ifdef CONFIG_PPC64
384 static int
385 __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
386 {
387         unsigned char replaced[MCOUNT_INSN_SIZE * 2];
388         unsigned int *op = (unsigned *)&replaced;
389         unsigned long ip = rec->ip;
390         unsigned long offset;
391
392         /* read where this goes */
393         if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE * 2))
394                 return -EFAULT;
395
396         /*
397          * It should be pointing to two nops or
398          *  b +8; ld r2,40(r1)
399          */
400         if (((op[0] != 0x48000008) || (op[1] != 0xe8410028)) &&
401             ((op[0] != PPC_NOP_INSTR) || (op[1] != PPC_NOP_INSTR))) {
402                 printk(KERN_ERR "Expected NOPs but have %x %x\n", op[0], op[1]);
403                 return -EINVAL;
404         }
405
406         /* If we never set up a trampoline to ftrace_caller, then bail */
407         if (!rec->arch.mod->arch.tramp) {
408                 printk(KERN_ERR "No ftrace trampoline\n");
409                 return -EINVAL;
410         }
411
412         /* now calculate a jump to the ftrace caller trampoline */
413         offset = rec->arch.mod->arch.tramp - ip;
414
415         if (test_offset(offset)) {
416                 printk(KERN_ERR "REL24 %li out of range!\n",
417                        (long int)offset);
418                 return -EINVAL;
419         }
420
421         /* Set to "bl addr" */
422         op[0] = branch_offset(offset);
423         /* ld r2,40(r1) */
424         op[1] = 0xe8410028;
425
426         DEBUGP("write to %lx\n", rec->ip);
427
428         if (probe_kernel_write((void *)ip, replaced, MCOUNT_INSN_SIZE * 2))
429                 return -EPERM;
430
431         return 0;
432 }
433 #else
434 static int
435 __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
436 {
437         unsigned char replaced[MCOUNT_INSN_SIZE];
438         unsigned int *op = (unsigned *)&replaced;
439         unsigned long ip = rec->ip;
440         unsigned long offset;
441
442         /* read where this goes */
443         if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
444                 return -EFAULT;
445
446         /* It should be pointing to a nop */
447         if (op[0] != PPC_NOP_INSTR) {
448                 printk(KERN_ERR "Expected NOP but have %x\n", op[0]);
449                 return -EINVAL;
450         }
451
452         /* If we never set up a trampoline to ftrace_caller, then bail */
453         if (!rec->arch.mod->arch.tramp) {
454                 printk(KERN_ERR "No ftrace trampoline\n");
455                 return -EINVAL;
456         }
457
458         /* now calculate a jump to the ftrace caller trampoline */
459         offset = rec->arch.mod->arch.tramp - ip;
460
461         if (test_offset(offset)) {
462                 printk(KERN_ERR "REL24 %li out of range!\n",
463                        (long int)offset);
464                 return -EINVAL;
465         }
466
467         /* Set to "bl addr" */
468         op[0] = branch_offset(offset);
469
470         DEBUGP("write to %lx\n", rec->ip);
471
472         if (probe_kernel_write((void *)ip, replaced, MCOUNT_INSN_SIZE))
473                 return -EPERM;
474
475         return 0;
476 }
477 #endif /* CONFIG_PPC64 */
478
479 int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
480 {
481         unsigned char *old, *new;
482         unsigned long ip = rec->ip;
483
484         /*
485          * If the calling address is more that 24 bits away,
486          * then we had to use a trampoline to make the call.
487          * Otherwise just update the call site.
488          */
489         if (test_24bit_addr(ip, addr)) {
490                 /* within range */
491                 old = ftrace_nop_replace();
492                 new = ftrace_call_replace(ip, addr);
493                 return ftrace_modify_code(ip, old, new);
494         }
495
496         /*
497          * Out of range jumps are called from modules.
498          * Being that we are converting from nop, it had better
499          * already have a module defined.
500          */
501         if (!rec->arch.mod) {
502                 printk(KERN_ERR "No module loaded\n");
503                 return -EINVAL;
504         }
505
506         return __ftrace_make_call(rec, addr);
507 }
508
509 int ftrace_update_ftrace_func(ftrace_func_t func)
510 {
511         unsigned long ip = (unsigned long)(&ftrace_call);
512         unsigned char old[MCOUNT_INSN_SIZE], *new;
513         int ret;
514
515         memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
516         new = ftrace_call_replace(ip, (unsigned long)func);
517         ret = ftrace_modify_code(ip, old, new);
518
519         return ret;
520 }
521
522 int __init ftrace_dyn_arch_init(void *data)
523 {
524         /* caller expects data to be zero */
525         unsigned long *p = data;
526
527         *p = 0;
528
529         return 0;
530 }