Patch "KVM: x86/pmu: Set enable bits for GP counters in PERF_GLOBAL_CTRL at "RESET"" has been added to the 6.8-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    KVM: x86/pmu: Set enable bits for GP counters in PERF_GLOBAL_CTRL at "RESET"

to the 6.8-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-x86-pmu-set-enable-bits-for-gp-counters-in-perf_.patch
and it can be found in the queue-6.8 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit ded52e5c57148ed18f624fd16882dc2821cec9cf
Author: Sean Christopherson <seanjc@xxxxxxxxxx>
Date:   Fri Mar 8 17:36:40 2024 -0800

    KVM: x86/pmu: Set enable bits for GP counters in PERF_GLOBAL_CTRL at "RESET"
    
    [ Upstream commit de120e1d692d73c7eefa3278837b1eb68f90728a ]
    
    Set the enable bits for general purpose counters in IA32_PERF_GLOBAL_CTRL
    when refreshing the PMU to emulate the MSR's architecturally defined
    post-RESET behavior.  Per Intel's SDM:
    
      IA32_PERF_GLOBAL_CTRL:  Sets bits n-1:0 and clears the upper bits.
    
    and
    
      Where "n" is the number of general-purpose counters available in the processor.
    
    AMD also documents this behavior for PerfMonV2 CPUs in one of AMD's many
    PPRs.
    
    Do not set any PERF_GLOBAL_CTRL bits if there are no general purpose
    counters, although a literal reading of the SDM would require the CPU to
    set either bits 63:0 or 31:0.  The intent of the behavior is to globally
    enable all GP counters; honor the intent, if not the letter of the law.
    
    Leaving PERF_GLOBAL_CTRL '0' effectively breaks PMU usage in guests that
    haven't been updated to work with PMUs that support PERF_GLOBAL_CTRL.
    This bug was recently exposed when KVM added supported for AMD's
    PerfMonV2, i.e. when KVM started exposing a vPMU with PERF_GLOBAL_CTRL to
    guest software that only knew how to program v1 PMUs (that don't support
    PERF_GLOBAL_CTRL).
    
    Failure to emulate the post-RESET behavior results in such guests
    unknowingly leaving all general purpose counters globally disabled (the
    entire reason the post-RESET value sets the GP counter enable bits is to
    maintain backwards compatibility).
    
    The bug has likely gone unnoticed because PERF_GLOBAL_CTRL has been
    supported on Intel CPUs for as long as KVM has existed, i.e. hardly anyone
    is running guest software that isn't aware of PERF_GLOBAL_CTRL on Intel
    PMUs.  And because up until v6.0, KVM _did_ emulate the behavior for Intel
    CPUs, although the old behavior was likely dumb luck.
    
    Because (a) that old code was also broken in its own way (the history of
    this code is a comedy of errors), and (b) PERF_GLOBAL_CTRL was documented
    as having a value of '0' post-RESET in all SDMs before March 2023.
    
    Initial vPMU support in commit f5132b01386b ("KVM: Expose a version 2
    architectural PMU to a guests") *almost* got it right (again likely by
    dumb luck), but for some reason only set the bits if the guest PMU was
    advertised as v1:
    
            if (pmu->version == 1) {
                    pmu->global_ctrl = (1 << pmu->nr_arch_gp_counters) - 1;
                    return;
            }
    
    Commit f19a0c2c2e6a ("KVM: PMU emulation: GLOBAL_CTRL MSR should be
    enabled on reset") then tried to remedy that goof, presumably because
    guest PMUs were leaving PERF_GLOBAL_CTRL '0', i.e. weren't enabling
    counters.
    
            pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) |
                    (((1ull << pmu->nr_arch_fixed_counters) - 1) << X86_PMC_IDX_FIXED);
            pmu->global_ctrl_mask = ~pmu->global_ctrl;
    
    That was KVM's behavior up until commit c49467a45fe0 ("KVM: x86/pmu:
    Don't overwrite the pmu->global_ctrl when refreshing") removed
    *everything*.  However, it did so based on the behavior defined by the
    SDM , which at the time stated that "Global Perf Counter Controls" is
    '0' at Power-Up and RESET.
    
    But then the March 2023 SDM (325462-079US), stealthily changed its
    "IA-32 and Intel 64 Processor States Following Power-up, Reset, or INIT"
    table to say:
    
      IA32_PERF_GLOBAL_CTRL: Sets bits n-1:0 and clears the upper bits.
    
    Note, kvm_pmu_refresh() can be invoked multiple times, i.e. it's not a
    "pure" RESET flow.  But it can only be called prior to the first KVM_RUN,
    i.e. the guest will only ever observe the final value.
    
    Note #2, KVM has always cleared global_ctrl during refresh (see commit
    f5132b01386b ("KVM: Expose a version 2 architectural PMU to a guests")),
    i.e. there is no danger of breaking existing setups by clobbering a value
    set by userspace.
    
    Reported-by: Babu Moger <babu.moger@xxxxxxx>
    Cc: Sandipan Das <sandipan.das@xxxxxxx>
    Cc: Like Xu <like.xu.linux@xxxxxxxxx>
    Cc: Mingwei Zhang <mizhang@xxxxxxxxxx>
    Cc: Dapeng Mi <dapeng1.mi@xxxxxxxxxxxxxxx>
    Cc: stable@xxxxxxxxxxxxxxx
    Reviewed-by: Dapeng Mi <dapeng1.mi@xxxxxxxxxxxxxxx>
    Tested-by: Dapeng Mi <dapeng1.mi@xxxxxxxxxxxxxxx>
    Link: https://lore.kernel.org/r/20240309013641.1413400-2-seanjc@xxxxxxxxxx
    Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 38512954ec267..2ab2d5213f52f 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -766,8 +766,20 @@ void kvm_pmu_refresh(struct kvm_vcpu *vcpu)
 	pmu->pebs_data_cfg_mask = ~0ull;
 	bitmap_zero(pmu->all_valid_pmc_idx, X86_PMC_IDX_MAX);
 
-	if (vcpu->kvm->arch.enable_pmu)
-		static_call(kvm_x86_pmu_refresh)(vcpu);
+	if (!vcpu->kvm->arch.enable_pmu)
+		return;
+
+	static_call(kvm_x86_pmu_refresh)(vcpu);
+
+	/*
+	 * At RESET, both Intel and AMD CPUs set all enable bits for general
+	 * purpose counters in IA32_PERF_GLOBAL_CTRL (so that software that
+	 * was written for v1 PMUs don't unknowingly leave GP counters disabled
+	 * in the global controls).  Emulate that behavior when refreshing the
+	 * PMU so that userspace doesn't need to manually set PERF_GLOBAL_CTRL.
+	 */
+	if (kvm_pmu_has_perf_global_ctrl(pmu) && pmu->nr_arch_gp_counters)
+		pmu->global_ctrl = GENMASK_ULL(pmu->nr_arch_gp_counters - 1, 0);
 }
 
 void kvm_pmu_init(struct kvm_vcpu *vcpu)




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux