aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r--kernel/trace/ftrace.c108
1 files changed, 50 insertions, 58 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 5cbddb59e99f..fdaab04a0282 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -327,96 +327,89 @@ ftrace_record_ip(unsigned long ip)
327 327
328static int 328static int
329__ftrace_replace_code(struct dyn_ftrace *rec, 329__ftrace_replace_code(struct dyn_ftrace *rec,
330 unsigned char *old, unsigned char *new, int enable) 330 unsigned char *nop, int enable)
331{ 331{
332 unsigned long ip, fl; 332 unsigned long ip, fl;
333 unsigned char *call, *old, *new;
333 334
334 ip = rec->ip; 335 ip = rec->ip;
335 336
336 if (ftrace_filtered && enable) { 337 /*
338 * If this record is not to be traced and
339 * it is not enabled then do nothing.
340 *
341 * If this record is not to be traced and
342 * it is enabled then disabled it.
343 *
344 */
345 if (rec->flags & FTRACE_FL_NOTRACE) {
346 if (rec->flags & FTRACE_FL_ENABLED)
347 rec->flags &= ~FTRACE_FL_ENABLED;
348 else
349 return 0;
350
351 } else if (ftrace_filtered && enable) {
337 /* 352 /*
338 * If filtering is on: 353 * Filtering is on:
339 *
340 * If this record is set to be filtered and
341 * is enabled then do nothing.
342 *
343 * If this record is set to be filtered and
344 * it is not enabled, enable it.
345 *
346 * If this record is not set to be filtered
347 * and it is not enabled do nothing.
348 *
349 * If this record is set not to trace then
350 * do nothing.
351 *
352 * If this record is set not to trace and
353 * it is enabled then disable it.
354 *
355 * If this record is not set to be filtered and
356 * it is enabled, disable it.
357 */ 354 */
358 355
359 fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE | 356 fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_ENABLED);
360 FTRACE_FL_ENABLED);
361 357
362 if ((fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED)) || 358 /* Record is filtered and enabled, do nothing */
363 (fl == (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE)) || 359 if (fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED))
364 !fl || (fl == FTRACE_FL_NOTRACE))
365 return 0; 360 return 0;
366 361
367 /* 362 /* Record is not filtered and is not enabled do nothing */
368 * If it is enabled disable it, 363 if (!fl)
369 * otherwise enable it! 364 return 0;
370 */ 365
371 if (fl & FTRACE_FL_ENABLED) { 366 /* Record is not filtered but enabled, disable it */
372 /* swap new and old */ 367 if (fl == FTRACE_FL_ENABLED)
373 new = old;
374 old = ftrace_call_replace(ip, FTRACE_ADDR);
375 rec->flags &= ~FTRACE_FL_ENABLED; 368 rec->flags &= ~FTRACE_FL_ENABLED;
376 } else { 369 else
377 new = ftrace_call_replace(ip, FTRACE_ADDR); 370 /* Otherwise record is filtered but not enabled, enable it */
378 rec->flags |= FTRACE_FL_ENABLED; 371 rec->flags |= FTRACE_FL_ENABLED;
379 }
380 } else { 372 } else {
373 /* Disable or not filtered */
381 374
382 if (enable) { 375 if (enable) {
383 /* 376 /* if record is enabled, do nothing */
384 * If this record is set not to trace and is
385 * not enabled, do nothing.
386 */
387 fl = rec->flags & (FTRACE_FL_NOTRACE | FTRACE_FL_ENABLED);
388 if (fl == FTRACE_FL_NOTRACE)
389 return 0;
390
391 new = ftrace_call_replace(ip, FTRACE_ADDR);
392 } else
393 old = ftrace_call_replace(ip, FTRACE_ADDR);
394
395 if (enable) {
396 if (rec->flags & FTRACE_FL_ENABLED) 377 if (rec->flags & FTRACE_FL_ENABLED)
397 return 0; 378 return 0;
379
398 rec->flags |= FTRACE_FL_ENABLED; 380 rec->flags |= FTRACE_FL_ENABLED;
381
399 } else { 382 } else {
383
384 /* if record is not enabled do nothing */
400 if (!(rec->flags & FTRACE_FL_ENABLED)) 385 if (!(rec->flags & FTRACE_FL_ENABLED))
401 return 0; 386 return 0;
387
402 rec->flags &= ~FTRACE_FL_ENABLED; 388 rec->flags &= ~FTRACE_FL_ENABLED;
403 } 389 }
404 } 390 }
405 391
392 call = ftrace_call_replace(ip, FTRACE_ADDR);
393
394 if (rec->flags & FTRACE_FL_ENABLED) {
395 old = nop;
396 new = call;
397 } else {
398 old = call;
399 new = nop;
400 }
401
406 return ftrace_modify_code(ip, old, new); 402 return ftrace_modify_code(ip, old, new);
407} 403}
408 404
409static void ftrace_replace_code(int enable) 405static void ftrace_replace_code(int enable)
410{ 406{
411 int i, failed; 407 int i, failed;
412 unsigned char *new = NULL, *old = NULL; 408 unsigned char *nop = NULL;
413 struct dyn_ftrace *rec; 409 struct dyn_ftrace *rec;
414 struct ftrace_page *pg; 410 struct ftrace_page *pg;
415 411
416 if (enable) 412 nop = ftrace_nop_replace();
417 old = ftrace_nop_replace();
418 else
419 new = ftrace_nop_replace();
420 413
421 for (pg = ftrace_pages_start; pg; pg = pg->next) { 414 for (pg = ftrace_pages_start; pg; pg = pg->next) {
422 for (i = 0; i < pg->index; i++) { 415 for (i = 0; i < pg->index; i++) {
@@ -434,7 +427,7 @@ static void ftrace_replace_code(int enable)
434 unfreeze_record(rec); 427 unfreeze_record(rec);
435 } 428 }
436 429
437 failed = __ftrace_replace_code(rec, old, new, enable); 430 failed = __ftrace_replace_code(rec, nop, enable);
438 if (failed && (rec->flags & FTRACE_FL_CONVERTED)) { 431 if (failed && (rec->flags & FTRACE_FL_CONVERTED)) {
439 rec->flags |= FTRACE_FL_FAILED; 432 rec->flags |= FTRACE_FL_FAILED;
440 if ((system_state == SYSTEM_BOOTING) || 433 if ((system_state == SYSTEM_BOOTING) ||
@@ -538,8 +531,7 @@ static void ftrace_startup(void)
538 531
539 mutex_lock(&ftrace_start_lock); 532 mutex_lock(&ftrace_start_lock);
540 ftrace_start++; 533 ftrace_start++;
541 if (ftrace_start == 1) 534 command |= FTRACE_ENABLE_CALLS;
542 command |= FTRACE_ENABLE_CALLS;
543 535
544 if (saved_ftrace_func != ftrace_trace_function) { 536 if (saved_ftrace_func != ftrace_trace_function) {
545 saved_ftrace_func = ftrace_trace_function; 537 saved_ftrace_func = ftrace_trace_function;