|
38 | 38 | #include <asm/page.h>
|
39 | 39 | #include <asm/rtas.h>
|
40 | 40 | #include <asm/time.h>
|
| 41 | +#include <asm/trace.h> |
41 | 42 | #include <asm/udbg.h>
|
42 | 43 |
|
43 | 44 | struct rtas_filter {
|
@@ -523,24 +524,70 @@ static const struct rtas_function *rtas_token_to_function(s32 token)
|
523 | 524 | /* This is here deliberately so it's only used in this file */
|
524 | 525 | void enter_rtas(unsigned long);
|
525 | 526 |
|
526 |
| -static void do_enter_rtas(struct rtas_args *args) |
| 527 | +static void __do_enter_rtas(struct rtas_args *args) |
| 528 | +{ |
| 529 | + enter_rtas(__pa(args)); |
| 530 | + srr_regs_clobbered(); /* rtas uses SRRs, invalidate */ |
| 531 | +} |
| 532 | + |
| 533 | +static void __do_enter_rtas_trace(struct rtas_args *args) |
527 | 534 | {
|
528 |
| - unsigned long msr; |
| 535 | + const char *name = NULL; |
| 536 | + /* |
| 537 | + * If the tracepoints that consume the function name aren't |
| 538 | + * active, avoid the lookup. |
| 539 | + */ |
| 540 | + if ((trace_rtas_input_enabled() || trace_rtas_output_enabled())) { |
| 541 | + const s32 token = be32_to_cpu(args->token); |
| 542 | + const struct rtas_function *func = rtas_token_to_function(token); |
| 543 | + |
| 544 | + name = func->name; |
| 545 | + } |
| 546 | + |
| 547 | + trace_rtas_input(args, name); |
| 548 | + trace_rtas_ll_entry(args); |
| 549 | + |
| 550 | + __do_enter_rtas(args); |
529 | 551 |
|
| 552 | + trace_rtas_ll_exit(args); |
| 553 | + trace_rtas_output(args, name); |
| 554 | +} |
| 555 | + |
| 556 | +static void do_enter_rtas(struct rtas_args *args) |
| 557 | +{ |
| 558 | + const unsigned long msr = mfmsr(); |
| 559 | + /* |
| 560 | + * Situations where we want to skip any active tracepoints for |
| 561 | + * safety reasons: |
| 562 | + * |
| 563 | + * 1. The last code executed on an offline CPU as it stops, |
| 564 | + * i.e. we're about to call stop-self. The tracepoints' |
| 565 | + * function name lookup uses xarray, which uses RCU, which |
| 566 | + * isn't valid to call on an offline CPU. Any events |
| 567 | + * emitted on an offline CPU will be discarded anyway. |
| 568 | + * |
| 569 | + * 2. In real mode, as when invoking ibm,nmi-interlock from |
| 570 | + * the pseries MCE handler. We cannot count on trace |
| 571 | + * buffers or the entries in rtas_token_to_function_xarray |
| 572 | + * to be contained in the RMO. |
| 573 | + */ |
| 574 | + const unsigned long mask = MSR_IR | MSR_DR; |
| 575 | + const bool can_trace = likely(cpu_online(raw_smp_processor_id()) && |
| 576 | + (msr & mask) == mask); |
530 | 577 | /*
|
531 | 578 | * Make sure MSR[RI] is currently enabled as it will be forced later
|
532 | 579 | * in enter_rtas.
|
533 | 580 | */
|
534 |
| - msr = mfmsr(); |
535 | 581 | BUG_ON(!(msr & MSR_RI));
|
536 | 582 |
|
537 | 583 | BUG_ON(!irqs_disabled());
|
538 | 584 |
|
539 | 585 | hard_irq_disable(); /* Ensure MSR[EE] is disabled on PPC64 */
|
540 | 586 |
|
541 |
| - enter_rtas(__pa(args)); |
542 |
| - |
543 |
| - srr_regs_clobbered(); /* rtas uses SRRs, invalidate */ |
| 587 | + if (can_trace) |
| 588 | + __do_enter_rtas_trace(args); |
| 589 | + else |
| 590 | + __do_enter_rtas(args); |
544 | 591 | }
|
545 | 592 |
|
546 | 593 | struct rtas_t rtas;
|
|
0 commit comments