Received: by 2002:a05:6358:11c7:b0:104:8066:f915 with SMTP id i7csp2994605rwl; Mon, 27 Mar 2023 07:59:05 -0700 (PDT) X-Google-Smtp-Source: AKy350ZVn5ZTHZUaomV3FsgXiphNHMFmStj4BHqWi1lHCccYOpE8G93JFl/ejFpkpO4kgfYxf2q5 X-Received: by 2002:a05:6a20:4a04:b0:df:559a:96dc with SMTP id fr4-20020a056a204a0400b000df559a96dcmr5579697pzb.32.1679929145515; Mon, 27 Mar 2023 07:59:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1679929145; cv=none; d=google.com; s=arc-20160816; b=SkFafbIySSXpjHqw5hKd8tkTIFiIJ2WaiukVOwQ/bWGE4WIk6H2G2KGl2QoauVJ50K jA/Bb39QH/b6URfDN17w+O5rN6wj7GBC2GI6CT5MrcN+cp/nydAknU47Lb/jvWyYq7eU jTt9zowl5hDZU51GXYdFH+V7vL+bB24qJmESiMp8QNxCeI4Yf405wBphmSkUN60IgUbk JwnCsPo1h4rbIy6MtZzDIrD7c7BjLyCoTX2zAoaDPAFwPinI3jwg76qd5Xre++abU4S+ 3kxPMNfPyEWxWm1OR8oGUAvQRf+bXV5Y0lHgXWwTQrVJRdDCVJ8+LSvxINGRUGRVGSu6 KaNg== 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=GcL6+3tvjdTW9fIDzgsbGrc6U5hGI9RcOR9ewIIRrxU=; b=KnUNSXTfPZXcuJYNYuYCZ5uMrm0HGOTqyWuZjiBTfPZ3CA2YCIfER5+7+HsPfvS26R GhV5vBYPsj5P5Dz6VmzAjTZatj38ybH5QZG4CfgZGlA86UvTui6ouTDHvzfNIGuDoNYm 8OAzoP8k+YiBrDO8VBKi7YkdzL3+vguURkPoG7KDpldMt3og8DipBJ8Eia3uztXvjxm5 09nfHNQ0ZsCNeVPUULow+ulMDBMQaO6eKRptYCLuVC8z+JVS07vdjssyFfHZiMsADpoX yzPH67r24vVYM5uOCJbdIE2kaMqNYIS52OIFtSpjWgZbItErVGmR2QYLTd+coWDzQ2Pc D6Kg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=LzcQMdM9; 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 t19-20020aa79473000000b0062d6f6569e1si3481651pfq.135.2023.03.27.07.58.52; Mon, 27 Mar 2023 07:59:05 -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=LzcQMdM9; 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 S232643AbjC0O6k (ORCPT + 99 others); Mon, 27 Mar 2023 10:58:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38062 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232725AbjC0O6i (ORCPT ); Mon, 27 Mar 2023 10:58:38 -0400 Received: from mail-oa1-x30.google.com (mail-oa1-x30.google.com [IPv6:2001:4860:4864:20::30]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 09D1040E7 for ; Mon, 27 Mar 2023 07:58:36 -0700 (PDT) Received: by mail-oa1-x30.google.com with SMTP id 586e51a60fabf-17ebba88c60so9544773fac.3 for ; Mon, 27 Mar 2023 07:58:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; t=1679929115; 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=GcL6+3tvjdTW9fIDzgsbGrc6U5hGI9RcOR9ewIIRrxU=; b=LzcQMdM9A6OT62XULX11p/ZaWBKvoAUOMEBaYR/G/OGaOEJkZaOvm+AITolNSJOWgI XFo3+59nxCia9pcoW0bmAv/uNk1Tnygb36jy/Aj70LJnkrELl5Z8CRmU4OapnR+uTszp nMnYXkHv0r8dLwz/IpPv8/qu08xsyOvEkr10MxXjoS2+INEjvWJ+uCwOqjKFs2V3Y0yQ 0ClU429ty9HawUZuwGM2nHnW/Yni0JU7kIFYLBySzOqvzK8lrplJHs69ZoMr/5bEnNkd BhwLkOOst7Jy20gw7K/JfQkK51TXhjnxZ+6CrC0miEJsfGGSPRI8rFM9K5lx7g763Zau cOrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679929115; 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=GcL6+3tvjdTW9fIDzgsbGrc6U5hGI9RcOR9ewIIRrxU=; b=PjS1uAK174jiJL2AgpfRGTXHL8in1O5uGd2NmUlsMvmZ2lpb3ZeS+0/6FiQ7DkHJbs /4w8sg4f3K/rOeORl7lYp1gBHSUUPOjv6wBwbuyN50ML+UnMCxBM2TzZp1E3zdB7S9NP dFE0lWoDV9LTHtW1k2JB8NYp7smoNwFrvoKQ2T0+pwk/a2/WFjQKYrlEZE/hEhYqgu7N FnWdL/K7PesVEFDwxqziS/XHifOSmG7skVQ6x/VQOlXBmCIsP03Tf8qGz7/QC/YSfGmg +aFS/zbgHEMRejOHKKrmpTlA6z9JDDpzJ9eMY3ttNidIoqgRzcEp912pP+Zin234siFB nYCA== X-Gm-Message-State: AAQBX9c2Qmrgq6W04vieGvNWlGrJbXgV4B7fVJ0TledVk7PlF3e/lLS7 5DGk4Lm8HscfRpnGOv8qC7zBgM5IWnncSCs2NEi/2g== X-Received: by 2002:a05:6871:4d03:b0:17d:1287:1b5c with SMTP id ug3-20020a0568714d0300b0017d12871b5cmr4109751oab.9.1679929115028; Mon, 27 Mar 2023 07:58:35 -0700 (PDT) MIME-Version: 1.0 References: <20230321112742.25255-1-likexu@tencent.com> In-Reply-To: From: Jim Mattson Date: Mon, 27 Mar 2023 07:58:23 -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 Mon, Mar 27, 2023 at 12:47=E2=80=AFAM Like Xu = wrote: > > On 25/3/2023 7:19 am, Jim Mattson wrote: > > On Tue, Mar 21, 2023 at 4:28=E2=80=AFAM Like Xu wrote: > >> > >> 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 tr= ack > >> 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/kv= m_host.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= avoid > >> * 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 k= vm_pmu *pmu, u32 msr, > >> return NULL; > >> } > >> > >> +static inline bool fixed_ctr_is_supported(struct kvm_pmu *pmu, unsign= ed 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= kvm_pmu *pmu, u32 msr) > >> u32 index =3D array_index_nospec(msr - base, > >> pmu->nr_arch_fixed_cou= nters); > >> > >> + 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_c= trl; > >> 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_vc= pu *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(stru= ct 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= (pmu, idx))) > >> return NULL; > >> *mask &=3D pmu->counter_bitmask[fixed ? KVM_PMC_FIXED : KVM_P= MC_GP]; > >> return &counters[array_index_nospec(idx, num_counters)]; > >> @@ -500,6 +506,9 @@ static void setup_fixed_pmc_eventsel(struct kvm_pm= u *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 *vcp= u) > >> > >> 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 *v= cpu) > >> pmu->available_event_types =3D ~entry->ebx & > >> ((1ull << eax.split.mask_leng= th) - 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. > > This is true in for "Version 5" section, but not mentioned in the CPUID.0= xA section. > I would argue that this is a deliberate omission for the instruction impl= ementation, > as it does use the word "version>1" in the near CPUID.0xA.EDX section. Do you have any evidence to support such an argument? The CPUID field in question was not defined prior to PMU version 5. (Does anyone from Intel want to chime in?) > For virtualised use, this feature offers a kind of flexibility as users c= an > enable part of > the fixed counters, don't you think? Or maybe you're more looking forward= to the > patch set that raises the vPMU version number from 2 to 5, that part of t= he code > was already in my tree some years ago. I would not be surprised if a guest OS checked for PMU version 5 before consulting the CPUID fields defined in PMU version 5. Does Linux even consult the fixed counter bitmask field today? I'd love to see KVM virtualize PMU version 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 > fixed counters - 1> 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_va= lid_pmc_idx); > >> + pmu->fixed_ctr_ctrl_mask &=3D ~(0xbull << (i *= 4)); > >> + counter_mask &=3D ~BIT_ULL(INTEL_PMC_MAX_GENER= IC + i); > >> + } > >> edx.split.bit_width_fixed =3D min_t(int, edx.split.bi= t_width_fixed, > >> kvm_pmu_cap.bit_wid= th_fixed); > >> pmu->counter_bitmask[KVM_PMC_FIXED] =3D > >> @@ -565,10 +586,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vc= pu) > >> 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 *vc= pu) > >> pmu->raw_event_mask |=3D (HSW_IN_TX|HSW_IN_TX_CHECKPO= INTED); > >> } > >> > >> - 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 *vcp= u) > >> pmu->pebs_enable_mask =3D counter_mask; > >> pmu->reserved_bits &=3D ~ICL_EVENTSEL_ADAPTIV= E; > >> 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_FIXE= D + i * 4)); > >> } > >> > >> base-commit: d8708b80fa0e6e21bc0c9e7276ad0bccef73b6e7 > >> -- > >> 2.40.0 > >>