Skip to content

Commit 8062427

Browse files
Dapeng Misean-jc
authored andcommitted
KVM: x86/pmu: Disable RDPMC interception for compatible mediated vPMU
Disable RDPMC interception for vCPUs with a mediated vPMU that is compatible with the host PMU, i.e. that doesn't require KVM emulation of RDPMC to honor the guest's vCPU model. With a mediated vPMU, all guest state accessible via RDPMC is loaded into hardware while the guest is running. Adust RDPMC interception only for non-TDX guests, as the TDX module is responsible for managing RDPMC intercepts based on the TD configuration. Co-developed-by: Mingwei Zhang <mizhang@google.com> Signed-off-by: Mingwei Zhang <mizhang@google.com> Co-developed-by: Sandipan Das <sandipan.das@amd.com> Signed-off-by: Sandipan Das <sandipan.das@amd.com> Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Tested-by: Xudong Hao <xudong.hao@intel.com> Co-developed-by: Sean Christopherson <seanjc@google.com> Tested-by: Manali Shukla <manali.shukla@amd.com> Link: https://patch.msgid.link/20251206001720.468579-21-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 1c4ba72 commit 8062427

5 files changed

Lines changed: 40 additions & 0 deletions

File tree

arch/x86/kvm/pmu.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,32 @@ int kvm_pmu_rdpmc(struct kvm_vcpu *vcpu, unsigned idx, u64 *data)
714714
return 0;
715715
}
716716

717+
bool kvm_need_rdpmc_intercept(struct kvm_vcpu *vcpu)
718+
{
719+
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
720+
721+
if (!kvm_vcpu_has_mediated_pmu(vcpu))
722+
return true;
723+
724+
/*
725+
* VMware allows access to these Pseduo-PMCs even when read via RDPMC
726+
* in Ring3 when CR4.PCE=0.
727+
*/
728+
if (enable_vmware_backdoor)
729+
return true;
730+
731+
/*
732+
* Note! Check *host* PMU capabilities, not KVM's PMU capabilities, as
733+
* KVM's capabilities are constrained based on KVM support, i.e. KVM's
734+
* capabilities themselves may be a subset of hardware capabilities.
735+
*/
736+
return pmu->nr_arch_gp_counters != kvm_host_pmu.num_counters_gp ||
737+
pmu->nr_arch_fixed_counters != kvm_host_pmu.num_counters_fixed ||
738+
pmu->counter_bitmask[KVM_PMC_GP] != (BIT_ULL(kvm_host_pmu.bit_width_gp) - 1) ||
739+
pmu->counter_bitmask[KVM_PMC_FIXED] != (BIT_ULL(kvm_host_pmu.bit_width_fixed) - 1);
740+
}
741+
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_need_rdpmc_intercept);
742+
717743
void kvm_pmu_deliver_pmi(struct kvm_vcpu *vcpu)
718744
{
719745
if (lapic_in_kernel(vcpu)) {

arch/x86/kvm/pmu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ void kvm_pmu_instruction_retired(struct kvm_vcpu *vcpu);
238238
void kvm_pmu_branch_retired(struct kvm_vcpu *vcpu);
239239

240240
bool is_vmware_backdoor_pmc(u32 pmc_idx);
241+
bool kvm_need_rdpmc_intercept(struct kvm_vcpu *vcpu);
241242

242243
extern struct kvm_pmu_ops intel_pmu_ops;
243244
extern struct kvm_pmu_ops amd_pmu_ops;

arch/x86/kvm/svm/svm.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,11 @@ static void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu)
10111011
svm->vmcb->control.virt_ext |= VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK;
10121012
}
10131013
}
1014+
1015+
if (kvm_need_rdpmc_intercept(vcpu))
1016+
svm_set_intercept(svm, INTERCEPT_RDPMC);
1017+
else
1018+
svm_clr_intercept(svm, INTERCEPT_RDPMC);
10141019
}
10151020

10161021
static void svm_recalc_intercepts(struct kvm_vcpu *vcpu)

arch/x86/kvm/vmx/vmx.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4300,8 +4300,15 @@ static void vmx_recalc_msr_intercepts(struct kvm_vcpu *vcpu)
43004300
*/
43014301
}
43024302

4303+
static void vmx_recalc_instruction_intercepts(struct kvm_vcpu *vcpu)
4304+
{
4305+
exec_controls_changebit(to_vmx(vcpu), CPU_BASED_RDPMC_EXITING,
4306+
kvm_need_rdpmc_intercept(vcpu));
4307+
}
4308+
43034309
void vmx_recalc_intercepts(struct kvm_vcpu *vcpu)
43044310
{
4311+
vmx_recalc_instruction_intercepts(vcpu);
43054312
vmx_recalc_msr_intercepts(vcpu);
43064313
}
43074314

arch/x86/kvm/x86.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3945,6 +3945,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
39453945

39463946
vcpu->arch.perf_capabilities = data;
39473947
kvm_pmu_refresh(vcpu);
3948+
kvm_make_request(KVM_REQ_RECALC_INTERCEPTS, vcpu);
39483949
break;
39493950
case MSR_IA32_PRED_CMD: {
39503951
u64 reserved_bits = ~(PRED_CMD_IBPB | PRED_CMD_SBPB);

0 commit comments

Comments
 (0)