Skip to content

Commit 24098f5

Browse files
nathanlynchmpe
authored andcommitted
powerpc/rtas: add tracepoints around RTAS entry
Decompose the RTAS entry C code into tracing and non-tracing variants, calling the just-added tracepoints in the tracing-enabled path. Skip tracing in contexts known to be unsafe (real mode, CPU offline). Signed-off-by: Nathan Lynch <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 2c81ca7 commit 24098f5

File tree

1 file changed

+53
-6
lines changed

1 file changed

+53
-6
lines changed

arch/powerpc/kernel/rtas.c

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <asm/page.h>
3939
#include <asm/rtas.h>
4040
#include <asm/time.h>
41+
#include <asm/trace.h>
4142
#include <asm/udbg.h>
4243

4344
struct rtas_filter {
@@ -523,24 +524,70 @@ static const struct rtas_function *rtas_token_to_function(s32 token)
523524
/* This is here deliberately so it's only used in this file */
524525
void enter_rtas(unsigned long);
525526

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)
527534
{
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);
529551

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);
530577
/*
531578
* Make sure MSR[RI] is currently enabled as it will be forced later
532579
* in enter_rtas.
533580
*/
534-
msr = mfmsr();
535581
BUG_ON(!(msr & MSR_RI));
536582

537583
BUG_ON(!irqs_disabled());
538584

539585
hard_irq_disable(); /* Ensure MSR[EE] is disabled on PPC64 */
540586

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);
544591
}
545592

546593
struct rtas_t rtas;

0 commit comments

Comments
 (0)