perf/x86/amd/lbr: Detect LbrExtV2 support
authorSandipan Das <sandipan.das@amd.com>
Thu, 11 Aug 2022 12:29:53 +0000 (17:59 +0530)
committerPeter Zijlstra <peterz@infradead.org>
Fri, 26 Aug 2022 22:05:43 +0000 (00:05 +0200)
AMD Last Branch Record Extension Version 2 (LbrExtV2) is driven by Core PMC
overflows. It records recently taken branches up to the moment when the PMC
overflow occurs.

Detect the feature during PMU initialization and set the branch stack depth
using CPUID leaf 0x80000022 EBX.

Signed-off-by: Sandipan Das <sandipan.das@amd.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/fc6e45378ada258f1bab79b0de6e05c393a8f1dd.1660211399.git.sandipan.das@amd.com
arch/x86/events/amd/Makefile
arch/x86/events/amd/core.c
arch/x86/events/amd/lbr.c [new file with mode: 0644]
arch/x86/events/perf_event.h
arch/x86/include/asm/perf_event.h

index b9f5d4610256d16f2816126efb6a5f83da849628..527d947eb76b92edfbe7a94e12a4f816e9a9b47f 100644 (file)
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_CPU_SUP_AMD)              += core.o
+obj-$(CONFIG_CPU_SUP_AMD)              += core.o lbr.o
 obj-$(CONFIG_PERF_EVENTS_AMD_BRS)      += brs.o
 obj-$(CONFIG_PERF_EVENTS_AMD_POWER)    += power.o
 obj-$(CONFIG_X86_LOCAL_APIC)           += ibs.o
index ef3520731a20f13d00c84b521d8b37216f78553e..a3aa67b4fd506b8dac78a57262b7763ede3ca347 100644 (file)
@@ -1374,10 +1374,11 @@ static int __init amd_core_pmu_init(void)
                x86_pmu.flags |= PMU_FL_PAIR;
        }
 
-       /*
-        * BRS requires special event constraints and flushing on ctxsw.
-        */
-       if (boot_cpu_data.x86 >= 0x19 && !amd_brs_init()) {
+       /* LBR and BRS are mutually exclusive features */
+       if (amd_pmu_lbr_init() && !amd_brs_init()) {
+               /*
+                * BRS requires special event constraints and flushing on ctxsw.
+                */
                x86_pmu.get_event_constraints = amd_get_event_constraints_f19h;
                x86_pmu.sched_task = amd_pmu_brs_sched_task;
                x86_pmu.limit_period = amd_pmu_limit_period;
diff --git a/arch/x86/events/amd/lbr.c b/arch/x86/events/amd/lbr.c
new file mode 100644 (file)
index 0000000..4e5b5d3
--- /dev/null
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/perf_event.h>
+#include <asm/perf_event.h>
+
+#include "../perf_event.h"
+
+__init int amd_pmu_lbr_init(void)
+{
+       union cpuid_0x80000022_ebx ebx;
+
+       if (x86_pmu.version < 2 || !boot_cpu_has(X86_FEATURE_AMD_LBR_V2))
+               return -EOPNOTSUPP;
+
+       /* Set number of entries */
+       ebx.full = cpuid_ebx(EXT_PERFMON_DEBUG_FEATURES);
+       x86_pmu.lbr_nr = ebx.split.lbr_v2_stack_sz;
+
+       pr_cont("%d-deep LBR, ", x86_pmu.lbr_nr);
+
+       return 0;
+}
index 5deb34e42bbd448ecbdb60286b000e9672178295..82e8a6d87adefdbbc0a65470c956c35cf95b2ab5 100644 (file)
@@ -1232,6 +1232,8 @@ static inline bool fixed_counter_disabled(int i, struct pmu *pmu)
 
 int amd_pmu_init(void);
 
+int amd_pmu_lbr_init(void);
+
 #ifdef CONFIG_PERF_EVENTS_AMD_BRS
 
 #define AMD_FAM19H_BRS_EVENT 0xc4 /* RETIRED_TAKEN_BRANCH_INSTRUCTIONS */
index f6fc8dd51ef477f894d41a59f30e49819fecedb4..9ac46dbe57d48fc3d6eb53471ef725899917f1d7 100644 (file)
@@ -207,7 +207,8 @@ union cpuid_0x80000022_ebx {
        struct {
                /* Number of Core Performance Counters */
                unsigned int    num_core_pmc:4;
-               unsigned int    reserved:6;
+               /* Number of available LBR Stack Entries */
+               unsigned int    lbr_v2_stack_sz:6;
                /* Number of Data Fabric Counters */
                unsigned int    num_df_pmc:6;
        } split;