KVM: x86/pmu: Reset the PMU, i.e. stop counters, before refreshing
commit 1647b52757d59131fe30cf73fa36fac834d4367f upstream. Stop all counters and release all perf events before refreshing the vPMU, i.e. before reconfiguring the vPMU to respond to changes in the vCPU model. Clear need_cleanup in kvm_pmu_reset() as well so that KVM doesn't prematurely stop counters, e.g. if KVM enters the guest and enables counters before the vCPU is scheduled out. Cc: stable@vger.kernel.org Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Link: https://lore.kernel.org/r/20231103230541.352265-3-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
57bbd59ae0
commit
7c7ddf4586
|
@ -657,25 +657,14 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* refresh PMU settings. This function generally is called when underlying
|
|
||||||
* settings are changed (such as changes of PMU CPUID by guest VMs), which
|
|
||||||
* should rarely happen.
|
|
||||||
*/
|
|
||||||
void kvm_pmu_refresh(struct kvm_vcpu *vcpu)
|
|
||||||
{
|
|
||||||
if (KVM_BUG_ON(kvm_vcpu_has_run(vcpu), vcpu->kvm))
|
|
||||||
return;
|
|
||||||
|
|
||||||
bitmap_zero(vcpu_to_pmu(vcpu)->all_valid_pmc_idx, X86_PMC_IDX_MAX);
|
|
||||||
static_call(kvm_x86_pmu_refresh)(vcpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
void kvm_pmu_reset(struct kvm_vcpu *vcpu)
|
void kvm_pmu_reset(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
|
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
|
||||||
struct kvm_pmc *pmc;
|
struct kvm_pmc *pmc;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
pmu->need_cleanup = false;
|
||||||
|
|
||||||
bitmap_zero(pmu->reprogram_pmi, X86_PMC_IDX_MAX);
|
bitmap_zero(pmu->reprogram_pmi, X86_PMC_IDX_MAX);
|
||||||
|
|
||||||
for_each_set_bit(i, pmu->all_valid_pmc_idx, X86_PMC_IDX_MAX) {
|
for_each_set_bit(i, pmu->all_valid_pmc_idx, X86_PMC_IDX_MAX) {
|
||||||
|
@ -695,6 +684,26 @@ void kvm_pmu_reset(struct kvm_vcpu *vcpu)
|
||||||
static_call_cond(kvm_x86_pmu_reset)(vcpu);
|
static_call_cond(kvm_x86_pmu_reset)(vcpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Refresh the PMU configuration for the vCPU, e.g. if userspace changes CPUID
|
||||||
|
* and/or PERF_CAPABILITIES.
|
||||||
|
*/
|
||||||
|
void kvm_pmu_refresh(struct kvm_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
if (KVM_BUG_ON(kvm_vcpu_has_run(vcpu), vcpu->kvm))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop/release all existing counters/events before realizing the new
|
||||||
|
* vPMU model.
|
||||||
|
*/
|
||||||
|
kvm_pmu_reset(vcpu);
|
||||||
|
|
||||||
|
bitmap_zero(vcpu_to_pmu(vcpu)->all_valid_pmc_idx, X86_PMC_IDX_MAX);
|
||||||
|
static_call(kvm_x86_pmu_refresh)(vcpu);
|
||||||
|
}
|
||||||
|
|
||||||
void kvm_pmu_init(struct kvm_vcpu *vcpu)
|
void kvm_pmu_init(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
|
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
|
||||||
|
|
Loading…
Reference in New Issue