From patchwork Fri Nov 25 04:05:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Yang, Weijiang" X-Patchwork-Id: 25836 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp3796976wrr; Thu, 24 Nov 2022 22:11:30 -0800 (PST) X-Google-Smtp-Source: AA0mqf4isq/x3z+8ynGtIHKr781BpruxinrH+vWZdhXm0D+uYxD9BsleN6mFNeBV01kL5Cy/u7Mm X-Received: by 2002:a63:f53:0:b0:476:e093:b068 with SMTP id 19-20020a630f53000000b00476e093b068mr14081544pgp.325.1669356690360; Thu, 24 Nov 2022 22:11:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669356690; cv=none; d=google.com; s=arc-20160816; b=fsXH2Bp8xd5XaOjoQZi1K1juL9dVgEEbgE1NdO9uwSkRkie5NQCHRUt+o2oq8lWm3Y 0Bi0zpeXx1qhwzAWmuR4aSwvvtm4qY5gKkUqHFFF2akI7B2Ekf8mtDkpbBP9+/zI0C68 Usbkn6oHBEBgLBHxgYynjvH+WUTledTRGcGe5F4bc+xUgraK69InW+P72zussOQiqNZt emXCaKNXLT+iFmzjdkzBahNP1YtITi31RUoNwwyYKwMdO+hqNM791JuEQaNfSY/JFnuk jPMKT0/deOks9Pk4pTjHPvlKlSP/MMJAl3c5b05I+aYu2YJd+Cgt4z0hKWPH5ZHYB9/5 EiBw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=/gxYNqlly5CyZX0pDvwhRZm/tDdsASWs4+lWJBw8ftY=; b=FgeGXTCspuKGqFPAErDL+rBoHedmGLy4uhgTi743alk8zdCL783ssdden9w0tXJ0B/ uuGD2fsybPAVj/8f3N6RciTIh84f79cJp0ZvYX3sTZZGNVXEhzdmzHcn9pu4K6J1H6ee 71yFCkt/bGa2h+drnRdkGL0UD9o8m12opeD3M0Y2nApiF7DY/X1++6deJaRPhEAwBXM0 I5r4+rhhFidHHLk2R2KbHRktSTRyBbbcLoC/mWxWgfjpYMGOFvxBdd+VnFIDW3YZ7RuJ Cub4/6s4JTwBOamwB4d4ZBkXot9XkmL/EHXYrIH7B6V56fbx4TARfYSSiF+dMY/ZIyOj 2M0w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=LTrNjthr; 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=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ot17-20020a17090b3b5100b00213b3144671si7559558pjb.0.2022.11.24.22.11.17; Thu, 24 Nov 2022 22:11:30 -0800 (PST) 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=@intel.com header.s=Intel header.b=LTrNjthr; 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=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229770AbiKYGK2 (ORCPT + 99 others); Fri, 25 Nov 2022 01:10:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46670 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229685AbiKYGKL (ORCPT ); Fri, 25 Nov 2022 01:10:11 -0500 Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9778321835; Thu, 24 Nov 2022 22:10:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1669356609; x=1700892609; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=2E8o88X70Bz2N9wjYZ3YWXzwXXJYBrtBan5h7P/+Xgs=; b=LTrNjthrZw1HAQAFPi8UZg45fAmVSdXmzGnRzsX5YGdbQUdfDUfu+bLW NFDTIA5Y9rrntV+OJgX5x00Qusdd5+attWtvPenSEkBH+rtehSSwv14wk CLzaaqzcg8/2srzcMMwX5D7dIqN79Znczu/11GOD+Irj81FyaEETXMxm+ AICXoAtfxgEhZ7Y2IGJ9XNRzt8pthwECAogLklBPRyK5pFKjpXJIk4ewW PM0eE5N8L83BC1YGocY1sqTqycXZzpXWebtXdBH+lNH+gHYzP00Jf2V/E 7lkNnRan/RbATGff3dPxq6x+XCpJiGCI4FaXq0VuEKQRS6reE4SItPIaO Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10541"; a="313116812" X-IronPort-AV: E=Sophos;i="5.96,192,1665471600"; d="scan'208";a="313116812" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Nov 2022 22:10:05 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10541"; a="784838478" X-IronPort-AV: E=Sophos;i="5.96,192,1665471600"; d="scan'208";a="784838478" Received: from embargo.jf.intel.com ([10.165.9.183]) by fmsmga001-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Nov 2022 22:10:04 -0800 From: Yang Weijiang To: seanjc@google.com, pbonzini@redhat.com, jmattson@google.com, kvm@vger.kernel.org, linux-kernel@vger.kernel.org Cc: like.xu.linux@gmail.com, kan.liang@linux.intel.com, wei.w.wang@intel.com, weijiang.yang@intel.com, Like Xu Subject: [PATCH v2 06/15] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_CTL for guest Arch LBR Date: Thu, 24 Nov 2022 23:05:55 -0500 Message-Id: <20221125040604.5051-7-weijiang.yang@intel.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20221125040604.5051-1-weijiang.yang@intel.com> References: <20221125040604.5051-1-weijiang.yang@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE 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 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750447360593090057?= X-GMAIL-MSGID: =?utf-8?q?1750447360593090057?= From: Paolo Bonzini Arch LBR is enabled by setting MSR_ARCH_LBR_CTL.LBREn to 1. A new guest state field named "Guest IA32_LBR_CTL" is added to enhance guest LBR usage. When guest Arch LBR is enabled, a guest LBR event will be created like the model-specific LBR does. Clear guest LBR enable bit on host PMI handling so guest can see expected config. On processors that support Arch LBR, MSR_IA32_DEBUGCTLMSR[bit 0] has no meaning. It can be written to 0 or 1, but reads will always return 0. Like IA32_DEBUGCTL, IA32_ARCH_LBR_CTL msr is also preserved on INIT. Regardless of the Arch LBR or legacy LBR, when the LBR_EN bit 0 of the corresponding control MSR is set to 1, LBR recording will be enabled. Signed-off-by: Like Xu Co-developed-by: Like Xu Signed-off-by: Paolo Bonzini Co-developed-by: Yang Weijiang Signed-off-by: Yang Weijiang --- arch/x86/events/intel/lbr.c | 2 - arch/x86/include/asm/msr-index.h | 1 + arch/x86/include/asm/vmx.h | 2 + arch/x86/kvm/vmx/pmu_intel.c | 67 ++++++++++++++++++++++++++++---- arch/x86/kvm/vmx/vmx.c | 7 ++++ 5 files changed, 69 insertions(+), 10 deletions(-) diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c index e7caabfa1377..ef589984b907 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -100,8 +100,6 @@ ARCH_LBR_RETURN |\ ARCH_LBR_OTHER_BRANCH) -#define ARCH_LBR_CTL_MASK 0x7f000e - static void intel_pmu_lbr_filter(struct cpu_hw_events *cpuc); static __always_inline bool is_lbr_call_stack_bit_set(u64 config) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 10ac52705892..2a9eaab2fdb1 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -220,6 +220,7 @@ #define LBR_INFO_BR_TYPE (0xfull << LBR_INFO_BR_TYPE_OFFSET) #define MSR_ARCH_LBR_CTL 0x000014ce +#define ARCH_LBR_CTL_MASK 0x7f000e #define ARCH_LBR_CTL_LBREN BIT(0) #define ARCH_LBR_CTL_CPL_OFFSET 1 #define ARCH_LBR_CTL_CPL (0x3ull << ARCH_LBR_CTL_CPL_OFFSET) diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 498dc600bd5c..8502c068202c 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -257,6 +257,8 @@ enum vmcs_field { GUEST_BNDCFGS_HIGH = 0x00002813, GUEST_IA32_RTIT_CTL = 0x00002814, GUEST_IA32_RTIT_CTL_HIGH = 0x00002815, + GUEST_IA32_LBR_CTL = 0x00002816, + GUEST_IA32_LBR_CTL_HIGH = 0x00002817, HOST_IA32_PAT = 0x00002c00, HOST_IA32_PAT_HIGH = 0x00002c01, HOST_IA32_EFER = 0x00002c02, diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 0c78cb4b72be..b57944d5e7d8 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -19,6 +19,7 @@ #include "pmu.h" #define MSR_PMC_FULL_WIDTH_BIT (MSR_IA32_PMC0 - MSR_IA32_PERFCTR0) +#define KVM_ARCH_LBR_CTL_MASK (ARCH_LBR_CTL_MASK | ARCH_LBR_CTL_LBREN) static struct kvm_event_hw_type_mapping intel_arch_events[] = { [0] = { 0x3c, 0x00, PERF_COUNT_HW_CPU_CYCLES }, @@ -178,7 +179,7 @@ static bool intel_pmu_is_valid_lbr_msr(struct kvm_vcpu *vcpu, u32 index) (index == MSR_LBR_SELECT || index == MSR_LBR_TOS)) return true; - if (index == MSR_ARCH_LBR_DEPTH) + if (index == MSR_ARCH_LBR_DEPTH || index == MSR_ARCH_LBR_CTL) return kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR) && guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR); @@ -345,6 +346,30 @@ static bool intel_pmu_handle_lbr_msrs_access(struct kvm_vcpu *vcpu, return true; } +static bool arch_lbr_ctl_is_valid(struct kvm_vcpu *vcpu, u64 ctl) +{ + struct kvm_cpuid_entry2 *entry; + struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); + + if (!pmu->kvm_arch_lbr_depth) + return false; + + if (ctl & ~KVM_ARCH_LBR_CTL_MASK) + return false; + + entry = kvm_find_cpuid_entry(vcpu, 0x1c); + if (!entry) + return false; + + if (!(entry->ebx & BIT(0)) && (ctl & ARCH_LBR_CTL_CPL)) + return false; + if (!(entry->ebx & BIT(2)) && (ctl & ARCH_LBR_CTL_STACK)) + return false; + if (!(entry->ebx & BIT(1)) && (ctl & ARCH_LBR_CTL_FILTER)) + return false; + return true; +} + static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); @@ -377,6 +402,14 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_ARCH_LBR_DEPTH: msr_info->data = lbr_desc->records.nr; return 0; + case MSR_ARCH_LBR_CTL: + if (!kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR)) { + WARN_ON_ONCE(!msr_info->host_initiated); + msr_info->data = 0; + } else { + msr_info->data = vmcs_read64(GUEST_IA32_LBR_CTL); + } + return 0; default: if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) { @@ -483,6 +516,18 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR)) wrmsrl(MSR_ARCH_LBR_DEPTH, lbr_desc->records.nr); return 0; + case MSR_ARCH_LBR_CTL: + if (msr_info->host_initiated && !pmu->kvm_arch_lbr_depth) + return data != 0; + + if (!arch_lbr_ctl_is_valid(vcpu, data)) + break; + + vmcs_write64(GUEST_IA32_LBR_CTL, data); + if (intel_pmu_lbr_is_enabled(vcpu) && !lbr_desc->event && + (data & ARCH_LBR_CTL_LBREN)) + intel_pmu_create_guest_lbr_event(vcpu); + return 0; default: if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) { @@ -727,12 +772,16 @@ static void intel_pmu_reset(struct kvm_vcpu *vcpu) */ static void intel_pmu_legacy_freezing_lbrs_on_pmi(struct kvm_vcpu *vcpu) { - u64 data = vmcs_read64(GUEST_IA32_DEBUGCTL); + u32 lbr_ctl_field = GUEST_IA32_DEBUGCTL; - if (data & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI) { - data &= ~DEBUGCTLMSR_LBR; - vmcs_write64(GUEST_IA32_DEBUGCTL, data); - } + if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI)) + return; + + if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR) && + guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR)) + lbr_ctl_field = GUEST_IA32_LBR_CTL; + + vmcs_write64(lbr_ctl_field, vmcs_read64(lbr_ctl_field) & ~0x1ULL); } static void intel_pmu_deliver_pmi(struct kvm_vcpu *vcpu) @@ -801,7 +850,8 @@ void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu) { struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); - bool lbr_enable = !guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR) && + bool lbr_enable = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR) ? + (vmcs_read64(GUEST_IA32_LBR_CTL) & ARCH_LBR_CTL_LBREN) : (vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR); if (!lbr_desc->event) { @@ -829,7 +879,8 @@ void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu) static void intel_pmu_cleanup(struct kvm_vcpu *vcpu) { - bool lbr_enable = !guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR) && + bool lbr_enable = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR) ? + (vmcs_read64(GUEST_IA32_LBR_CTL) & ARCH_LBR_CTL_LBREN) : (vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR); if (!lbr_enable) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index cea8c07f5229..1ae2efc29546 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2120,6 +2120,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) VM_EXIT_SAVE_DEBUG_CONTROLS) get_vmcs12(vcpu)->guest_ia32_debugctl = data; + /* + * For Arch LBR, IA32_DEBUGCTL[bit 0] has no meaning. + * It can be written to 0 or 1, but reads will always return 0. + */ + if (guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR)) + data &= ~DEBUGCTLMSR_LBR; + vmcs_write64(GUEST_IA32_DEBUGCTL, data); if (intel_pmu_lbr_is_enabled(vcpu) && !to_vmx(vcpu)->lbr_desc.event && (data & DEBUGCTLMSR_LBR))