blob: b90eb1a13071bcf4aab93855101b0c6865176ae7 [file] [log] [blame]
Steven Rostedt3d083392008-05-12 21:20:42 +02001/*
2 * Code for replacing ftrace calls with jumps.
3 *
4 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
5 *
6 * Thanks goes to Ingo Molnar, for suggesting the idea.
7 * Mathieu Desnoyers, for suggesting postponing the modifications.
8 * Arjan van de Ven, for keeping me straight, and explaining to me
9 * the dangers of modifying code on the run.
10 */
11
Joe Perches3bb258b2009-10-04 17:53:29 -070012#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
Steven Rostedt3d083392008-05-12 21:20:42 +020014#include <linux/spinlock.h>
15#include <linux/hardirq.h>
Steven Rostedt6f93fc02008-08-20 12:55:07 -040016#include <linux/uaccess.h>
Steven Rostedt3d083392008-05-12 21:20:42 +020017#include <linux/ftrace.h>
18#include <linux/percpu.h>
Ingo Molnar19b3e962008-11-11 11:57:02 +010019#include <linux/sched.h>
Steven Rostedt3d083392008-05-12 21:20:42 +020020#include <linux/init.h>
21#include <linux/list.h>
matthieu castet84e1c6b2010-11-16 22:35:16 +010022#include <linux/module.h>
Steven Rostedt3d083392008-05-12 21:20:42 +020023
Frederic Weisbecker47788c52009-04-08 20:40:59 +020024#include <trace/syscall.h>
25
Steven Rostedt16239632009-02-17 17:57:30 -050026#include <asm/cacheflush.h>
Steven Rostedt59a094c2012-05-04 09:26:16 -040027#include <asm/kprobes.h>
Abhishek Sagar395a59d2008-06-21 23:47:27 +053028#include <asm/ftrace.h>
Steven Rostedt732f3ca2008-08-14 18:05:05 -040029#include <asm/nops.h>
Steven Rostedt3d083392008-05-12 21:20:42 +020030
Frederic Weisbeckercaf4b322008-11-11 07:03:45 +010031#ifdef CONFIG_DYNAMIC_FTRACE
Steven Rostedt3d083392008-05-12 21:20:42 +020032
Steven Rostedt16239632009-02-17 17:57:30 -050033int ftrace_arch_code_modify_prepare(void)
34{
35 set_kernel_text_rw();
matthieu castet84e1c6b2010-11-16 22:35:16 +010036 set_all_modules_text_rw();
Steven Rostedt16239632009-02-17 17:57:30 -050037 return 0;
38}
39
40int ftrace_arch_code_modify_post_process(void)
41{
matthieu castet84e1c6b2010-11-16 22:35:16 +010042 set_all_modules_text_ro();
Steven Rostedt16239632009-02-17 17:57:30 -050043 set_kernel_text_ro();
44 return 0;
45}
46
Steven Rostedt3d083392008-05-12 21:20:42 +020047union ftrace_code_union {
Abhishek Sagar395a59d2008-06-21 23:47:27 +053048 char code[MCOUNT_INSN_SIZE];
Steven Rostedt3d083392008-05-12 21:20:42 +020049 struct {
50 char e8;
51 int offset;
52 } __attribute__((packed));
53};
54
Steven Rostedt15adc042008-10-23 09:33:08 -040055static int ftrace_calc_offset(long ip, long addr)
Steven Rostedt3c1720f2008-05-12 21:20:43 +020056{
57 return (int)(addr - ip);
58}
59
Steven Rostedt31e88902008-11-14 16:21:19 -080060static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
Steven Rostedt3c1720f2008-05-12 21:20:43 +020061{
62 static union ftrace_code_union calc;
63
64 calc.e8 = 0xe8;
Abhishek Sagar395a59d2008-06-21 23:47:27 +053065 calc.offset = ftrace_calc_offset(ip + MCOUNT_INSN_SIZE, addr);
Steven Rostedt3c1720f2008-05-12 21:20:43 +020066
67 /*
68 * No locking needed, this must be called via kstop_machine
69 * which in essence is like running on a uniprocessor machine.
70 */
71 return calc.code;
72}
73
Suresh Siddha55ca3cc2009-10-28 18:46:57 -080074static inline int
75within(unsigned long addr, unsigned long start, unsigned long end)
76{
77 return addr >= start && addr < end;
78}
79
Steven Rostedt17666f02008-10-30 16:08:32 -040080static int
Rakib Mullick0d098a72011-05-12 23:33:40 +060081do_ftrace_mod_code(unsigned long ip, const void *new_code)
Steven Rostedt17666f02008-10-30 16:08:32 -040082{
Suresh Siddha55ca3cc2009-10-28 18:46:57 -080083 /*
84 * On x86_64, kernel text mappings are mapped read-only with
85 * CONFIG_DEBUG_RODATA. So we use the kernel identity mapping instead
86 * of the kernel text mapping to modify the kernel text.
87 *
88 * For 32bit kernels, these mappings are same and we can use
89 * kernel identity mapping to modify code.
90 */
91 if (within(ip, (unsigned long)_text, (unsigned long)_etext))
92 ip = (unsigned long)__va(__pa(ip));
93
Steven Rostedt4a6d70c2012-04-24 16:31:07 -040094 return probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE);
Steven Rostedt17666f02008-10-30 16:08:32 -040095}
96
H. Peter Anvindc326fc2011-04-18 15:19:51 -070097static const unsigned char *ftrace_nop_replace(void)
Frederic Weisbeckercaf4b322008-11-11 07:03:45 +010098{
H. Peter Anvindc326fc2011-04-18 15:19:51 -070099 return ideal_nops[NOP_ATOMIC5];
Frederic Weisbeckercaf4b322008-11-11 07:03:45 +0100100}
101
Steven Rostedt31e88902008-11-14 16:21:19 -0800102static int
Steven Rostedt8a4d0a62012-05-30 13:36:38 -0400103ftrace_modify_code_direct(unsigned long ip, unsigned const char *old_code,
Rakib Mullick0d098a72011-05-12 23:33:40 +0600104 unsigned const char *new_code)
Steven Rostedt3d083392008-05-12 21:20:42 +0200105{
Steven Rostedt6f93fc02008-08-20 12:55:07 -0400106 unsigned char replaced[MCOUNT_INSN_SIZE];
Steven Rostedt3d083392008-05-12 21:20:42 +0200107
108 /*
109 * Note: Due to modules and __init, code can
110 * disappear and change, we need to protect against faulting
Steven Rostedt76aefee2008-10-23 09:33:00 -0400111 * as well as code changing. We do this by using the
Steven Rostedtab9a0912008-10-23 09:33:01 -0400112 * probe_kernel_* functions.
Steven Rostedt3d083392008-05-12 21:20:42 +0200113 *
114 * No real locking needed, this code is run through
Steven Rostedt6f93fc02008-08-20 12:55:07 -0400115 * kstop_machine, or before SMP starts.
Steven Rostedt3d083392008-05-12 21:20:42 +0200116 */
Steven Rostedt76aefee2008-10-23 09:33:00 -0400117
118 /* read the text we want to modify */
Steven Rostedtab9a0912008-10-23 09:33:01 -0400119 if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
Steven Rostedt593eb8a2008-10-23 09:32:59 -0400120 return -EFAULT;
Steven Rostedt6f93fc02008-08-20 12:55:07 -0400121
Steven Rostedt76aefee2008-10-23 09:33:00 -0400122 /* Make sure it is what we expect it to be */
Steven Rostedt6f93fc02008-08-20 12:55:07 -0400123 if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0)
Steven Rostedt593eb8a2008-10-23 09:32:59 -0400124 return -EINVAL;
Steven Rostedt6f93fc02008-08-20 12:55:07 -0400125
Steven Rostedt76aefee2008-10-23 09:33:00 -0400126 /* replace the text with the new text */
Steven Rostedt17666f02008-10-30 16:08:32 -0400127 if (do_ftrace_mod_code(ip, new_code))
Steven Rostedt593eb8a2008-10-23 09:32:59 -0400128 return -EPERM;
Steven Rostedt6f93fc02008-08-20 12:55:07 -0400129
Steven Rostedt3d083392008-05-12 21:20:42 +0200130 sync_core();
131
Steven Rostedt6f93fc02008-08-20 12:55:07 -0400132 return 0;
Steven Rostedt3d083392008-05-12 21:20:42 +0200133}
134
Steven Rostedt31e88902008-11-14 16:21:19 -0800135int ftrace_make_nop(struct module *mod,
136 struct dyn_ftrace *rec, unsigned long addr)
137{
Rakib Mullick0d098a72011-05-12 23:33:40 +0600138 unsigned const char *new, *old;
Steven Rostedt31e88902008-11-14 16:21:19 -0800139 unsigned long ip = rec->ip;
140
141 old = ftrace_call_replace(ip, addr);
142 new = ftrace_nop_replace();
143
Steven Rostedt8a4d0a62012-05-30 13:36:38 -0400144 /*
145 * On boot up, and when modules are loaded, the MCOUNT_ADDR
146 * is converted to a nop, and will never become MCOUNT_ADDR
147 * again. This code is either running before SMP (on boot up)
148 * or before the code will ever be executed (module load).
149 * We do not want to use the breakpoint version in this case,
150 * just modify the code directly.
151 */
152 if (addr == MCOUNT_ADDR)
153 return ftrace_modify_code_direct(rec->ip, old, new);
154
155 /* Normal cases use add_brk_on_nop */
156 WARN_ONCE(1, "invalid use of ftrace_make_nop");
157 return -EINVAL;
Steven Rostedt31e88902008-11-14 16:21:19 -0800158}
159
160int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
161{
Rakib Mullick0d098a72011-05-12 23:33:40 +0600162 unsigned const char *new, *old;
Steven Rostedt31e88902008-11-14 16:21:19 -0800163 unsigned long ip = rec->ip;
164
165 old = ftrace_nop_replace();
166 new = ftrace_call_replace(ip, addr);
167
Steven Rostedt8a4d0a62012-05-30 13:36:38 -0400168 /* Should only be called when module is loaded */
169 return ftrace_modify_code_direct(rec->ip, old, new);
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200170}
171
Steven Rostedta192cd02012-05-30 13:26:37 -0400172/*
173 * The modifying_ftrace_code is used to tell the breakpoint
174 * handler to call ftrace_int3_handler(). If it fails to
175 * call this handler for a breakpoint added by ftrace, then
176 * the kernel may crash.
177 *
178 * As atomic_writes on x86 do not need a barrier, we do not
179 * need to add smp_mb()s for this to work. It is also considered
180 * that we can not read the modifying_ftrace_code before
181 * executing the breakpoint. That would be quite remarkable if
182 * it could do that. Here's the flow that is required:
183 *
184 * CPU-0 CPU-1
185 *
186 * atomic_inc(mfc);
187 * write int3s
188 * <trap-int3> // implicit (r)mb
189 * if (atomic_read(mfc))
190 * call ftrace_int3_handler()
191 *
192 * Then when we are finished:
193 *
194 * atomic_dec(mfc);
195 *
196 * If we hit a breakpoint that was not set by ftrace, it does not
197 * matter if ftrace_int3_handler() is called or not. It will
198 * simply be ignored. But it is crucial that a ftrace nop/caller
199 * breakpoint is handled. No other user should ever place a
200 * breakpoint on an ftrace nop/caller location. It must only
201 * be done by this code.
202 */
203atomic_t modifying_ftrace_code __read_mostly;
Steven Rostedt08d636b2011-08-16 09:57:10 -0400204
Steven Rostedt8a4d0a62012-05-30 13:36:38 -0400205static int
206ftrace_modify_code(unsigned long ip, unsigned const char *old_code,
207 unsigned const char *new_code);
208
Steven Rostedt08f6fba2012-04-30 16:20:23 -0400209#ifdef ARCH_SUPPORTS_FTRACE_SAVE_REGS
210/*
211 * Should never be called:
212 * As it is only called by __ftrace_replace_code() which is called by
213 * ftrace_replace_code() that x86 overrides, and by ftrace_update_code()
214 * which is called to turn mcount into nops or nops into function calls
215 * but not to convert a function from not using regs to one that uses
216 * regs, which ftrace_modify_call() is for.
217 */
218int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
219 unsigned long addr)
220{
221 WARN_ON(1);
222 return -EINVAL;
223}
224#endif
225
Steven Rostedt8a4d0a62012-05-30 13:36:38 -0400226int ftrace_update_ftrace_func(ftrace_func_t func)
227{
228 unsigned long ip = (unsigned long)(&ftrace_call);
229 unsigned char old[MCOUNT_INSN_SIZE], *new;
230 int ret;
231
232 memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
233 new = ftrace_call_replace(ip, (unsigned long)func);
234
235 /* See comment above by declaration of modifying_ftrace_code */
236 atomic_inc(&modifying_ftrace_code);
237
238 ret = ftrace_modify_code(ip, old, new);
239
Steven Rostedt08f6fba2012-04-30 16:20:23 -0400240#ifdef ARCH_SUPPORTS_FTRACE_SAVE_REGS
241 /* Also update the regs callback function */
242 if (!ret) {
243 ip = (unsigned long)(&ftrace_regs_call);
244 memcpy(old, &ftrace_regs_call, MCOUNT_INSN_SIZE);
245 new = ftrace_call_replace(ip, (unsigned long)func);
246 ret = ftrace_modify_code(ip, old, new);
247 }
248#endif
249
Steven Rostedt8a4d0a62012-05-30 13:36:38 -0400250 atomic_dec(&modifying_ftrace_code);
251
252 return ret;
253}
254
Steven Rostedt08d636b2011-08-16 09:57:10 -0400255/*
256 * A breakpoint was added to the code address we are about to
257 * modify, and this is the handle that will just skip over it.
258 * We are either changing a nop into a trace call, or a trace
259 * call to a nop. While the change is taking place, we treat
260 * it just like it was a nop.
261 */
262int ftrace_int3_handler(struct pt_regs *regs)
263{
264 if (WARN_ON_ONCE(!regs))
265 return 0;
266
267 if (!ftrace_location(regs->ip - 1))
268 return 0;
269
270 regs->ip += MCOUNT_INSN_SIZE - 1;
271
272 return 1;
273}
274
275static int ftrace_write(unsigned long ip, const char *val, int size)
276{
277 /*
278 * On x86_64, kernel text mappings are mapped read-only with
279 * CONFIG_DEBUG_RODATA. So we use the kernel identity mapping instead
280 * of the kernel text mapping to modify the kernel text.
281 *
282 * For 32bit kernels, these mappings are same and we can use
283 * kernel identity mapping to modify code.
284 */
285 if (within(ip, (unsigned long)_text, (unsigned long)_etext))
286 ip = (unsigned long)__va(__pa(ip));
287
288 return probe_kernel_write((void *)ip, val, size);
289}
290
291static int add_break(unsigned long ip, const char *old)
292{
293 unsigned char replaced[MCOUNT_INSN_SIZE];
294 unsigned char brk = BREAKPOINT_INSTRUCTION;
295
296 if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
297 return -EFAULT;
298
299 /* Make sure it is what we expect it to be */
300 if (memcmp(replaced, old, MCOUNT_INSN_SIZE) != 0)
301 return -EINVAL;
302
303 if (ftrace_write(ip, &brk, 1))
304 return -EPERM;
305
306 return 0;
307}
308
309static int add_brk_on_call(struct dyn_ftrace *rec, unsigned long addr)
310{
311 unsigned const char *old;
312 unsigned long ip = rec->ip;
313
314 old = ftrace_call_replace(ip, addr);
315
316 return add_break(rec->ip, old);
317}
318
319
320static int add_brk_on_nop(struct dyn_ftrace *rec)
321{
322 unsigned const char *old;
323
324 old = ftrace_nop_replace();
325
326 return add_break(rec->ip, old);
327}
328
Steven Rostedt08f6fba2012-04-30 16:20:23 -0400329/*
330 * If the record has the FTRACE_FL_REGS set, that means that it
331 * wants to convert to a callback that saves all regs. If FTRACE_FL_REGS
332 * is not not set, then it wants to convert to the normal callback.
333 */
334static unsigned long get_ftrace_addr(struct dyn_ftrace *rec)
335{
336 if (rec->flags & FTRACE_FL_REGS)
337 return (unsigned long)FTRACE_REGS_ADDR;
338 else
339 return (unsigned long)FTRACE_ADDR;
340}
341
342/*
343 * The FTRACE_FL_REGS_EN is set when the record already points to
344 * a function that saves all the regs. Basically the '_EN' version
345 * represents the current state of the function.
346 */
347static unsigned long get_ftrace_old_addr(struct dyn_ftrace *rec)
348{
349 if (rec->flags & FTRACE_FL_REGS_EN)
350 return (unsigned long)FTRACE_REGS_ADDR;
351 else
352 return (unsigned long)FTRACE_ADDR;
353}
354
Steven Rostedt08d636b2011-08-16 09:57:10 -0400355static int add_breakpoints(struct dyn_ftrace *rec, int enable)
356{
357 unsigned long ftrace_addr;
358 int ret;
359
360 ret = ftrace_test_record(rec, enable);
361
Steven Rostedt08f6fba2012-04-30 16:20:23 -0400362 ftrace_addr = get_ftrace_addr(rec);
Steven Rostedt08d636b2011-08-16 09:57:10 -0400363
364 switch (ret) {
365 case FTRACE_UPDATE_IGNORE:
366 return 0;
367
368 case FTRACE_UPDATE_MAKE_CALL:
369 /* converting nop to call */
370 return add_brk_on_nop(rec);
371
Steven Rostedt08f6fba2012-04-30 16:20:23 -0400372 case FTRACE_UPDATE_MODIFY_CALL_REGS:
373 case FTRACE_UPDATE_MODIFY_CALL:
374 ftrace_addr = get_ftrace_old_addr(rec);
375 /* fall through */
Steven Rostedt08d636b2011-08-16 09:57:10 -0400376 case FTRACE_UPDATE_MAKE_NOP:
377 /* converting a call to a nop */
378 return add_brk_on_call(rec, ftrace_addr);
379 }
380 return 0;
381}
382
383/*
384 * On error, we need to remove breakpoints. This needs to
385 * be done caefully. If the address does not currently have a
386 * breakpoint, we know we are done. Otherwise, we look at the
387 * remaining 4 bytes of the instruction. If it matches a nop
388 * we replace the breakpoint with the nop. Otherwise we replace
389 * it with the call instruction.
390 */
391static int remove_breakpoint(struct dyn_ftrace *rec)
392{
393 unsigned char ins[MCOUNT_INSN_SIZE];
394 unsigned char brk = BREAKPOINT_INSTRUCTION;
395 const unsigned char *nop;
396 unsigned long ftrace_addr;
397 unsigned long ip = rec->ip;
398
399 /* If we fail the read, just give up */
400 if (probe_kernel_read(ins, (void *)ip, MCOUNT_INSN_SIZE))
401 return -EFAULT;
402
403 /* If this does not have a breakpoint, we are done */
404 if (ins[0] != brk)
405 return -1;
406
407 nop = ftrace_nop_replace();
408
409 /*
410 * If the last 4 bytes of the instruction do not match
411 * a nop, then we assume that this is a call to ftrace_addr.
412 */
413 if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) != 0) {
414 /*
415 * For extra paranoidism, we check if the breakpoint is on
416 * a call that would actually jump to the ftrace_addr.
417 * If not, don't touch the breakpoint, we make just create
418 * a disaster.
419 */
Steven Rostedt08f6fba2012-04-30 16:20:23 -0400420 ftrace_addr = get_ftrace_addr(rec);
421 nop = ftrace_call_replace(ip, ftrace_addr);
422
423 if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) == 0)
424 goto update;
425
426 /* Check both ftrace_addr and ftrace_old_addr */
427 ftrace_addr = get_ftrace_old_addr(rec);
Steven Rostedt08d636b2011-08-16 09:57:10 -0400428 nop = ftrace_call_replace(ip, ftrace_addr);
429
430 if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) != 0)
431 return -EINVAL;
432 }
433
Steven Rostedt08f6fba2012-04-30 16:20:23 -0400434 update:
Steven Rostedt08d636b2011-08-16 09:57:10 -0400435 return probe_kernel_write((void *)ip, &nop[0], 1);
436}
437
438static int add_update_code(unsigned long ip, unsigned const char *new)
439{
440 /* skip breakpoint */
441 ip++;
442 new++;
443 if (ftrace_write(ip, new, MCOUNT_INSN_SIZE - 1))
444 return -EPERM;
445 return 0;
446}
447
448static int add_update_call(struct dyn_ftrace *rec, unsigned long addr)
449{
450 unsigned long ip = rec->ip;
451 unsigned const char *new;
452
453 new = ftrace_call_replace(ip, addr);
454 return add_update_code(ip, new);
455}
456
457static int add_update_nop(struct dyn_ftrace *rec)
458{
459 unsigned long ip = rec->ip;
460 unsigned const char *new;
461
462 new = ftrace_nop_replace();
463 return add_update_code(ip, new);
464}
465
466static int add_update(struct dyn_ftrace *rec, int enable)
467{
468 unsigned long ftrace_addr;
469 int ret;
470
471 ret = ftrace_test_record(rec, enable);
472
Steven Rostedt08f6fba2012-04-30 16:20:23 -0400473 ftrace_addr = get_ftrace_addr(rec);
Steven Rostedt08d636b2011-08-16 09:57:10 -0400474
475 switch (ret) {
476 case FTRACE_UPDATE_IGNORE:
477 return 0;
478
Steven Rostedt08f6fba2012-04-30 16:20:23 -0400479 case FTRACE_UPDATE_MODIFY_CALL_REGS:
480 case FTRACE_UPDATE_MODIFY_CALL:
Steven Rostedt08d636b2011-08-16 09:57:10 -0400481 case FTRACE_UPDATE_MAKE_CALL:
482 /* converting nop to call */
483 return add_update_call(rec, ftrace_addr);
484
485 case FTRACE_UPDATE_MAKE_NOP:
486 /* converting a call to a nop */
487 return add_update_nop(rec);
488 }
489
490 return 0;
491}
492
493static int finish_update_call(struct dyn_ftrace *rec, unsigned long addr)
494{
495 unsigned long ip = rec->ip;
496 unsigned const char *new;
497
498 new = ftrace_call_replace(ip, addr);
499
500 if (ftrace_write(ip, new, 1))
501 return -EPERM;
502
503 return 0;
504}
505
506static int finish_update_nop(struct dyn_ftrace *rec)
507{
508 unsigned long ip = rec->ip;
509 unsigned const char *new;
510
511 new = ftrace_nop_replace();
512
513 if (ftrace_write(ip, new, 1))
514 return -EPERM;
515 return 0;
516}
517
518static int finish_update(struct dyn_ftrace *rec, int enable)
519{
520 unsigned long ftrace_addr;
521 int ret;
522
523 ret = ftrace_update_record(rec, enable);
524
Steven Rostedt08f6fba2012-04-30 16:20:23 -0400525 ftrace_addr = get_ftrace_addr(rec);
Steven Rostedt08d636b2011-08-16 09:57:10 -0400526
527 switch (ret) {
528 case FTRACE_UPDATE_IGNORE:
529 return 0;
530
Steven Rostedt08f6fba2012-04-30 16:20:23 -0400531 case FTRACE_UPDATE_MODIFY_CALL_REGS:
532 case FTRACE_UPDATE_MODIFY_CALL:
Steven Rostedt08d636b2011-08-16 09:57:10 -0400533 case FTRACE_UPDATE_MAKE_CALL:
534 /* converting nop to call */
535 return finish_update_call(rec, ftrace_addr);
536
537 case FTRACE_UPDATE_MAKE_NOP:
538 /* converting a call to a nop */
539 return finish_update_nop(rec);
540 }
541
542 return 0;
543}
544
545static void do_sync_core(void *data)
546{
547 sync_core();
548}
549
550static void run_sync(void)
551{
552 int enable_irqs = irqs_disabled();
553
554 /* We may be called with interrupts disbled (on bootup). */
555 if (enable_irqs)
556 local_irq_enable();
557 on_each_cpu(do_sync_core, NULL, 1);
558 if (enable_irqs)
559 local_irq_disable();
560}
561
Steven Rostedte4f5d542012-04-27 09:13:18 -0400562void ftrace_replace_code(int enable)
Steven Rostedt08d636b2011-08-16 09:57:10 -0400563{
564 struct ftrace_rec_iter *iter;
565 struct dyn_ftrace *rec;
566 const char *report = "adding breakpoints";
567 int count = 0;
568 int ret;
569
570 for_ftrace_rec_iter(iter) {
571 rec = ftrace_rec_iter_record(iter);
572
573 ret = add_breakpoints(rec, enable);
574 if (ret)
575 goto remove_breakpoints;
576 count++;
577 }
578
579 run_sync();
580
581 report = "updating code";
582
583 for_ftrace_rec_iter(iter) {
584 rec = ftrace_rec_iter_record(iter);
585
586 ret = add_update(rec, enable);
587 if (ret)
588 goto remove_breakpoints;
589 }
590
591 run_sync();
592
593 report = "removing breakpoints";
594
595 for_ftrace_rec_iter(iter) {
596 rec = ftrace_rec_iter_record(iter);
597
598 ret = finish_update(rec, enable);
599 if (ret)
600 goto remove_breakpoints;
601 }
602
603 run_sync();
604
605 return;
606
607 remove_breakpoints:
608 ftrace_bug(ret, rec ? rec->ip : 0);
609 printk(KERN_WARNING "Failed on %s (%d):\n", report, count);
610 for_ftrace_rec_iter(iter) {
611 rec = ftrace_rec_iter_record(iter);
612 remove_breakpoint(rec);
613 }
614}
615
Steven Rostedt8a4d0a62012-05-30 13:36:38 -0400616static int
617ftrace_modify_code(unsigned long ip, unsigned const char *old_code,
618 unsigned const char *new_code)
619{
620 int ret;
621
622 ret = add_break(ip, old_code);
623 if (ret)
624 goto out;
625
626 run_sync();
627
628 ret = add_update_code(ip, new_code);
629 if (ret)
630 goto fail_update;
631
632 run_sync();
633
634 ret = ftrace_write(ip, new_code, 1);
635 if (ret) {
636 ret = -EPERM;
637 goto out;
638 }
639 run_sync();
640 out:
641 return ret;
642
643 fail_update:
644 probe_kernel_write((void *)ip, &old_code[0], 1);
645 goto out;
646}
647
Steven Rostedt08d636b2011-08-16 09:57:10 -0400648void arch_ftrace_update_code(int command)
649{
Steven Rostedta192cd02012-05-30 13:26:37 -0400650 /* See comment above by declaration of modifying_ftrace_code */
651 atomic_inc(&modifying_ftrace_code);
Steven Rostedt08d636b2011-08-16 09:57:10 -0400652
Steven Rostedte4f5d542012-04-27 09:13:18 -0400653 ftrace_modify_all_code(command);
Steven Rostedt08d636b2011-08-16 09:57:10 -0400654
Steven Rostedta192cd02012-05-30 13:26:37 -0400655 atomic_dec(&modifying_ftrace_code);
Steven Rostedt08d636b2011-08-16 09:57:10 -0400656}
657
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200658int __init ftrace_dyn_arch_init(void *data)
Steven Rostedt3d083392008-05-12 21:20:42 +0200659{
Steven Rostedt732f3ca2008-08-14 18:05:05 -0400660 /* The return code is retured via data */
661 *(unsigned long *)data = 0;
Steven Rostedtdfa60ab2008-05-12 21:20:43 +0200662
Steven Rostedt3d083392008-05-12 21:20:42 +0200663 return 0;
664}
Frederic Weisbeckercaf4b322008-11-11 07:03:45 +0100665#endif
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100666
Frederic Weisbeckerfb526072008-11-25 21:07:04 +0100667#ifdef CONFIG_FUNCTION_GRAPH_TRACER
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100668
Steven Rostedt5a45cfe2008-11-26 00:16:24 -0500669#ifdef CONFIG_DYNAMIC_FTRACE
670extern void ftrace_graph_call(void);
671
672static int ftrace_mod_jmp(unsigned long ip,
673 int old_offset, int new_offset)
674{
675 unsigned char code[MCOUNT_INSN_SIZE];
676
677 if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE))
678 return -EFAULT;
679
680 if (code[0] != 0xe9 || old_offset != *(int *)(&code[1]))
681 return -EINVAL;
682
683 *(int *)(&code[1]) = new_offset;
684
685 if (do_ftrace_mod_code(ip, &code))
686 return -EPERM;
687
688 return 0;
689}
690
691int ftrace_enable_ftrace_graph_caller(void)
692{
693 unsigned long ip = (unsigned long)(&ftrace_graph_call);
694 int old_offset, new_offset;
695
696 old_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE);
697 new_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE);
698
699 return ftrace_mod_jmp(ip, old_offset, new_offset);
700}
701
702int ftrace_disable_ftrace_graph_caller(void)
703{
704 unsigned long ip = (unsigned long)(&ftrace_graph_call);
705 int old_offset, new_offset;
706
707 old_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE);
708 new_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE);
709
710 return ftrace_mod_jmp(ip, old_offset, new_offset);
711}
712
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100713#endif /* !CONFIG_DYNAMIC_FTRACE */
714
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100715/*
716 * Hook the return address and push it in the stack of return addrs
717 * in current thread info.
718 */
Steven Rostedt71e308a2009-06-18 12:45:08 -0400719void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
720 unsigned long frame_pointer)
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100721{
722 unsigned long old;
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100723 int faulted;
Frederic Weisbecker287b6e62008-11-26 00:57:25 +0100724 struct ftrace_graph_ent trace;
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100725 unsigned long return_hooker = (unsigned long)
726 &return_to_handler;
727
Frederic Weisbecker380c4b12008-12-06 03:43:41 +0100728 if (unlikely(atomic_read(&current->tracing_graph_pause)))
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100729 return;
730
731 /*
732 * Protect against fault, even if it shouldn't
733 * happen. This tool is too much intrusive to
734 * ignore such a protection.
735 */
736 asm volatile(
Steven Rostedt96665782009-02-10 11:53:23 -0500737 "1: " _ASM_MOV " (%[parent]), %[old]\n"
738 "2: " _ASM_MOV " %[return_hooker], (%[parent])\n"
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100739 " movl $0, %[faulted]\n"
Steven Rostedte3944bf2009-02-10 13:07:13 -0500740 "3:\n"
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100741
742 ".section .fixup, \"ax\"\n"
Steven Rostedte3944bf2009-02-10 13:07:13 -0500743 "4: movl $1, %[faulted]\n"
744 " jmp 3b\n"
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100745 ".previous\n"
746
Steven Rostedte3944bf2009-02-10 13:07:13 -0500747 _ASM_EXTABLE(1b, 4b)
748 _ASM_EXTABLE(2b, 4b)
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100749
Steven Rostedtaa512a22009-05-13 13:52:19 -0400750 : [old] "=&r" (old), [faulted] "=r" (faulted)
Steven Rostedt96665782009-02-10 11:53:23 -0500751 : [parent] "r" (parent), [return_hooker] "r" (return_hooker)
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100752 : "memory"
753 );
754
Steven Rostedt14a866c2008-12-02 23:50:02 -0500755 if (unlikely(faulted)) {
756 ftrace_graph_stop();
757 WARN_ON(1);
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100758 return;
759 }
760
Steven Rostedt722b3c72011-02-11 20:36:02 -0500761 trace.func = self_addr;
762 trace.depth = current->curr_ret_stack + 1;
763
764 /* Only trace if the calling function expects to */
765 if (!ftrace_graph_entry(&trace)) {
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100766 *parent = old;
Frederic Weisbecker287b6e62008-11-26 00:57:25 +0100767 return;
768 }
769
Steven Rostedt722b3c72011-02-11 20:36:02 -0500770 if (ftrace_push_return_trace(old, self_addr, &trace.depth,
771 frame_pointer) == -EBUSY) {
Steven Rostedte49dc192008-12-02 23:50:05 -0500772 *parent = old;
Steven Rostedt722b3c72011-02-11 20:36:02 -0500773 return;
Steven Rostedte49dc192008-12-02 23:50:05 -0500774 }
Frederic Weisbeckere7d37372008-11-16 06:02:06 +0100775}
Frederic Weisbeckerfb526072008-11-25 21:07:04 +0100776#endif /* CONFIG_FUNCTION_GRAPH_TRACER */