]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
perf/x86/amd/core: Avoid enabling BRS from the SVM reload path
authorSandipan Das <sandipan.das@amd.com>
Wed, 8 Jul 2026 10:32:04 +0000 (16:02 +0530)
committerIngo Molnar <mingo@kernel.org>
Wed, 8 Jul 2026 10:37:22 +0000 (12:37 +0200)
Branch Sampling (BRS) and Last Branch Record (LBR) are mutually
exclusive hardware features, and users of both are tracked via
cpuc->lbr_users.

When SVM is toggled on a CPU, the host perf events are reprogrammed to
update the HostOnly filter bit (set when virtualization is enabled,
cleared when it is disabled). On PerfMonV2-capable processors, this
reprogramming is performed by calling amd_pmu_enable_all() to rewrite
the event selectors. However, amd_pmu_enable_all() also calls
amd_brs_enable_all(), which enables BRS whenever cpuc->lbr_users > 0.
Having active LBR events satisfies this gating on processors that have
LBR but not BRS. The kernel then tries to set the BRS enable bit in
DebugExtnCfg (MSR 0xc000010f). Since that bit is deprecated on such
hardware, the write results in a #GP:

  Call Trace:
   <IRQ>
   amd_pmu_enable_all+0x1d/0x90
   amd_pmu_disable_virt+0x62/0xb0
   kvm_arch_disable_virtualization_cpu+0xa/0x40 [kvm]
   hardware_disable_nolock+0x1a/0x30 [kvm]
   __flush_smp_call_function_queue+0x9b/0x410
   __sysvec_call_function+0x18/0xc0
   sysvec_call_function+0x69/0x90
   </IRQ>
   <TASK>
   asm_sysvec_call_function+0x16/0x20
  RIP: 0010:cpuidle_enter_state+0xc4/0x450
   ? cpuidle_enter_state+0xb7/0x450
   cpuidle_enter+0x29/0x40
   cpuidle_idle_call+0xf5/0x160
   do_idle+0x7b/0xe0
   cpu_startup_entry+0x26/0x30
   start_secondary+0x115/0x140
   secondary_startup_64_no_verify+0x194/0x19b
   </TASK>

Fix this by ensuring that BRS is not enabled from the event selector
reprogramming path even when cpuc->lbr_users > 0.

Fixes: bae19fdd7e9e ("perf/x86/amd/core: Fix reloading events for SVM")
Signed-off-by: Sandipan Das <sandipan.das@amd.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://patch.msgid.link/702fa204d574b03d14e3664c7d4b201db048bbfd.1783506528.git.sandipan.das@amd.com
arch/x86/events/amd/core.c

index 6569048a8c1cc26c9da5dafa08acfefbc7bef6dd..a787409f5a6252e0e01cedd37674b807071c055f 100644 (file)
@@ -754,13 +754,11 @@ static void amd_pmu_enable_event(struct perf_event *event)
        x86_pmu_enable_event(event);
 }
 
-static void amd_pmu_enable_all(int added)
+static void __amd_pmu_enable_all(void)
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
        int idx;
 
-       amd_brs_enable_all();
-
        for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
                /* only activate events which are marked as active */
                if (!test_bit(idx, cpuc->active_mask))
@@ -775,6 +773,12 @@ static void amd_pmu_enable_all(int added)
        }
 }
 
+static void amd_pmu_enable_all(int added)
+{
+       amd_brs_enable_all();
+       __amd_pmu_enable_all();
+}
+
 static void amd_pmu_v2_enable_event(struct perf_event *event)
 {
        struct hw_perf_event *hwc = &event->hw;
@@ -1561,7 +1565,7 @@ static inline void amd_pmu_reload_virt(void)
                 * set global enable bits once again
                 */
                amd_pmu_v2_disable_all();
-               amd_pmu_enable_all(0);
+               __amd_pmu_enable_all();
                amd_pmu_v2_enable_all(0);
                return;
        }