From nobody Fri Sep 19 12:20:34 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 35C2EC433EF for ; Tue, 17 May 2022 15:42:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350314AbiEQPmG (ORCPT ); Tue, 17 May 2022 11:42:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57342 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350486AbiEQPlh (ORCPT ); Tue, 17 May 2022 11:41:37 -0400 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8913240E7C; Tue, 17 May 2022 08:41:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1652802096; x=1684338096; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=lPvj3AuKPLOBCyfjiHi73B4oqME7322FSr1EsA5Gyy8=; b=DSuY6ZQyvCRnB71qfe0TuZS/2Zalm4Hm2HcwRlRk8vfWSXSGaRj4iaJt QiH9JHHNBe00AtU0PLATRxVnZKqkBNGYC3kZL3+ChxEvPeYKmqizvXdel qD5MDWnVIycDlRcaXXPyXQr+asM22KzcoLti0H4zSW0oF2mEAOtCzYlAv 4DnPxByO43/n0ruaSGDIjEtUqAPwqDbTzpae18o8jNy0o8TsAX+UHCFFW KeaBE/QUMJTiJ3sMPqahg+zcYZjn/pwqBvIC7Q2NiISwxiDOGtKGtEJrg SDXRv24JT9kVC+mtdGyAyRM3b2CVFfjVvVZVz6+w+VgJ3ih1eLOy3L9JJ A==; X-IronPort-AV: E=McAfee;i="6400,9594,10350"; a="357632101" X-IronPort-AV: E=Sophos;i="5.91,233,1647327600"; d="scan'208";a="357632101" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 May 2022 08:41:34 -0700 X-IronPort-AV: E=Sophos;i="5.91,233,1647327600"; d="scan'208";a="626533571" Received: from embargo.jf.intel.com ([10.165.9.183]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 May 2022 08:41:33 -0700 From: Yang Weijiang To: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, like.xu.linux@gmail.com, vkuznets@redhat.com, kan.liang@linux.intel.com, wei.w.wang@intel.com, kvm@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Like Xu , Yang Weijiang Subject: [PATCH v12 06/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_DEPTH for guest Arch LBR Date: Tue, 17 May 2022 11:40:50 -0400 Message-Id: <20220517154100.29983-7-weijiang.yang@intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220517154100.29983-1-weijiang.yang@intel.com> References: <20220517154100.29983-1-weijiang.yang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Like Xu The number of Arch LBR entries available is determined by the value in host MSR_ARCH_LBR_DEPTH.DEPTH. The supported LBR depth values are enumerated in CPUID.(EAX=3D01CH, ECX=3D0):EAX[7:0]. For each bit "n" set in this field, the MSR_ARCH_LBR_DEPTH.DEPTH value of "8*(n+1)" is supported. In the first generation of Arch LBR, max entry size is 32, host configures the max size and guest always honors the setting. Write to MSR_ARCH_LBR_DEPTH has side-effect, all LBR entries are reset to 0. Kernel PMU driver can leverage this effect to do fask reset to LBR record MSRs. KVM allows guest to achieve it when Arch LBR records MSRs are passed through to the guest. Signed-off-by: Like Xu Co-developed-by: Yang Weijiang Signed-off-by: Yang Weijiang Reviewed-by: Kan Liang --- arch/x86/include/asm/kvm_host.h | 3 +++ arch/x86/kvm/vmx/pmu_intel.c | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index 9cdc5bbd721f..b6735dcf5a6a 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -547,6 +547,9 @@ struct kvm_pmu { * redundant check before cleanup if guest don't use vPMU at all. */ u8 event_count; + + /* Guest arch lbr depth supported by KVM. */ + u64 kvm_arch_lbr_depth; }; =20 struct kvm_pmu_ops; diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 84b326c4dce9..22d6a869ea4d 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -182,6 +182,12 @@ static bool intel_pmu_is_valid_lbr_msr(struct kvm_vcpu= *vcpu, u32 index) if (!intel_pmu_lbr_is_enabled(vcpu)) return ret; =20 + if (index =3D=3D MSR_ARCH_LBR_DEPTH) { + if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR)) + ret =3D guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR); + return ret; + } + ret =3D (index =3D=3D MSR_LBR_SELECT) || (index =3D=3D MSR_LBR_TOS) || (index >=3D records->from && index < records->from + records->nr) || (index >=3D records->to && index < records->to + records->nr); @@ -343,10 +349,26 @@ static bool intel_pmu_handle_lbr_msrs_access(struct k= vm_vcpu *vcpu, return true; } =20 +/* + * Check if the requested depth value the same as that of host. + * When guest/host depth are different, the handling would be tricky, + * so now only max depth is supported for both host and guest. + */ +static bool arch_lbr_depth_is_valid(struct kvm_vcpu *vcpu, u64 depth) +{ + struct kvm_pmu *pmu =3D vcpu_to_pmu(vcpu); + + if (!kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR)) + return false; + + return (depth =3D=3D pmu->kvm_arch_lbr_depth); +} + static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_i= nfo) { struct kvm_pmu *pmu =3D vcpu_to_pmu(vcpu); struct kvm_pmc *pmc; + struct lbr_desc *lbr_desc =3D vcpu_to_lbr_desc(vcpu); u32 msr =3D msr_info->index; =20 switch (msr) { @@ -371,6 +393,9 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, str= uct msr_data *msr_info) case MSR_PEBS_DATA_CFG: msr_info->data =3D pmu->pebs_data_cfg; return 0; + case MSR_ARCH_LBR_DEPTH: + msr_info->data =3D lbr_desc->records.nr; + return 0; default: if ((pmc =3D get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || (pmc =3D get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) { @@ -397,6 +422,7 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, str= uct msr_data *msr_info) { struct kvm_pmu *pmu =3D vcpu_to_pmu(vcpu); struct kvm_pmc *pmc; + struct lbr_desc *lbr_desc =3D vcpu_to_lbr_desc(vcpu); u32 msr =3D msr_info->index; u64 data =3D msr_info->data; u64 reserved_bits; @@ -452,6 +478,16 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, st= ruct msr_data *msr_info) return 0; } break; + case MSR_ARCH_LBR_DEPTH: + if (!arch_lbr_depth_is_valid(vcpu, data)) + return 1; + lbr_desc->records.nr =3D data; + /* + * Writing depth MSR from guest could either setting the + * MSR or resetting the LBR records with the side-effect. + */ + wrmsrl(MSR_ARCH_LBR_DEPTH, lbr_desc->records.nr); + return 0; default: if ((pmc =3D get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || (pmc =3D get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) { @@ -615,6 +651,18 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) vcpu->arch.ia32_misc_enable_msr |=3D MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL; vcpu->arch.perf_capabilities &=3D ~PERF_CAP_PEBS_MASK; } + + if (!kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR)) + return; + + entry =3D kvm_find_cpuid_entry(vcpu, 28, 0); + if (entry) { + /* + * The depth mask in CPUID is fixed to host supported + * value when userspace sets guest CPUID. + */ + pmu->kvm_arch_lbr_depth =3D fls(entry->eax & 0xff) * 8; + } } =20 static void intel_pmu_init(struct kvm_vcpu *vcpu) --=20 2.27.0