Received: by 2002:a05:6358:3188:b0:123:57c1:9b43 with SMTP id q8csp22924066rwd; Fri, 30 Jun 2023 14:58:11 -0700 (PDT) X-Google-Smtp-Source: APBJJlE8hNt5udZ13KDFYAC1IkYGApreNgUDCY9pFIYLzIn/1TmQgZiWZdhyJAfbXe0Z40I2Y1dn X-Received: by 2002:a17:90a:bc81:b0:261:38ca:3c48 with SMTP id x1-20020a17090abc8100b0026138ca3c48mr3473798pjr.11.1688162291156; Fri, 30 Jun 2023 14:58:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1688162291; cv=none; d=google.com; s=arc-20160816; b=ieQTBzCu3ChRYZTOa6md8v08t8BMCkW0VkuhVHqerAiJHAb4wdZ2RoUst/YA9Z9HMQ 6s/mXtQ/V6Fh6R2j03T36bDHt+x4mB4+i6eapm8byDhn79tGHdNn9nCTPplP69zZvntS B/b/rtyrEPmILG2Pr7SRwBKLAxbGAY27w5p7MjD5HJT95lgNnMMB+esbrL6LyeNvqxTF XKVre4DnfS8fmR5fsFXBK8ByFjiXAHL99QX9hE26oZVrOIvNa5zudSJkhGUXRYuPOSrd tGpBxCir0OBalFf6FnZBBmPbIOhDrBlQTneGjNUewn3ZNouNPcjIEirHp+8moZfph4Vu hIvA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=wODLWlyjETqxXtTl1QZCmIIk5mYTcllzfcsmN+hcIOo=; fh=TS2mxc8wESXTOKCDA58PXnuPWcD7HA1DAOoimABCKxQ=; b=tUsklKA7C1kYonf2kxblSrN1bqdDZA2Isd5ID62tvLU3NrUeQm3b1VdHa5Cwhn7Upk l3ZnEiV3uaU2n6WssN3p9Ttn/ZaS5sNOXBWx97T8Jens6TbRT69lFSSXf/rAz7lR7Ix1 kVWlbFD6nXoXY0jx/WElytDCMypnRYYD3Ne7VtBwDJG3Tq8cSm9XzJGjVnoD+JSVW+vi UGWVjHkNvYBx0pRCQn7K/8+WIm6WYvDHK/pY5QzGtg+1BGnbWJTORzne9OIBa8Vt8CRn lxsuvSPrShvU6MQUAkENSC8KS4K0mPFx7FQstBrYrNY6Sihod2i30FvPRlIElDU8ozFe T2CQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=6ZbWBuAh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id l6-20020a170903120600b001ac9ab8539csi14331967plh.77.2023.06.30.14.57.55; Fri, 30 Jun 2023 14:58:11 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=6ZbWBuAh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232382AbjF3V0H (ORCPT + 99 others); Fri, 30 Jun 2023 17:26:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36880 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232269AbjF3V0G (ORCPT ); Fri, 30 Jun 2023 17:26:06 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 210F42686 for ; Fri, 30 Jun 2023 14:26:04 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id 98e67ed59e1d1-262e9468034so2329086a91.0 for ; Fri, 30 Jun 2023 14:26:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1688160363; x=1690752363; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=wODLWlyjETqxXtTl1QZCmIIk5mYTcllzfcsmN+hcIOo=; b=6ZbWBuAhu9aoPVlRjLwPVX8szYQBDPV27fWJHbFgK20pkuVUUChvdExjQpiey7bhUW veHLVc7nKJ5vhtXQNc23UXBU6XYT/aKsbPLUWryhNiBnhZh5WBfFgF0cwwjfsordJrVt q/X5ipeFRUY49MC+Y4oJcz9//BQ4mV4DLoIE9EGDG7uqEcR4sb35yMHDbDbYGetPO1Le /zgWm8F7IuE22q5WFoYllmWsHq/KwNorvtHZKpi9yuRoEzf7PWo0aLl7e2GTDZ0MPWwF hMIM0uj3+hgjp7Deoz877jVcRNA3A9Dm9FDJg5cNKxSsUFf703DkuuGl9rymbcraXrlf vOcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688160363; x=1690752363; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=wODLWlyjETqxXtTl1QZCmIIk5mYTcllzfcsmN+hcIOo=; b=N14jRTykISVBpcNN7iqmFDDjLzooxp589xy227szzhxf22w5GMuxDjxw50JkLstTLA 8xpsZQKOOvMw7htTUQ/fVzRCzfjE9kP+w7WePnwRt4WWmZ4mQZZXBjMnzz4AUPFDXj78 H8Br0Z+0nmydrVbGC9XyuavMJiQMwRkmn6ZBW/a3nrnQORWeEICe3A02HIyZeO3K36Hu IU0B2Jyq6UDa3Zo3dn3CFTaj6WrFK3B0N1MLeZz0hcG9hOhQrwQvRny42b2WboWFv8sL SihQVKLRlAnsNNscOSgiGFBr21IbwZmEzQHBsdMU2rCIHAuafw1gRQPpwikGckrf0fis Mhaw== X-Gm-Message-State: ABy/qLbgJliszO40SVdFwHoJskdNDCuAF0JwgrCovI9Rjqm/G9GQ0UZ9 KB3ZBU18iWzqpuNX+/vLCptLzlwy63U= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a17:90b:e03:b0:262:d099:5e0d with SMTP id ge3-20020a17090b0e0300b00262d0995e0dmr2384948pjb.0.1688160363569; Fri, 30 Jun 2023 14:26:03 -0700 (PDT) Date: Fri, 30 Jun 2023 14:26:02 -0700 In-Reply-To: Mime-Version: 1.0 References: <20230504120042.785651-1-rkagan@amazon.de> Message-ID: Subject: Re: [PATCH] KVM: x86: vPMU: truncate counter value to allowed width From: Sean Christopherson To: Roman Kagan , Jim Mattson , Paolo Bonzini , Eric Hankland , kvm@vger.kernel.org, Dave Hansen , Like Xu , x86@kernel.org, Thomas Gleixner , linux-kernel@vger.kernel.org, "H. Peter Anvin" , Borislav Petkov , Ingo Molnar , Mingwei Zhang Content-Type: text/plain; charset="us-ascii" X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Jun 30, 2023, Sean Christopherson wrote: > On Fri, Jun 30, 2023, Roman Kagan wrote: > > On Fri, Jun 30, 2023 at 07:28:29AM -0700, Sean Christopherson wrote: > > > On Fri, Jun 30, 2023, Roman Kagan wrote: > > > > On Thu, Jun 29, 2023 at 05:11:06PM -0700, Sean Christopherson wrote: > > > > > @@ -74,6 +74,14 @@ static inline u64 pmc_read_counter(struct kvm_pmc *pmc) > > > > > return counter & pmc_bitmask(pmc); > > > > > } > > > > > > > > > > +static inline void pmc_write_counter(struct kvm_pmc *pmc, u64 val) > > > > > +{ > > > > > + if (pmc->perf_event && !pmc->is_paused) > > > > > + perf_event_set_count(pmc->perf_event, val); > > > > > + > > > > > + pmc->counter = val; > > > > > > > > Doesn't this still have the original problem of storing wider value than > > > > allowed? > > > > > > Yes, this was just to fix the counter offset weirdness. My plan is to apply your > > > patch on top. Sorry for not making that clear. > > > > Ah, got it, thanks! > > > > Also I'm now chasing a problem that we occasionally see > > > > [3939579.462832] Uhhuh. NMI received for unknown reason 30 on CPU 43. > > [3939579.462836] Do you have a strange power saving mode enabled? > > [3939579.462836] Dazed and confused, but trying to continue > > > > in the guests when perf is used. These messages disappear when > > 9cd803d496e7 ("KVM: x86: Update vPMCs when retiring instructions") is > > reverted. I haven't yet figured out where exactly the culprit is. > > Can you reverting de0f619564f4 ("KVM: x86/pmu: Defer counter emulated overflow > via pmc->prev_counter")? I suspect the problem is the prev_counter mess. Ugh, yeah, de0f619564f4 created a bit of a mess. The underlying issue that it was solving is that perf_event_read_value() and friends might sleep (yay mutex), and so can't be called from KVM's fastpath (IRQs disabled). However, detecting overflow requires reading perf_event_read_value() to gather the accumulated count from the hardware event in order to add it to the emulated count from software. E.g. if pmc->counter is X and the perf event counter is Y, KVM needs to factor in Y because X+Y+1 might overflow even if X+1 does not. Trying to snapshot the previous counter value is a bit of a mess. It could probably made to work, but it's hard to reason about what the snapshot actually contains and when it should be cleared, especially when factoring in the wrapping logic. Rather than snapshot the previous counter, I think it makes sense to: 1) Track the number of emulated counter events 2) Accumulate and reset the counts from perf_event and emulated_counter into pmc->counter when pausing the PMC 3) Pause and reprogram the PMC on writes (instead of the current approach of blindly updating the sample period) 4) Pause the counter when stopping the perf_event to ensure pmc->counter is fresh (instead of manually updating pmc->counter) IMO, that yields more intuitive logic, and makes it easier to reason about correctness since the behavior is easily define: pmc->counter holds the counts that have been gathered and processed, perf_event and emulated_counter hold outstanding counts on top. E.g. on a WRMSR to the counter, both the emulated counter and the hardware counter are reset, because whatever counts existed previously are irrelevant. Pausing the counter _might_ make WRMSR slower, but we need to get this all functionally correct before worrying too much about performance. Diff below for what I'm thinking (needs to be split into multiple patches). It's *very* lightly tested. I'm about to disappear for a week, I'll pick this back up when I get return. In the meantime, any testing and/or input would be much appreciated! --- arch/x86/include/asm/kvm-x86-pmu-ops.h | 2 +- arch/x86/include/asm/kvm_host.h | 11 ++- arch/x86/kvm/pmu.c | 94 ++++++++++++++++++++++---- arch/x86/kvm/pmu.h | 53 +++------------ arch/x86/kvm/svm/pmu.c | 19 +----- arch/x86/kvm/vmx/pmu_intel.c | 26 +------ 6 files changed, 103 insertions(+), 102 deletions(-) diff --git a/arch/x86/include/asm/kvm-x86-pmu-ops.h b/arch/x86/include/asm/kvm-x86-pmu-ops.h index 6c98f4bb4228..058bc636356a 100644 --- a/arch/x86/include/asm/kvm-x86-pmu-ops.h +++ b/arch/x86/include/asm/kvm-x86-pmu-ops.h @@ -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) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 28bd38303d70..337f5e1da57c 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -492,8 +492,17 @@ struct kvm_pmc { u8 idx; bool is_paused; bool intr; + /* + * Value of the PMC counter that has been gathered from the associated + * perf_event and from emulated_counter. This is *not* the current + * value as seen by the guest or userspace. + */ u64 counter; - u64 prev_counter; + /* + * PMC events triggered by KVM emulation that haven't been fully + * procssed, e.g. haven't undergone overflow detection. + */ + u64 emulated_counter; u64 eventsel; struct perf_event *perf_event; struct kvm_vcpu *vcpu; diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index bf653df86112..472e45f5993f 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -148,9 +148,9 @@ static void kvm_perf_overflow(struct perf_event *perf_event, struct kvm_pmc *pmc = perf_event->overflow_handler_context; /* - * Ignore overflow events for counters that are scheduled to be - * reprogrammed, e.g. if a PMI for the previous event races with KVM's - * handling of a related guest WRMSR. + * Ignore asynchronous overflow events for counters that are scheduled + * to be reprogrammed, e.g. if a PMI for the previous event races with + * KVM's handling of a related guest WRMSR. */ if (test_and_set_bit(pmc->idx, pmc_to_pmu(pmc)->reprogram_pmi)) return; @@ -182,6 +182,21 @@ static u64 pmc_get_pebs_precise_level(struct kvm_pmc *pmc) return 1; } +static u64 pmc_get_sample_period(struct kvm_pmc *pmc) +{ + u64 sample_period = (-pmc->counter) & pmc_bitmask(pmc); + + /* + * Verify pmc->counter is fresh, i.e. that the perf event is paused and + * emulated events have been gathered. + */ + WARN_ON_ONCE(pmc->emulated_counter || (pmc->perf_event && !pmc->is_paused)); + + if (!sample_period) + sample_period = pmc_bitmask(pmc) + 1; + return sample_period; +} + static int pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type, u64 config, bool exclude_user, bool exclude_kernel, bool intr) @@ -200,7 +215,7 @@ static int pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type, u64 config, }; bool pebs = test_bit(pmc->idx, (unsigned long *)&pmu->pebs_enable); - attr.sample_period = get_sample_period(pmc, pmc->counter); + attr.sample_period = pmc_get_sample_period(pmc); if ((attr.config & HSW_IN_TX_CHECKPOINTED) && guest_cpuid_is_intel(pmc->vcpu)) { @@ -238,13 +253,19 @@ static int pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type, u64 config, static void pmc_pause_counter(struct kvm_pmc *pmc) { - u64 counter = pmc->counter; + /* + * Accumulate emulated events, even if the PMC was already paused, e.g. + * if KVM emulated an event after a WRMSR, but before reprogramming, or + * if KVM couldn't create a perf event. + */ + u64 counter = pmc->counter + pmc->emulated_counter; - if (!pmc->perf_event || pmc->is_paused) - return; + pmc->emulated_counter = 0; /* update counter, reset event value to avoid redundant accumulation */ - counter += perf_event_pause(pmc->perf_event, true); + if (pmc->perf_event && !pmc->is_paused) + counter += perf_event_pause(pmc->perf_event, true); + pmc->counter = counter & pmc_bitmask(pmc); pmc->is_paused = true; } @@ -256,8 +277,7 @@ static bool pmc_resume_counter(struct kvm_pmc *pmc) /* recalibrate sample period and check if it's accepted by perf core */ if (is_sampling_event(pmc->perf_event) && - perf_event_period(pmc->perf_event, - get_sample_period(pmc, pmc->counter))) + perf_event_period(pmc->perf_event, pmc_get_sample_period(pmc))) return false; if (test_bit(pmc->idx, (unsigned long *)&pmc_to_pmu(pmc)->pebs_enable) != @@ -395,6 +415,32 @@ static bool check_pmu_event_filter(struct kvm_pmc *pmc) return is_fixed_event_allowed(filter, pmc->idx); } +void pmc_write_counter(struct kvm_pmc *pmc, u64 val) +{ + pmc_pause_counter(pmc); + pmc->counter = val & pmc_bitmask(pmc); + kvm_pmu_request_counter_reprogram(pmc); +} +EXPORT_SYMBOL_GPL(pmc_write_counter); + +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_pause_counter(pmc); + pmc_release_perf_event(pmc); + } +} + static bool pmc_event_is_allowed(struct kvm_pmc *pmc) { return pmc_is_globally_enabled(pmc) && pmc_speculative_in_use(pmc) && @@ -404,6 +450,7 @@ static bool pmc_event_is_allowed(struct kvm_pmc *pmc) static void reprogram_counter(struct kvm_pmc *pmc) { struct kvm_pmu *pmu = pmc_to_pmu(pmc); + u64 prev_counter = pmc->counter; u64 eventsel = pmc->eventsel; u64 new_config = eventsel; u8 fixed_ctr_ctrl; @@ -413,7 +460,7 @@ static void reprogram_counter(struct kvm_pmc *pmc) if (!pmc_event_is_allowed(pmc)) goto reprogram_complete; - if (pmc->counter < pmc->prev_counter) + if (pmc->counter < prev_counter) __kvm_perf_overflow(pmc, false); if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL) @@ -453,7 +500,6 @@ static void reprogram_counter(struct kvm_pmc *pmc) reprogram_complete: clear_bit(pmc->idx, (unsigned long *)&pmc_to_pmu(pmc)->reprogram_pmi); - pmc->prev_counter = 0; } void kvm_pmu_handle_event(struct kvm_vcpu *vcpu) @@ -678,9 +724,28 @@ void kvm_pmu_refresh(struct kvm_vcpu *vcpu) void kvm_pmu_reset(struct kvm_vcpu *vcpu) { struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); + struct kvm_pmc *pmc; + int i; irq_work_sync(&pmu->irq_work); - static_call(kvm_x86_pmu_reset)(vcpu); + + 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) @@ -727,8 +792,7 @@ void kvm_pmu_destroy(struct kvm_vcpu *vcpu) static void kvm_pmu_incr_counter(struct kvm_pmc *pmc) { - pmc->prev_counter = pmc->counter; - pmc->counter = (pmc->counter + 1) & pmc_bitmask(pmc); + pmc->emulated_counter++; kvm_pmu_request_counter_reprogram(pmc); } diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index 7d9ba301c090..0ac60ffae944 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -55,6 +55,12 @@ static inline bool kvm_pmu_has_perf_global_ctrl(struct kvm_pmu *pmu) return pmu->version > 1; } +static inline void kvm_pmu_request_counter_reprogram(struct kvm_pmc *pmc) +{ + set_bit(pmc->idx, pmc_to_pmu(pmc)->reprogram_pmi); + kvm_make_request(KVM_REQ_PMU, pmc->vcpu); +} + static inline u64 pmc_bitmask(struct kvm_pmc *pmc) { struct kvm_pmu *pmu = pmc_to_pmu(pmc); @@ -66,31 +72,17 @@ static inline u64 pmc_read_counter(struct kvm_pmc *pmc) { u64 counter, enabled, running; - counter = pmc->counter; + counter = pmc->counter + pmc->emulated_counter; + if (pmc->perf_event && !pmc->is_paused) counter += perf_event_read_value(pmc->perf_event, &enabled, &running); + /* FIXME: Scaling needed? */ return 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); - } -} +void pmc_write_counter(struct kvm_pmc *pmc, u64 val); static inline bool pmc_is_gp(struct kvm_pmc *pmc) { @@ -140,25 +132,6 @@ static inline struct kvm_pmc *get_fixed_pmc(struct kvm_pmu *pmu, u32 msr) return NULL; } -static inline u64 get_sample_period(struct kvm_pmc *pmc, u64 counter_value) -{ - u64 sample_period = (-counter_value) & pmc_bitmask(pmc); - - if (!sample_period) - sample_period = pmc_bitmask(pmc) + 1; - return sample_period; -} - -static inline void pmc_update_sample_period(struct kvm_pmc *pmc) -{ - if (!pmc->perf_event || pmc->is_paused || - !is_sampling_event(pmc->perf_event)) - return; - - perf_event_period(pmc->perf_event, - get_sample_period(pmc, pmc->counter)); -} - static inline bool pmc_speculative_in_use(struct kvm_pmc *pmc) { struct kvm_pmu *pmu = pmc_to_pmu(pmc); @@ -214,12 +187,6 @@ static inline void kvm_init_pmu_capability(const struct kvm_pmu_ops *pmu_ops) KVM_PMC_MAX_FIXED); } -static inline void kvm_pmu_request_counter_reprogram(struct kvm_pmc *pmc) -{ - set_bit(pmc->idx, pmc_to_pmu(pmc)->reprogram_pmi); - kvm_make_request(KVM_REQ_PMU, pmc->vcpu); -} - static inline void reprogram_counters(struct kvm_pmu *pmu, u64 diff) { int bit; diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c index cef5a3d0abd0..b6a7ad4d6914 100644 --- a/arch/x86/kvm/svm/pmu.c +++ b/arch/x86/kvm/svm/pmu.c @@ -160,8 +160,7 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) /* MSR_PERFCTRn */ pmc = get_gp_pmc_amd(pmu, msr, PMU_TYPE_COUNTER); if (pmc) { - pmc->counter += data - pmc_read_counter(pmc); - pmc_update_sample_period(pmc); + pmc_write_counter(pmc, data); return 0; } /* MSR_EVNTSELn */ @@ -233,21 +232,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 +243,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, diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 80c769c58a87..ce49d060bc96 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -406,12 +406,10 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) if (!msr_info->host_initiated && !(msr & MSR_PMC_FULL_WIDTH_BIT)) data = (s64)(s32)data; - pmc->counter += data - pmc_read_counter(pmc); - pmc_update_sample_period(pmc); + pmc_write_counter(pmc, data); break; } else if ((pmc = get_fixed_pmc(pmu, msr))) { - pmc->counter += data - pmc_read_counter(pmc); - pmc_update_sample_period(pmc); + pmc_write_counter(pmc, data); break; } else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) { reserved_bits = pmu->reserved_bits; @@ -603,26 +601,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); } base-commit: 88bb466c9dec4f70d682cf38c685324e7b1b3d60 --