Received: by 2002:a05:6358:11c7:b0:104:8066:f915 with SMTP id i7csp1817720rwl; Fri, 24 Mar 2023 16:21:42 -0700 (PDT) X-Google-Smtp-Source: AK7set+u5QmfHVVAr2Mamd5VbnDa1mooVrQVrl5FNI9snjAGPCr4nHAkPlILxfdWQkxqBeLdVKPG X-Received: by 2002:a05:6a20:6692:b0:da:4e05:768 with SMTP id o18-20020a056a20669200b000da4e050768mr4753150pzh.38.1679700101786; Fri, 24 Mar 2023 16:21:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1679700101; cv=none; d=google.com; s=arc-20160816; b=BqiZS9grz/XEjkdIEMR7iM1YODs1fnP0LFvahCEKIE0q5PBz6I7lp+VOsUYnZ5RmmQ KW+yH7nSWe8frjoatfkuphcSkagiEIlsmTlyeQXotdj8UIBjFHjXiqO2HmsJgxduJPch AEFY9HpRyubVQYlC1dlEBb41fiqch8Fh/mWoDwrTKAH8HM8HaIFE9I/TyDThaRsaf4X5 JUu+pJWwnJ9eorDZq7myaCyXz7dD8apKscjiuz6dAcLeNBx6Kv9r93iZKrKgc7y2lrUe wEht80quHbveDIrIdf4jdibWtMCQX5gKmGaLHMxlFyxtxJYCWVoJqZ+lCr/uIqbBjhdD cBmA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:cc:to:subject :message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=jaHai1v0U5AvJP0zHlY3uELem034mHhVuUlCm/v+PZY=; b=TRlzgmAHG9giajxAZZSleZt7vl6hoI3+et3oaNt4d93VcuU2HGV9+GaJYKIu/zT/Y3 Y5w7HJvlSGe4uau1CwFbeg0ikJGdF/8rYUV8hoX5Gp79tKEtnbY9yP9nbd+jUzrwkk17 hUY0eQpINc3M3NygB3gkRa97OKyV4TO697Sn1nJZ//HleNCma11pVY1Kupaq658Ft41N rt2mFIHHWBpq0U12MgWuAfjyaVfR+HWN+nDUN3vNSetZlgUyv9J57PkjpAsJ3reY3Obk bhtMh36ggz3bYOtQuS8JX+us+hhu1QQTiFfbJMKh7GzRbVjjQ0Nwwx2fBiO8gv9OK7hr /XTA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=kd40Mgzj; 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 w133-20020a62828b000000b005e2c94ead4csi21101035pfd.121.2023.03.24.16.21.29; Fri, 24 Mar 2023 16:21:41 -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=20210112 header.b=kd40Mgzj; 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 S230350AbjCXXUG (ORCPT + 99 others); Fri, 24 Mar 2023 19:20:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50254 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229472AbjCXXUE (ORCPT ); Fri, 24 Mar 2023 19:20:04 -0400 Received: from mail-oi1-x234.google.com (mail-oi1-x234.google.com [IPv6:2607:f8b0:4864:20::234]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3C50819F3C for ; Fri, 24 Mar 2023 16:20:03 -0700 (PDT) Received: by mail-oi1-x234.google.com with SMTP id r84so1140776oih.11 for ; Fri, 24 Mar 2023 16:20:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; t=1679700002; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=jaHai1v0U5AvJP0zHlY3uELem034mHhVuUlCm/v+PZY=; b=kd40MgzjAGB6PP0D06mfxR4Tcqv9DmL//VbnljqoS/wxAOZLUyWtpX+I9IvXyXGWIF hMPwok/UFrJGDzJj9P1QtSriXPbPoVFXkiWsAuOsAY2OqhRL3AAkN1YbjH+BNBr1wySy Y9Qa8MZPQJFMq662bl/ae+pYHHi2WLYrsCCWCwjqqKxDUXTnnl/6fNvxSDQQyygxqf4X c7K/PggU9YSDQcbxIt7XwZ8MNJg6gTlRXhlGfAIqIQ96/19h5addx4a7WNqLOYDZfnW4 Lq9Wk91Yf71Ue3SmGb4P6lPnVOsQBecxGJ7VdvwqeIDNTdUCPXYc9F6bJLXJ7kZYY0wX crbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679700002; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jaHai1v0U5AvJP0zHlY3uELem034mHhVuUlCm/v+PZY=; b=D3J5d8LInMxERSuYuMOtiEc98Ap0xp5zfB/rDJD+jp+pRMKbYfyp8YRB7A5RXquB4+ tUH4WcGjKcSnSghZfgKoaBg0SKQ6/SzNX9wCpAi0TUjbFBhfUFdDKhKG77AtjcbNTPqs RMx+Bip19+7GcojlXSFt1xg92sZAcoJ3cEu0mHrpMVO1xZjt3IarTVOak5OeOpaREIjc BHrdtqsxP+B9/DQ1h7d/opbozTumaPhiR7YibR9/bEGwzovYE20rLPPoR3fQpIvCD/FM XE4HsL2XCDS2mIIYTCLICrTjWI7/yLRXwXSqLVQO/knaA412OVRs6D8dOsUGeqvcffk9 Smew== X-Gm-Message-State: AO0yUKXlnB+ENZ85CcnOPaUFFJ51oJHq+PmUeBugGtf27IkzhFGeunnd OQ65JQh6KUihHCZr3+T6sQau/to8gNvbqzP67ai5bA== X-Received: by 2002:a05:6808:615:b0:386:9bb5:a786 with SMTP id y21-20020a056808061500b003869bb5a786mr996112oih.9.1679700002267; Fri, 24 Mar 2023 16:20:02 -0700 (PDT) MIME-Version: 1.0 References: <20230321112742.25255-1-likexu@tencent.com> In-Reply-To: <20230321112742.25255-1-likexu@tencent.com> From: Jim Mattson Date: Fri, 24 Mar 2023 16:19:51 -0700 Message-ID: Subject: Re: [PATCH] KVM: x86/pmu: Add Intel PMU supported fixed counters bit mask To: Like Xu Cc: Sean Christopherson , Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-15.7 required=5.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,ENV_AND_HDR_SPF_MATCH, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL, USER_IN_DEF_SPF_WL autolearn=unavailable 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 Tue, Mar 21, 2023 at 4:28=E2=80=AFAM Like Xu w= rote: > > From: Like Xu > > Per Intel SDM, fixed-function performance counter 'i' is supported if: > > FxCtr[i]_is_supported :=3D ECX[i] || (EDX[4:0] > i); > > which means that the KVM user space can use EDX to limit the number of > fixed counters and at the same time, using ECX to enable part of other > KVM supported fixed counters. > > Add a bitmap (instead of always checking the vcpu's CPUIDs) to keep track > of the guest available fixed counters and perform the semantic checks. > > Signed-off-by: Like Xu > --- > arch/x86/include/asm/kvm_host.h | 2 ++ > arch/x86/kvm/pmu.h | 8 +++++ > arch/x86/kvm/vmx/pmu_intel.c | 53 +++++++++++++++++++++------------ > 3 files changed, 44 insertions(+), 19 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_h= ost.h > index a45de1118a42..14689e583127 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -565,6 +565,8 @@ struct kvm_pmu { > */ > bool need_cleanup; > > + DECLARE_BITMAP(supported_fixed_pmc_idx, KVM_PMC_MAX_FIXED); > + > /* > * The total number of programmed perf_events and it helps to avo= id > * redundant check before cleanup if guest don't use vPMU at all. > diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h > index be62c16f2265..9f4504e5e9d5 100644 > --- a/arch/x86/kvm/pmu.h > +++ b/arch/x86/kvm/pmu.h > @@ -111,6 +111,11 @@ static inline struct kvm_pmc *get_gp_pmc(struct kvm_= pmu *pmu, u32 msr, > return NULL; > } > > +static inline bool fixed_ctr_is_supported(struct kvm_pmu *pmu, unsigned = int idx) > +{ > + return test_bit(idx, pmu->supported_fixed_pmc_idx); > +} > + > /* returns fixed PMC with the specified MSR */ > static inline struct kvm_pmc *get_fixed_pmc(struct kvm_pmu *pmu, u32 msr= ) > { > @@ -120,6 +125,9 @@ static inline struct kvm_pmc *get_fixed_pmc(struct kv= m_pmu *pmu, u32 msr) > u32 index =3D array_index_nospec(msr - base, > pmu->nr_arch_fixed_counter= s); > > + if (!fixed_ctr_is_supported(pmu, index)) > + return NULL; > + > return &pmu->fixed_counters[index]; > } > > diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c > index e8a3be0b9df9..12f4b2fe7756 100644 > --- a/arch/x86/kvm/vmx/pmu_intel.c > +++ b/arch/x86/kvm/vmx/pmu_intel.c > @@ -43,13 +43,16 @@ static int fixed_pmc_events[] =3D {1, 0, 7}; > static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data) > { > struct kvm_pmc *pmc; > - u8 old_fixed_ctr_ctrl =3D pmu->fixed_ctr_ctrl; > + u8 new_ctrl, old_ctrl, old_fixed_ctr_ctrl =3D pmu->fixed_ctr_ctrl= ; > int i; > > pmu->fixed_ctr_ctrl =3D data; > for (i =3D 0; i < pmu->nr_arch_fixed_counters; i++) { > - u8 new_ctrl =3D fixed_ctrl_field(data, i); > - u8 old_ctrl =3D fixed_ctrl_field(old_fixed_ctr_ctrl, i); > + if (!fixed_ctr_is_supported(pmu, i)) > + continue; > + > + new_ctrl =3D fixed_ctrl_field(data, i); > + old_ctrl =3D fixed_ctrl_field(old_fixed_ctr_ctrl, i); > > if (old_ctrl =3D=3D new_ctrl) > continue; > @@ -125,6 +128,9 @@ static bool intel_is_valid_rdpmc_ecx(struct kvm_vcpu = *vcpu, unsigned int idx) > > idx &=3D ~(3u << 30); > > + if (fixed && !fixed_ctr_is_supported(pmu, idx)) > + return false; > + > return fixed ? idx < pmu->nr_arch_fixed_counters > : idx < pmu->nr_arch_gp_counters; > } > @@ -145,7 +151,7 @@ static struct kvm_pmc *intel_rdpmc_ecx_to_pmc(struct = kvm_vcpu *vcpu, > counters =3D pmu->gp_counters; > num_counters =3D pmu->nr_arch_gp_counters; > } > - if (idx >=3D num_counters) > + if (idx >=3D num_counters || (fixed && !fixed_ctr_is_supported(pm= u, idx))) > return NULL; > *mask &=3D pmu->counter_bitmask[fixed ? KVM_PMC_FIXED : KVM_PMC_G= P]; > return &counters[array_index_nospec(idx, num_counters)]; > @@ -500,6 +506,9 @@ static void setup_fixed_pmc_eventsel(struct kvm_pmu *= pmu) > int i; > > for (i =3D 0; i < pmu->nr_arch_fixed_counters; i++) { > + if (!fixed_ctr_is_supported(pmu, i)) > + continue; > + > pmc =3D &pmu->fixed_counters[i]; > event =3D fixed_pmc_events[array_index_nospec(i, size)]; > pmc->eventsel =3D (intel_arch_events[event].unit_mask << = 8) | > @@ -520,6 +529,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) > > pmu->nr_arch_gp_counters =3D 0; > pmu->nr_arch_fixed_counters =3D 0; > + bitmap_zero(pmu->supported_fixed_pmc_idx, KVM_PMC_MAX_FIXED); > pmu->counter_bitmask[KVM_PMC_GP] =3D 0; > pmu->counter_bitmask[KVM_PMC_FIXED] =3D 0; > pmu->version =3D 0; > @@ -551,13 +561,24 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu= ) > pmu->available_event_types =3D ~entry->ebx & > ((1ull << eax.split.mask_length) = - 1); > > - if (pmu->version =3D=3D 1) { > - pmu->nr_arch_fixed_counters =3D 0; > - } else { > + counter_mask =3D ~(BIT_ULL(pmu->nr_arch_gp_counters) - 1); > + bitmap_set(pmu->all_valid_pmc_idx, 0, pmu->nr_arch_gp_counters); > + > + if (pmu->version > 1) { > pmu->nr_arch_fixed_counters =3D > - min3(ARRAY_SIZE(fixed_pmc_events), > - (size_t) edx.split.num_counters_fixed, > - (size_t)kvm_pmu_cap.num_counters_fixed); > + min_t(int, ARRAY_SIZE(fixed_pmc_events), > + kvm_pmu_cap.num_counters_fixed); > + for (i =3D 0; i < pmu->nr_arch_fixed_counters; i++) { > + /* FxCtr[i]_is_supported :=3D CPUID.0xA.ECX[i] ||= (EDX[4:0] > i) */ This is true only when pmu->version >=3D 5. From the SDM, volume 3, section 20.2.5 Architectural Performance Monitoring Version 5: With Architectural Performance Monitoring Version 5, register CPUID.0AH.ECX indicates Fixed Counter enumeration. It is a bit mask which enumerates the supported Fixed Counters in a processor. If bit 'i' is set, it implies that Fixed Counter 'i' is supported. Software is recommended to use the following logic to check if a Fixed Counter is supported on a given processor: FxCtr[i]_is_supported :=3D ECX[i] || (EDX[4:0] > i); Prior to PMU version 5, all fixed counters from 0 through are supported. > + if (!(entry->ecx & BIT_ULL(i) || > + edx.split.num_counters_fixed > i)) > + continue; > + > + set_bit(i, pmu->supported_fixed_pmc_idx); > + set_bit(INTEL_PMC_MAX_GENERIC + i, pmu->all_valid= _pmc_idx); > + pmu->fixed_ctr_ctrl_mask &=3D ~(0xbull << (i * 4)= ); > + counter_mask &=3D ~BIT_ULL(INTEL_PMC_MAX_GENERIC = + i); > + } > edx.split.bit_width_fixed =3D min_t(int, edx.split.bit_wi= dth_fixed, > kvm_pmu_cap.bit_width_f= ixed); > pmu->counter_bitmask[KVM_PMC_FIXED] =3D > @@ -565,10 +586,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) > setup_fixed_pmc_eventsel(pmu); > } > > - for (i =3D 0; i < pmu->nr_arch_fixed_counters; i++) > - pmu->fixed_ctr_ctrl_mask &=3D ~(0xbull << (i * 4)); > - counter_mask =3D ~(((1ull << pmu->nr_arch_gp_counters) - 1) | > - (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC= _IDX_FIXED)); > pmu->global_ctrl_mask =3D counter_mask; > pmu->global_ovf_ctrl_mask =3D pmu->global_ctrl_mask > & ~(MSR_CORE_PERF_GLOBAL_OVF_CTRL_OVF_BUF | > @@ -585,11 +602,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) > pmu->raw_event_mask |=3D (HSW_IN_TX|HSW_IN_TX_CHECKPOINTE= D); > } > > - bitmap_set(pmu->all_valid_pmc_idx, > - 0, pmu->nr_arch_gp_counters); > - bitmap_set(pmu->all_valid_pmc_idx, > - INTEL_PMC_MAX_GENERIC, pmu->nr_arch_fixed_counters); > - > perf_capabilities =3D vcpu_get_perf_capabilities(vcpu); > if (cpuid_model_is_consistent(vcpu) && > (perf_capabilities & PMU_CAP_LBR_FMT)) > @@ -605,6 +617,9 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) > pmu->pebs_enable_mask =3D counter_mask; > pmu->reserved_bits &=3D ~ICL_EVENTSEL_ADAPTIVE; > for (i =3D 0; i < pmu->nr_arch_fixed_counters; i+= +) { > + if (!fixed_ctr_is_supported(pmu, i)) > + continue; > + > pmu->fixed_ctr_ctrl_mask &=3D > ~(1ULL << (INTEL_PMC_IDX_FIXED + = i * 4)); > } > > base-commit: d8708b80fa0e6e21bc0c9e7276ad0bccef73b6e7 > -- > 2.40.0 >