perf/x86: Hybrid PMU support for extra_regs
authorKan Liang <kan.liang@linux.intel.com>
Mon, 12 Apr 2021 14:30:50 +0000 (07:30 -0700)
committerPeter Zijlstra <peterz@infradead.org>
Mon, 19 Apr 2021 18:03:26 +0000 (20:03 +0200)
Different hybrid PMU may have different extra registers, e.g. Core PMU
may have offcore registers, frontend register and ldlat register. Atom
core may only have offcore registers and ldlat register. Each hybrid PMU
should use its own extra_regs.

An Intel Hybrid system should always have extra registers.
Unconditionally allocate shared_regs for Intel Hybrid system.

Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Link: https://lkml.kernel.org/r/1618237865-33448-11-git-send-email-kan.liang@linux.intel.com
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/events/perf_event.h

index f92d2344aa056b2170517bc3182819a94aef6748..57d3fe1e8b044d51a355af4c220845a20e632c35 100644 (file)
@@ -154,15 +154,16 @@ again:
  */
 static int x86_pmu_extra_regs(u64 config, struct perf_event *event)
 {
+       struct extra_reg *extra_regs = hybrid(event->pmu, extra_regs);
        struct hw_perf_event_extra *reg;
        struct extra_reg *er;
 
        reg = &event->hw.extra_reg;
 
-       if (!x86_pmu.extra_regs)
+       if (!extra_regs)
                return 0;
 
-       for (er = x86_pmu.extra_regs; er->msr; er++) {
+       for (er = extra_regs; er->msr; er++) {
                if (er->event != (config & er->config_mask))
                        continue;
                if (event->attr.config1 & ~er->valid_mask)
index 447a80f88033b519211dced4eec4013c05db3cf3..f727aa5dc095f66d82d2ab9017e6c0b0e580fdc4 100644 (file)
@@ -2966,8 +2966,10 @@ intel_vlbr_constraints(struct perf_event *event)
        return NULL;
 }
 
-static int intel_alt_er(int idx, u64 config)
+static int intel_alt_er(struct cpu_hw_events *cpuc,
+                       int idx, u64 config)
 {
+       struct extra_reg *extra_regs = hybrid(cpuc->pmu, extra_regs);
        int alt_idx = idx;
 
        if (!(x86_pmu.flags & PMU_FL_HAS_RSP_1))
@@ -2979,7 +2981,7 @@ static int intel_alt_er(int idx, u64 config)
        if (idx == EXTRA_REG_RSP_1)
                alt_idx = EXTRA_REG_RSP_0;
 
-       if (config & ~x86_pmu.extra_regs[alt_idx].valid_mask)
+       if (config & ~extra_regs[alt_idx].valid_mask)
                return idx;
 
        return alt_idx;
@@ -2987,15 +2989,16 @@ static int intel_alt_er(int idx, u64 config)
 
 static void intel_fixup_er(struct perf_event *event, int idx)
 {
+       struct extra_reg *extra_regs = hybrid(event->pmu, extra_regs);
        event->hw.extra_reg.idx = idx;
 
        if (idx == EXTRA_REG_RSP_0) {
                event->hw.config &= ~INTEL_ARCH_EVENT_MASK;
-               event->hw.config |= x86_pmu.extra_regs[EXTRA_REG_RSP_0].event;
+               event->hw.config |= extra_regs[EXTRA_REG_RSP_0].event;
                event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0;
        } else if (idx == EXTRA_REG_RSP_1) {
                event->hw.config &= ~INTEL_ARCH_EVENT_MASK;
-               event->hw.config |= x86_pmu.extra_regs[EXTRA_REG_RSP_1].event;
+               event->hw.config |= extra_regs[EXTRA_REG_RSP_1].event;
                event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1;
        }
 }
@@ -3071,7 +3074,7 @@ again:
                 */
                c = NULL;
        } else {
-               idx = intel_alt_er(idx, reg->config);
+               idx = intel_alt_er(cpuc, idx, reg->config);
                if (idx != reg->idx) {
                        raw_spin_unlock_irqrestore(&era->lock, flags);
                        goto again;
@@ -4155,7 +4158,7 @@ int intel_cpuc_prepare(struct cpu_hw_events *cpuc, int cpu)
 {
        cpuc->pebs_record_size = x86_pmu.pebs_record_size;
 
-       if (x86_pmu.extra_regs || x86_pmu.lbr_sel_map) {
+       if (is_hybrid() || x86_pmu.extra_regs || x86_pmu.lbr_sel_map) {
                cpuc->shared_regs = allocate_shared_regs(cpu);
                if (!cpuc->shared_regs)
                        goto err;
index 34b7fc92f4255b9ee72626728ac8f1cc52475a97..d8c448bc837f809073624576f6684f695fdc1895 100644 (file)
@@ -650,6 +650,7 @@ struct x86_hybrid_pmu {
                                        [PERF_COUNT_HW_CACHE_RESULT_MAX];
        struct event_constraint         *event_constraints;
        struct event_constraint         *pebs_constraints;
+       struct extra_reg                *extra_regs;
 };
 
 static __always_inline struct x86_hybrid_pmu *hybrid_pmu(struct pmu *pmu)