mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-20 17:41:09 +00:00
KVM: x86/pmu: Move PMU reset logic to common x86 code
Move the common (or at least "ignored") aspects of resetting the vPMU to common x86 code, along with the stop/release helpers that are no used only by the common pmu.c. There is no need to manually handle fixed counters as all_valid_pmc_idx tracks both fixed and general purpose counters, and resetting the vPMU is far from a hot path, i.e. the extra bit of overhead to the PMC from the index is a non-issue. Zero fixed_ctr_ctrl in common code even though it's Intel specific. Ensuring it's zero doesn't harm AMD/SVM in any way, and stopping the fixed counters via all_valid_pmc_idx, but not clearing the associated control bits, would be odd/confusing. Make the .reset() hook optional as SVM no longer needs vendor specific handling. Cc: stable@vger.kernel.org Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Link: https://lore.kernel.org/r/20231103230541.352265-2-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
parent
e9e60c82fe
commit
cbb359d81a
5 changed files with 40 additions and 56 deletions
|
@ -22,7 +22,7 @@ KVM_X86_PMU_OP(get_msr)
|
|||
KVM_X86_PMU_OP(set_msr)
|
||||
KVM_X86_PMU_OP(refresh)
|
||||
KVM_X86_PMU_OP(init)
|
||||
KVM_X86_PMU_OP(reset)
|
||||
KVM_X86_PMU_OP_OPTIONAL(reset)
|
||||
KVM_X86_PMU_OP_OPTIONAL(deliver_pmi)
|
||||
KVM_X86_PMU_OP_OPTIONAL(cleanup)
|
||||
|
||||
|
|
|
@ -250,6 +250,24 @@ static bool pmc_resume_counter(struct kvm_pmc *pmc)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void pmc_release_perf_event(struct kvm_pmc *pmc)
|
||||
{
|
||||
if (pmc->perf_event) {
|
||||
perf_event_release_kernel(pmc->perf_event);
|
||||
pmc->perf_event = NULL;
|
||||
pmc->current_config = 0;
|
||||
pmc_to_pmu(pmc)->event_count--;
|
||||
}
|
||||
}
|
||||
|
||||
static void pmc_stop_counter(struct kvm_pmc *pmc)
|
||||
{
|
||||
if (pmc->perf_event) {
|
||||
pmc->counter = pmc_read_counter(pmc);
|
||||
pmc_release_perf_event(pmc);
|
||||
}
|
||||
}
|
||||
|
||||
static int filter_cmp(const void *pa, const void *pb, u64 mask)
|
||||
{
|
||||
u64 a = *(u64 *)pa & mask;
|
||||
|
@ -654,7 +672,27 @@ void kvm_pmu_refresh(struct kvm_vcpu *vcpu)
|
|||
|
||||
void kvm_pmu_reset(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
static_call(kvm_x86_pmu_reset)(vcpu);
|
||||
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
|
||||
struct kvm_pmc *pmc;
|
||||
int i;
|
||||
|
||||
bitmap_zero(pmu->reprogram_pmi, X86_PMC_IDX_MAX);
|
||||
|
||||
for_each_set_bit(i, pmu->all_valid_pmc_idx, X86_PMC_IDX_MAX) {
|
||||
pmc = static_call(kvm_x86_pmu_pmc_idx_to_pmc)(pmu, i);
|
||||
if (!pmc)
|
||||
continue;
|
||||
|
||||
pmc_stop_counter(pmc);
|
||||
pmc->counter = 0;
|
||||
|
||||
if (pmc_is_gp(pmc))
|
||||
pmc->eventsel = 0;
|
||||
}
|
||||
|
||||
pmu->fixed_ctr_ctrl = pmu->global_ctrl = pmu->global_status = 0;
|
||||
|
||||
static_call_cond(kvm_x86_pmu_reset)(vcpu);
|
||||
}
|
||||
|
||||
void kvm_pmu_init(struct kvm_vcpu *vcpu)
|
||||
|
|
|
@ -80,24 +80,6 @@ static inline void pmc_write_counter(struct kvm_pmc *pmc, u64 val)
|
|||
pmc->counter &= pmc_bitmask(pmc);
|
||||
}
|
||||
|
||||
static inline void pmc_release_perf_event(struct kvm_pmc *pmc)
|
||||
{
|
||||
if (pmc->perf_event) {
|
||||
perf_event_release_kernel(pmc->perf_event);
|
||||
pmc->perf_event = NULL;
|
||||
pmc->current_config = 0;
|
||||
pmc_to_pmu(pmc)->event_count--;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void pmc_stop_counter(struct kvm_pmc *pmc)
|
||||
{
|
||||
if (pmc->perf_event) {
|
||||
pmc->counter = pmc_read_counter(pmc);
|
||||
pmc_release_perf_event(pmc);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool pmc_is_gp(struct kvm_pmc *pmc)
|
||||
{
|
||||
return pmc->type == KVM_PMC_GP;
|
||||
|
|
|
@ -233,21 +233,6 @@ static void amd_pmu_init(struct kvm_vcpu *vcpu)
|
|||
}
|
||||
}
|
||||
|
||||
static void amd_pmu_reset(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < KVM_AMD_PMC_MAX_GENERIC; i++) {
|
||||
struct kvm_pmc *pmc = &pmu->gp_counters[i];
|
||||
|
||||
pmc_stop_counter(pmc);
|
||||
pmc->counter = pmc->prev_counter = pmc->eventsel = 0;
|
||||
}
|
||||
|
||||
pmu->global_ctrl = pmu->global_status = 0;
|
||||
}
|
||||
|
||||
struct kvm_pmu_ops amd_pmu_ops __initdata = {
|
||||
.hw_event_available = amd_hw_event_available,
|
||||
.pmc_idx_to_pmc = amd_pmc_idx_to_pmc,
|
||||
|
@ -259,7 +244,6 @@ struct kvm_pmu_ops amd_pmu_ops __initdata = {
|
|||
.set_msr = amd_pmu_set_msr,
|
||||
.refresh = amd_pmu_refresh,
|
||||
.init = amd_pmu_init,
|
||||
.reset = amd_pmu_reset,
|
||||
.EVENTSEL_EVENT = AMD64_EVENTSEL_EVENT,
|
||||
.MAX_NR_GP_COUNTERS = KVM_AMD_PMC_MAX_GENERIC,
|
||||
.MIN_NR_GP_COUNTERS = AMD64_NUM_COUNTERS,
|
||||
|
|
|
@ -632,26 +632,6 @@ static void intel_pmu_init(struct kvm_vcpu *vcpu)
|
|||
|
||||
static void intel_pmu_reset(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
|
||||
struct kvm_pmc *pmc = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < KVM_INTEL_PMC_MAX_GENERIC; i++) {
|
||||
pmc = &pmu->gp_counters[i];
|
||||
|
||||
pmc_stop_counter(pmc);
|
||||
pmc->counter = pmc->prev_counter = pmc->eventsel = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < KVM_PMC_MAX_FIXED; i++) {
|
||||
pmc = &pmu->fixed_counters[i];
|
||||
|
||||
pmc_stop_counter(pmc);
|
||||
pmc->counter = pmc->prev_counter = 0;
|
||||
}
|
||||
|
||||
pmu->fixed_ctr_ctrl = pmu->global_ctrl = pmu->global_status = 0;
|
||||
|
||||
intel_pmu_release_guest_lbr_event(vcpu);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue