perf/x86/lbr: Avoid reading the LBRs when adaptive PEBS handles them
authorAndi Kleen <ak@linux.intel.com>
Tue, 2 Apr 2019 19:45:03 +0000 (12:45 -0700)
committerIngo Molnar <mingo@kernel.org>
Tue, 16 Apr 2019 10:26:17 +0000 (12:26 +0200)
With adaptive PEBS the CPU can directly supply the LBR information,
so we don't need to read it again. But the LBRs still need to be
enabled. Add a special count to the cpuc that distinguishes these
two cases, and avoid reading the LBRs unnecessarily when PEBS is
active.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Cc: acme@kernel.org
Cc: jolsa@kernel.org
Link: https://lkml.kernel.org/r/20190402194509.2832-7-kan.liang@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/events/intel/lbr.c
arch/x86/events/perf_event.h

index 07b7175..6f814a2 100644 (file)
@@ -488,6 +488,8 @@ void intel_pmu_lbr_add(struct perf_event *event)
         * be 'new'. Conversely, a new event can get installed through the
         * context switch path for the first time.
         */
+       if (x86_pmu.intel_cap.pebs_baseline && event->attr.precise_ip > 0)
+               cpuc->lbr_pebs_users++;
        perf_sched_cb_inc(event->ctx->pmu);
        if (!cpuc->lbr_users++ && !event->total_time_running)
                intel_pmu_lbr_reset();
@@ -507,8 +509,11 @@ void intel_pmu_lbr_del(struct perf_event *event)
                task_ctx->lbr_callstack_users--;
        }
 
+       if (x86_pmu.intel_cap.pebs_baseline && event->attr.precise_ip > 0)
+               cpuc->lbr_pebs_users--;
        cpuc->lbr_users--;
        WARN_ON_ONCE(cpuc->lbr_users < 0);
+       WARN_ON_ONCE(cpuc->lbr_pebs_users < 0);
        perf_sched_cb_dec(event->ctx->pmu);
 }
 
@@ -658,7 +663,13 @@ void intel_pmu_lbr_read(void)
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
 
-       if (!cpuc->lbr_users)
+       /*
+        * Don't read when all LBRs users are using adaptive PEBS.
+        *
+        * This could be smarter and actually check the event,
+        * but this simple approach seems to work for now.
+        */
+       if (!cpuc->lbr_users || cpuc->lbr_users == cpuc->lbr_pebs_users)
                return;
 
        if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_32)
index 2059c14..dced915 100644 (file)
@@ -233,6 +233,7 @@ struct cpu_hw_events {
         * Intel LBR bits
         */
        int                             lbr_users;
+       int                             lbr_pebs_users;
        struct perf_branch_stack        lbr_stack;
        struct perf_branch_entry        lbr_entries[MAX_LBR_ENTRIES];
        struct er_account               *lbr_sel;