]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: x86/pmu: Disallow emulation in the fastpath if mediated PMCs are active
authorSean Christopherson <seanjc@google.com>
Sat, 6 Dec 2025 00:17:04 +0000 (16:17 -0800)
committerSean Christopherson <seanjc@google.com>
Thu, 8 Jan 2026 19:52:12 +0000 (11:52 -0800)
Don't handle exits in the fastpath if emulation is required, i.e. if an
instruction needs to be skipped, the mediated PMU is enabled, and one or
more PMCs is counting instructions.  With the mediated PMU, KVM's cache of
PMU state is inconsistent with respect to hardware until KVM exits the
inner run loop (when the mediated PMU is "put").

Reviewed-by: Sandipan Das <sandipan.das@amd.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Tested-by: Manali Shukla <manali.shukla@amd.com>
Link: https://patch.msgid.link/20251206001720.468579-29-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/pmu.h
arch/x86/kvm/x86.c

index 25b583da9ee29f81cf2ead31dd5c4f64beeac856..0925246731cb101d10647cddbc2e55c160c81c29 100644 (file)
@@ -234,6 +234,16 @@ static inline bool pmc_is_globally_enabled(struct kvm_pmc *pmc)
        return test_bit(pmc->idx, (unsigned long *)&pmu->global_ctrl);
 }
 
+static inline bool kvm_pmu_is_fastpath_emulation_allowed(struct kvm_vcpu *vcpu)
+{
+       struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+
+       return !kvm_vcpu_has_mediated_pmu(vcpu) ||
+              !bitmap_intersects(pmu->pmc_counting_instructions,
+                                 (unsigned long *)&pmu->global_ctrl,
+                                 X86_PMC_IDX_MAX);
+}
+
 void kvm_pmu_deliver_pmi(struct kvm_vcpu *vcpu);
 void kvm_pmu_handle_event(struct kvm_vcpu *vcpu);
 int kvm_pmu_rdpmc(struct kvm_vcpu *vcpu, unsigned pmc, u64 *data);
index 589a309259f42ed75f9dfa4f89d8b6a3e0df1b72..4683df775b0a3759ed41f7b9b9404d6eb47734c0 100644 (file)
@@ -2215,6 +2215,9 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_emulate_invd);
 
 fastpath_t handle_fastpath_invd(struct kvm_vcpu *vcpu)
 {
+       if (!kvm_pmu_is_fastpath_emulation_allowed(vcpu))
+               return EXIT_FASTPATH_NONE;
+
        if (!kvm_emulate_invd(vcpu))
                return EXIT_FASTPATH_EXIT_USERSPACE;
 
@@ -2271,6 +2274,9 @@ static inline bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu)
 
 static fastpath_t __handle_fastpath_wrmsr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 {
+       if (!kvm_pmu_is_fastpath_emulation_allowed(vcpu))
+               return EXIT_FASTPATH_NONE;
+
        switch (msr) {
        case APIC_BASE_MSR + (APIC_ICR >> 4):
                if (!lapic_in_kernel(vcpu) || !apic_x2apic_mode(vcpu->arch.apic) ||
@@ -11714,6 +11720,9 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_emulate_halt);
 
 fastpath_t handle_fastpath_hlt(struct kvm_vcpu *vcpu)
 {
+       if (!kvm_pmu_is_fastpath_emulation_allowed(vcpu))
+               return EXIT_FASTPATH_NONE;
+
        if (!kvm_emulate_halt(vcpu))
                return EXIT_FASTPATH_EXIT_USERSPACE;