[PATCH v2 1/3] perf/x86: Add x86_pmu::print_debug
Sandipan Das <[email protected]>
| Newsgroups | org.kernel.vger.linux-perf-users,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <36cb7f0289adf8a186e6107ae3f6f5286857fd00.1786728929.git.sandipan.das@amd.com> |
perf_event_print_debug() dumps the global control and status MSRs whenever x86_pmu.version >= 2, reading registers that exist only on Intel-compatible PMUs. This is not safe since x86_pmu.version is not Intel-specific and is now set by other vendors whose global registers use different addresses. As a first step, split perf_event_print_debug() in two. The register dump moves into a new common helper, x86_pmu_print_debug(), leaving perf_event_print_debug() to handle the preamble and dispatch to an optional x86_pmu::print_debug method. This lets each vendor-specific PMU dump its own global state before chaining into the common helper. PMUs that do not implement the method, such as those with x86_pmu.version < 2, get the common helper alone. No functional change intended. Signed-off-by: Sandipan Das <[email protected]> --- arch/x86/events/core.c | 35 +++++++++++++++++++++++++++-------- arch/x86/events/perf_event.h | 4 ++++ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 8b3ea0adb965..364a4c83f677 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -105,6 +105,8 @@ DEFINE_STATIC_CALL_NULL(x86_pmu_pebs_disable, *x86_pmu.pebs_disable); DEFINE_STATIC_CALL_NULL(x86_pmu_pebs_enable_all, *x86_pmu.pebs_enable_all); DEFINE_STATIC_CALL_NULL(x86_pmu_pebs_disable_all, *x86_pmu.pebs_disable_all); +DEFINE_STATIC_CALL_NULL(x86_pmu_print_debug, *x86_pmu.print_debug); + /* * This one is magic, it will get called even when PMU init fails (because * there is no PMU), in which case it should simply return NULL. @@ -1571,26 +1573,20 @@ static void x86_pmu_start(struct perf_event *event, int flags) perf_event_update_userpage(event); } -void perf_event_print_debug(void) +void x86_pmu_print_debug(int cpu) { u64 ctrl, status, overflow, pmc_ctrl, pmc_count, prev_left, fixed; unsigned long *cntr_mask, *fixed_cntr_mask; struct event_constraint *pebs_constraints; struct cpu_hw_events *cpuc; u64 pebs, debugctl; - int cpu, idx; - - guard(irqsave)(); + int idx; - cpu = smp_processor_id(); cpuc = &per_cpu(cpu_hw_events, cpu); cntr_mask = hybrid(cpuc->pmu, cntr_mask); fixed_cntr_mask = hybrid(cpuc->pmu, fixed_cntr_mask); pebs_constraints = hybrid(cpuc->pmu, pebs_constraints); - if (!*(u64 *)cntr_mask) - return; - if (x86_pmu.version >= 2) { rdmsrq(MSR_CORE_PERF_GLOBAL_CTRL, ctrl); rdmsrq(MSR_CORE_PERF_GLOBAL_STATUS, status); @@ -1634,6 +1630,24 @@ void perf_event_print_debug(void) } } +void perf_event_print_debug(void) +{ + struct cpu_hw_events *cpuc; + unsigned long *cntr_mask; + int cpu; + + guard(irqsave)(); + + cpu = smp_processor_id(); + cpuc = &per_cpu(cpu_hw_events, cpu); + cntr_mask = hybrid(cpuc->pmu, cntr_mask); + + if (!*(u64 *)cntr_mask) + return; + + static_call(x86_pmu_print_debug)(cpu); +} + void x86_pmu_stop(struct perf_event *event, int flags) { struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); @@ -2122,6 +2136,8 @@ static void x86_pmu_static_call_update(void) static_call_update(x86_pmu_pebs_disable, x86_pmu.pebs_disable); static_call_update(x86_pmu_pebs_enable_all, x86_pmu.pebs_enable_all); static_call_update(x86_pmu_pebs_disable_all, x86_pmu.pebs_disable_all); + + static_call_update(x86_pmu_print_debug, x86_pmu.print_debug); } static void _x86_pmu_read(struct perf_event *event) @@ -2233,6 +2249,9 @@ static int __init init_hw_perf_events(void) if (!x86_pmu.update) x86_pmu.update = x86_perf_event_update; + if (!x86_pmu.print_debug) + x86_pmu.print_debug = x86_pmu_print_debug; + x86_pmu_static_call_update(); /* diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index fa381110f7a7..a5d15ff50a2d 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -1052,6 +1052,8 @@ struct x86_pmu { int num_hybrid_pmus; struct x86_hybrid_pmu *hybrid_pmu; enum intel_cpu_type (*get_hybrid_cpu_type) (void); + + void (*print_debug)(int cpu); }; struct x86_perf_task_context_opt { @@ -1317,6 +1319,8 @@ int x86_pmu_handle_irq(struct pt_regs *regs); void x86_pmu_show_pmu_cap(struct pmu *pmu); +void x86_pmu_print_debug(int cpu); + static inline int x86_pmu_num_counters(struct pmu *pmu) { return hweight64(hybrid(pmu, cntr_mask64)); -- 2.53.0