From patchwork Thu Sep 21 08:29:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Xiong Y" X-Patchwork-Id: 13394247 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 B3713E7D0A2 for ; Thu, 21 Sep 2023 18:14:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229621AbjIUSOF (ORCPT ); Thu, 21 Sep 2023 14:14:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48016 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230160AbjIUSNh (ORCPT ); Thu, 21 Sep 2023 14:13:37 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1D9819ECE for ; Thu, 21 Sep 2023 10:49:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695318598; x=1726854598; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=efkQc+tbxzsdrsFs8ZgvsaNPhMb65ZoGq5/udoaz3jU=; b=O+6v8IHqYDXaX0Lra6pj8KqVTu3AjvKL1H/e6ipKM5v5EpGNbXLx9GJr B/QJgEHYbJG8G+ZImNuoPhihtqHITzSE+aZ6OA+1tQAlFAz4bN7CZZprh SaRPdEi1Vp3Jocl882vO9otfpu849H38Q0UWRyuhmV2ZjVcD+vEK6SXMo YOtm4tozBSyYlASsGYTMki38DJWhf4GGqEOnko5zkp2fXKrs4KCKKjTX+ PtJeyCOW016dPOmGFMZ1tScW56m9SpsbvG9iA19EtM+r4mHq1yF2q+REY eVrvOdGZpgREp0d3Y4n7cxakYl1x4McZbB5GfpE8Qy29zXnWQXMp0+qs+ g==; X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="359841322" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="359841322" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:30:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="747001019" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="747001019" Received: from dorasunx-mobl1.ccr.corp.intel.com (HELO xiongzha-desk1.ccr.corp.intel.com) ([10.255.30.47]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:30:48 -0700 From: Xiong Zhang To: kvm@vger.kernel.org Cc: seanjc@google.com, like.xu.linux@gmail.com, dapeng1.mi@linux.intel.com, zhiyuan.lv@intel.com, zhenyu.z.wang@intel.com, kan.liang@intel.com, Xiong Zhang Subject: [PATCH v2 1/9] KVM: x86/PMU: Delay vLBR release to the vcpu next sched-in Date: Thu, 21 Sep 2023 16:29:49 +0800 Message-Id: <20230921082957.44628-2-xiong.y.zhang@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230921082957.44628-1-xiong.y.zhang@intel.com> References: <20230921082957.44628-1-xiong.y.zhang@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org If guest LBR is disabled at vCPU sched-in time, the vLBR event will be released, then the following guest LBR MSRs accessing will be trapped, and cause KVM to create new vLBR event. If this new vLBR event is the only user of host LBR facility, host LBR driver will reset LBR facility at vLBR creation. So guest LBR content may be changed during vCPU sched-out and sched-in. Considering this serial: 1. Guest disables LBR. 2. Guest reads LBR MSRs, but it doesn't finish. 3. vCPU is sched-out, later sched-in, vLBR event is released. 4. Guest continue reading LBR MSRs, KVM creates vLBR event again, if this vLBR event is the only LBR user on host now, host LBR driver will reset HW LBR facility at vLBR creataion. 5. Guest gets the remain LBR MSRs with reset state. So gueest LBR MSRs reading before vCPU sched-out is correct, while guest LBR MSRs reading after vCPU sched-out is wrong and is in reset state. Similarly guest LBR MSRs writing before vCPU sched-out is lost and is in reset state, while guest LBR MSRs writing after vCPU sched-out is correct. This is a bug that guest LBR content is changed as vCPU's scheduling. This can happen when guest LBR MSRs accessing spans vCPU's scheduling, usually guest access LBR MSRs at guest task switch and PMI handler. Two options could be used to fixed this bug: a. Save guest LBR snapshot at vLBR release in step 3, then restore guest LBR after vLBR creation in step 4. But the number of LBR MSRs is near 100, this means 100 MSRs reading and 100s writing are needed for each vLBR release, the overhead is too heavy. b. Defer vLBR release in step 3. This commit choose the option b. Guest LBR MSRs accessing is passthrough, so the interceptable guest DEBUGCTLMSR_LBR bit is used to predict guest LBR usage. If guest LBR is disabled in a whole vCPU shced time slice, KVM will predict guest LBR won't be used recently, then vLBR will be released in next vCPU sched-in. Guest LBR MSRs accessing should be finished in two vCPU sched time slice, otherwise it is maybe a guest LBR driver bug and can not be supported by this commit. Signed-off-by: Xiong Zhang --- arch/x86/kvm/vmx/pmu_intel.c | 10 ++++++++-- arch/x86/kvm/vmx/vmx.c | 12 +++++++++--- arch/x86/kvm/vmx/vmx.h | 2 ++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index f2efa0bf7ae8..76d7bd8e4fc6 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -628,6 +628,7 @@ static void intel_pmu_init(struct kvm_vcpu *vcpu) lbr_desc->records.nr = 0; lbr_desc->event = NULL; lbr_desc->msr_passthrough = false; + lbr_desc->in_use = FALSE; } static void intel_pmu_reset(struct kvm_vcpu *vcpu) @@ -761,8 +762,13 @@ void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu) static void intel_pmu_cleanup(struct kvm_vcpu *vcpu) { - if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR)) - intel_pmu_release_guest_lbr_event(vcpu); + struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); + + if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR)) { + if (!lbr_desc->in_use) + intel_pmu_release_guest_lbr_event(vcpu); + lbr_desc->in_use = false; + } } void intel_pmu_cross_mapped_check(struct kvm_pmu *pmu) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 72e3943f3693..4056e19266b5 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2238,9 +2238,15 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) get_vmcs12(vcpu)->guest_ia32_debugctl = data; vmcs_write64(GUEST_IA32_DEBUGCTL, data); - if (intel_pmu_lbr_is_enabled(vcpu) && !to_vmx(vcpu)->lbr_desc.event && - (data & DEBUGCTLMSR_LBR)) - intel_pmu_create_guest_lbr_event(vcpu); + + if (intel_pmu_lbr_is_enabled(vcpu) && (data & DEBUGCTLMSR_LBR)) { + struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); + + lbr_desc->in_use = true; + if (!lbr_desc->event) + intel_pmu_create_guest_lbr_event(vcpu); + } + return 0; } case MSR_IA32_BNDCFGS: diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index c2130d2c8e24..547edeb52d09 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -107,6 +107,8 @@ struct lbr_desc { /* True if LBRs are marked as not intercepted in the MSR bitmap */ bool msr_passthrough; + + bool in_use; }; /* From patchwork Thu Sep 21 08:29:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Xiong Y" X-Patchwork-Id: 13394246 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 57A60E7D0A5 for ; Thu, 21 Sep 2023 18:13:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230186AbjIUSNk (ORCPT ); Thu, 21 Sep 2023 14:13:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47046 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229778AbjIUSMd (ORCPT ); Thu, 21 Sep 2023 14:12:33 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1BE3A42C3A for ; Thu, 21 Sep 2023 10:49:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695318598; x=1726854598; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AJ7TummwzL9HHIztJ90SFhtCF8CM4tWGiNkSK8PMMxc=; b=K8FfkJy8mt9K+Qrl2xcpqBFDWK7jNxLuijg3hCr/mXAZP+dMhAEjymzL Y8+D2q2ycPsidreFjeIO4plujZ9hjhriG66oDOqPMFjfyncd/CDxQULd7 vzM8I8RYnigY7r2xTqpP0C455XbkVsBbi31uJvPuZCegOorxbOJugfFmc uxjV92BlhedOq+xKwwMurnjeHPtVMaj7vtGLxxMNDfA/Ak6U9MP1cfzfu Tj+XEAQecvWQRSqKqERiGHVk3XCvpYWGnJ2eVqZPzTXyt5i/DkR411j74 77sstxXW6u1/GQgjLx6k+rOsYGmlTzR0nm/qjiQluUJITzFg8ZbV2iX25 A==; X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="359841333" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="359841333" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:30:55 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="747001045" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="747001045" Received: from dorasunx-mobl1.ccr.corp.intel.com (HELO xiongzha-desk1.ccr.corp.intel.com) ([10.255.30.47]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:30:52 -0700 From: Xiong Zhang To: kvm@vger.kernel.org Cc: seanjc@google.com, like.xu.linux@gmail.com, dapeng1.mi@linux.intel.com, zhiyuan.lv@intel.com, zhenyu.z.wang@intel.com, kan.liang@intel.com, Xiong Zhang Subject: [PATCH v2 2/9] KVM: x86/pmu: Don't release vLBR casued by vPMI Date: Thu, 21 Sep 2023 16:29:50 +0800 Message-Id: <20230921082957.44628-3-xiong.y.zhang@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230921082957.44628-1-xiong.y.zhang@intel.com> References: <20230921082957.44628-1-xiong.y.zhang@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org To emulate Freeze_LBR_On_PMI feature, KVM PMU disables guest LBR at PMI injection. When guest LBR is disabled, vLBR event may be released at two vCPU sched-in later. once vLBR event is released, KVM will create a new vLBR event when guest access LBR MSRs again. First this adds overhead at vLBR event release and re-creation. Second this may changes guest LBR contend as vLBR event creation may cause host LBR drvier reset hw LBR facility. This commit avoids the vLBR release for Freeze_LBR_On_PMI emulation. It changes boolean lbr_desc->in_use into enum lbr_desc->state, so it could express more LBR states, KVM sets lbr_desc->state as FREEZE_ON_PMI at vPMI injection, so that vLBR release function could check this state to avoid vLBR release. When guest enables LBR at the end of the guest PMI handler, KVM will set lbr_desc->state as IN_USE. Signed-off-by: Xiong Zhang --- arch/x86/kvm/vmx/pmu_intel.c | 8 +++++--- arch/x86/kvm/vmx/vmx.c | 2 +- arch/x86/kvm/vmx/vmx.h | 8 +++++++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 76d7bd8e4fc6..c8d46c3d1ab6 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -628,7 +628,7 @@ static void intel_pmu_init(struct kvm_vcpu *vcpu) lbr_desc->records.nr = 0; lbr_desc->event = NULL; lbr_desc->msr_passthrough = false; - lbr_desc->in_use = FALSE; + lbr_desc->state = LBR_STATE_PREDICT_FREE; } static void intel_pmu_reset(struct kvm_vcpu *vcpu) @@ -671,6 +671,7 @@ static void intel_pmu_legacy_freezing_lbrs_on_pmi(struct kvm_vcpu *vcpu) if (data & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI) { data &= ~DEBUGCTLMSR_LBR; vmcs_write64(GUEST_IA32_DEBUGCTL, data); + vcpu_to_lbr_desc(vcpu)->state = LBR_STATE_FREEZE_ON_PMI; } } @@ -765,9 +766,10 @@ static void intel_pmu_cleanup(struct kvm_vcpu *vcpu) struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR)) { - if (!lbr_desc->in_use) + if (lbr_desc->state == LBR_STATE_PREDICT_FREE) intel_pmu_release_guest_lbr_event(vcpu); - lbr_desc->in_use = false; + else if (lbr_desc->state == LBR_STATE_IN_USE) + lbr_desc->state = LBR_STATE_PREDICT_FREE; } } diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 4056e19266b5..565df8eeb78b 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2242,7 +2242,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) if (intel_pmu_lbr_is_enabled(vcpu) && (data & DEBUGCTLMSR_LBR)) { struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); - lbr_desc->in_use = true; + lbr_desc->state = LBR_STATE_IN_USE; if (!lbr_desc->event) intel_pmu_create_guest_lbr_event(vcpu); } diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 547edeb52d09..0cb68a319fc8 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -93,6 +93,12 @@ union vmx_exit_reason { u32 full; }; +enum lbr_state { + LBR_STATE_PREDICT_FREE = 0, + LBR_STATE_IN_USE = 1, + LBR_STATE_FREEZE_ON_PMI = 2 +}; + struct lbr_desc { /* Basic info about guest LBR records. */ struct x86_pmu_lbr records; @@ -108,7 +114,7 @@ struct lbr_desc { /* True if LBRs are marked as not intercepted in the MSR bitmap */ bool msr_passthrough; - bool in_use; + enum lbr_state state; }; /* From patchwork Thu Sep 21 08:29:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Xiong Y" X-Patchwork-Id: 13394582 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 AD6E9E7D0A2 for ; Thu, 21 Sep 2023 20:50:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232287AbjIUUuD (ORCPT ); Thu, 21 Sep 2023 16:50:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53596 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232018AbjIUUtJ (ORCPT ); Thu, 21 Sep 2023 16:49:09 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E8E844E5CB for ; Thu, 21 Sep 2023 10:49:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695318598; x=1726854598; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JxIQN4W0m34DpRad7XzCHfwbyOw8EJzcxV997kxjd20=; b=LVsCNRVEJDxLmWXwqVOAAsPA8e3mMzPrHf2C5SiauyQ71wsMIWdkcBs+ fQtqYLFlwvM2Tm5jQNAMELHUAHRxskX15fhc5SkC01DLKQk1h4rEgoMUr zrV9itIevQqf68Ve04XQOOew0CwP97exTk1hThqa8bXByuvlEKugIYu1r ilY/3pC2fwVWRwdv7IY/0u5SD1ooAYdqTYTWSCrQPvB44L28hTKdy0mG0 CAbVGgUSN4o9Q0/GlcEA+35hvhqVLwHxxi4Oi8QaoKH07U5C/xRfV2fM0 q8NwV4x0uJylGNlqsNP8S8mPqfsLb0uHHc0qjVOTcehUf1mYcyUDvkdJG Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="359841342" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="359841342" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:30:59 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="747001078" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="747001078" Received: from dorasunx-mobl1.ccr.corp.intel.com (HELO xiongzha-desk1.ccr.corp.intel.com) ([10.255.30.47]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:30:57 -0700 From: Xiong Zhang To: kvm@vger.kernel.org Cc: seanjc@google.com, like.xu.linux@gmail.com, dapeng1.mi@linux.intel.com, zhiyuan.lv@intel.com, zhenyu.z.wang@intel.com, kan.liang@intel.com, Xiong Zhang Subject: [PATCH v2 3/9] KVM: x85/pmu: Add Streamlined FREEZE_LBR_ON_PMI for vPMU v4 Date: Thu, 21 Sep 2023 16:29:51 +0800 Message-Id: <20230921082957.44628-4-xiong.y.zhang@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230921082957.44628-1-xiong.y.zhang@intel.com> References: <20230921082957.44628-1-xiong.y.zhang@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Arch PMU version 4 adds a streamlined FREEZE_LBR_ON_PMI feature, this feature adds LBR_FRZ[bit 58] into IA32_PERF_GLOBAL_STATUS, this bit is set due to the following conditions: -- IA32_DEBUGCTL.FREEZE_LBR_ON_PMI has been set -- A performance counter, configured to generate PMI, has overflowed to signal a PMI. Consequently the LBR stack is frozen. Effectively, this bit also serves as a control to enabled capturing data in the LBR stack. When this bit is set, LBR stack is frozen, and new LBR records won't be filled. The sequence of streamlined freeze LBR is: 1. Profiling agent set IA32_DEBUGCTL.FREEZE_LBR_ON_PMI, and enable a performance counter to generate PMI on overflow. 2. Processor generates PMI and sets IA32_PERF_GLOBAL_STATUS.LBR_FRZ, then LBR stack is forzen. 3. Profiling agent PMI handler handles overflow, and clears IA32_PERF_GLOBAL_STATUS. 4. When IA32_PERF_GLOBAL_STATUS.LBR_FRZ is cleared in step 3, processor resume LBR stack, and new LBR records can be filled again. In order to emulate this behavior, LBR stack must be frozen on guest vPMI. KVM has two choice to do this: 1. KVM stops vLBR event through perf_event_pause(), and put vLBR event into off state, then vLBR lose LBR hw resource, finally guest couldn't read LBR records in guest PMI handler. This choice couldn't be used. 2. KVM clears guest DEBUGCTLMSR_LBR bit in VMCS on PMI, so when guest is running, LBR HW stack is disabled, while vLBR event is still active and own LBR HW, so guest could still read LBR records in guest PMI handler. But the sequence of streamlined freeze LBR doesn't clear DEBUGCTLMSR_LBR bit, so when guest read guest DEBUGCTL_MSR, KVM will return a value with DEBUGCTLMSR_LBR bit set during LBR freezing. Once guest clears IA32_PERF_GLOBAL_STATUS.LBR_FRZ in step 4, KVM will re-enable guest LBR through setting guest DEBUGCTL_LBR bit in VMCS. As KVM needs re-enable guest LBR when guest clears global status, the handling of GLOBAL_OVF_CTRL MSR is moved from common pmu.c into vmx/pmu_intel.c. Signed-off-by: Xiong Zhang Reviewed-by: Dapeng Mi --- arch/x86/include/asm/msr-index.h | 1 + arch/x86/kvm/pmu.c | 8 ------ arch/x86/kvm/vmx/pmu_intel.c | 49 ++++++++++++++++++++++++++++++++ arch/x86/kvm/vmx/vmx.c | 7 +++++ 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 1d111350197f..badc2f729a8e 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -1054,6 +1054,7 @@ /* PERF_GLOBAL_OVF_CTL bits */ #define MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI_BIT 55 #define MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI (1ULL << MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI_BIT) +#define MSR_CORE_PERF_GLOBAL_OVF_CTRL_LBR_FREEZE BIT_ULL(58) #define MSR_CORE_PERF_GLOBAL_OVF_CTRL_OVF_BUF_BIT 62 #define MSR_CORE_PERF_GLOBAL_OVF_CTRL_OVF_BUF (1ULL << MSR_CORE_PERF_GLOBAL_OVF_CTRL_OVF_BUF_BIT) #define MSR_CORE_PERF_GLOBAL_OVF_CTRL_COND_CHGD_BIT 63 diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index edb89b51b383..4b6a508f3f0b 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -640,14 +640,6 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) reprogram_counters(pmu, diff); } break; - case MSR_CORE_PERF_GLOBAL_OVF_CTRL: - /* - * GLOBAL_OVF_CTRL, a.k.a. GLOBAL STATUS_RESET, clears bits in - * GLOBAL_STATUS, and so the set of reserved bits is the same. - */ - if (data & pmu->global_status_mask) - return 1; - fallthrough; case MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR: if (!msr_info->host_initiated) pmu->global_status &= ~data; diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index c8d46c3d1ab6..6e3bbe777bf5 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -426,6 +426,34 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) pmu->pebs_data_cfg = data; break; + case MSR_CORE_PERF_GLOBAL_OVF_CTRL: + /* + * GLOBAL_OVF_CTRL, a.k.a. GLOBAL STATUS_RESET, clears bits in + * GLOBAL_STATUS, and so the set of reserved bits is the same. + */ + if (data & pmu->global_status_mask) + return 1; + + /* + * Guest clears GLOBAL_STATUS_LBR_FREEZE bit, KVM re-enable + * Guset LBR which is disabled at vPMI injection for streamlined + * Freeze_LBR_On_PMI. + */ + if (pmu->version >= 4 && !msr_info->host_initiated && + (data & MSR_CORE_PERF_GLOBAL_OVF_CTRL_LBR_FREEZE) && + (pmu->global_status & MSR_CORE_PERF_GLOBAL_OVF_CTRL_LBR_FREEZE)) { + u64 debug_ctl = vmcs_read64(GUEST_IA32_DEBUGCTL); + + if (!(debug_ctl & DEBUGCTLMSR_LBR)) { + debug_ctl |= DEBUGCTLMSR_LBR; + vmcs_write64(GUEST_IA32_DEBUGCTL, debug_ctl); + } + vcpu_to_lbr_desc(vcpu)->state = LBR_STATE_IN_USE; + } + + if (!msr_info->host_initiated) + pmu->global_status &= ~data; + break; default: if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) { @@ -565,6 +593,9 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) if (vmx_pt_mode_is_host_guest()) pmu->global_status_mask &= ~MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI; + if (pmu->version >= 4) + pmu->global_status_mask &= + ~MSR_CORE_PERF_GLOBAL_OVF_CTRL_LBR_FREEZE; entry = kvm_find_cpuid_entry_index(vcpu, 7, 0); if (entry && @@ -675,6 +706,22 @@ static void intel_pmu_legacy_freezing_lbrs_on_pmi(struct kvm_vcpu *vcpu) } } +static void intel_pmu_streamlined_freezing_lbrs_on_pmi(struct kvm_vcpu *vcpu) +{ + u64 data = vmcs_read64(GUEST_IA32_DEBUGCTL); + struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); + + /* + * Even if streamlined freezing LBR won't clear LBR_EN like legacy + * freezing LBR, here legacy freezing LBR is called to freeze LBR HW + * for streamlined freezing LBR when guest run. But guest VM will + * see a fake guest DEBUGCTL MSR with LBR_EN bit set. + */ + intel_pmu_legacy_freezing_lbrs_on_pmi(vcpu); + if ((data & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI) && (data & DEBUGCTLMSR_LBR)) + pmu->global_status |= MSR_CORE_PERF_GLOBAL_OVF_CTRL_LBR_FREEZE; +} + static void intel_pmu_deliver_pmi(struct kvm_vcpu *vcpu) { u8 version = vcpu_to_pmu(vcpu)->version; @@ -684,6 +731,8 @@ static void intel_pmu_deliver_pmi(struct kvm_vcpu *vcpu) if (version > 1 && version < 4) intel_pmu_legacy_freezing_lbrs_on_pmi(vcpu); + else if (version >= 4) + intel_pmu_streamlined_freezing_lbrs_on_pmi(vcpu); } static void vmx_update_intercept_for_lbr_msrs(struct kvm_vcpu *vcpu, bool set) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 565df8eeb78b..66e4cf714dbd 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2113,6 +2113,13 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) break; case MSR_IA32_DEBUGCTLMSR: msr_info->data = vmcs_read64(GUEST_IA32_DEBUGCTL); + /* + * In streamlined Freeze_LBR_On_PMI, guest should see LBR_EN. + */ + if ((vcpu_to_pmu(vcpu)->global_status & + MSR_CORE_PERF_GLOBAL_OVF_CTRL_LBR_FREEZE) && + vcpu_to_pmu(vcpu)->version >= 4) + msr_info->data |= DEBUGCTLMSR_LBR; break; default: find_uret_msr: From patchwork Thu Sep 21 08:29:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Xiong Y" X-Patchwork-Id: 13394369 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 7D5BDE7D0A4 for ; Thu, 21 Sep 2023 19:05:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231239AbjIUTF6 (ORCPT ); Thu, 21 Sep 2023 15:05:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42540 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231618AbjIUTFF (ORCPT ); Thu, 21 Sep 2023 15:05:05 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 998D5E083 for ; Thu, 21 Sep 2023 10:49:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695318599; x=1726854599; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dovjjs6Cwd613M4DckYtJynCmnyAMU353Nvw3+PCAK4=; b=Pl5+QQfY7dSYvItWfeNxpz7ii5GgpV7YEeSvEYQGZu6RqIsLp6ZYrycK dTyxJPBAazowIoEQZsNnVrBjweBF5Z1gDGMlAQUTfzs9VrPlcTqqqL9ZC 2zgpkrlI8BLfHvH2ds9haIXmwuuo/65FaNGOXCJjmONdIfjCcIBLfxj52 +WqRG4Fa/LYFS0Vx4ikAIFnGtltiprHLZ6PHMequymsuCH9wNFzVmNSAd nxurrBbG0eBNvZFTxx4NPyVstj49U/FzW5GVR8NrNYcAeLkn0IS4ssUZC MaDjX2xMqyIaik0AQW2zNL0MqcdO20XIz689imvTHaIhfVN8GUAA0R7Mj Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="359841347" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="359841347" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:31:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="747001098" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="747001098" Received: from dorasunx-mobl1.ccr.corp.intel.com (HELO xiongzha-desk1.ccr.corp.intel.com) ([10.255.30.47]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:31:01 -0700 From: Xiong Zhang To: kvm@vger.kernel.org Cc: seanjc@google.com, like.xu.linux@gmail.com, dapeng1.mi@linux.intel.com, zhiyuan.lv@intel.com, zhenyu.z.wang@intel.com, kan.liang@intel.com, Xiong Zhang Subject: [PATCH v2 4/9] KVM: x86/pmu: Add PERF_GLOBAL_STATUS_SET MSR emulation Date: Thu, 21 Sep 2023 16:29:52 +0800 Message-Id: <20230921082957.44628-5-xiong.y.zhang@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230921082957.44628-1-xiong.y.zhang@intel.com> References: <20230921082957.44628-1-xiong.y.zhang@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The IA32_PERF_GLOBAL_STATUS_SET MSR is introduced with arch PMU version 4. It allows software to set individual bits in IA32_PERF_GLOBAL_STATUS MSR. It can be used by a VMM to virtualize the state of IA32_PERF_GLOBAL_STATUS across VMS. If the running VM owns the whole PMU, different VM will have different perf global status, VMM needs to restore IA32_PERF_GLOBAL_STATUS MSR at VM switch, but IA32_PERF_GLOBAL_STATUS MSR is read only, so VMM can use IA32_PERF_GLOBAL_STATUS_SET MSR to restore PERF_GLOBAL_STATUS MSR. This commit adds this MSR emulation, so that L1 VMM could use it. As it is mainly used by VMM to restore VM's PERF_GLOBAL_STATUS MSR during VM switch, it doesn't need to inject PMI or FREEZE_LBR when VMM write it. Signed-off-by: Xiong Zhang --- Changelog: v1-v2: Add it into msrs_to_save_pmu[] --- arch/x86/include/asm/msr-index.h | 1 + arch/x86/kvm/vmx/pmu_intel.c | 16 ++++++++++++++++ arch/x86/kvm/x86.c | 1 + 3 files changed, 18 insertions(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index badc2f729a8e..50d231f76003 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -1048,6 +1048,7 @@ #define MSR_CORE_PERF_GLOBAL_STATUS 0x0000038e #define MSR_CORE_PERF_GLOBAL_CTRL 0x0000038f #define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x00000390 +#define MSR_CORE_PERF_GLOBAL_STATUS_SET 0x00000391 #define MSR_PERF_METRICS 0x00000329 diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 6e3bbe777bf5..957663b403f2 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -206,6 +206,8 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr) switch (msr) { case MSR_CORE_PERF_FIXED_CTR_CTRL: return kvm_pmu_has_perf_global_ctrl(pmu); + case MSR_CORE_PERF_GLOBAL_STATUS_SET: + return vcpu_to_pmu(vcpu)->version >= 4; case MSR_IA32_PEBS_ENABLE: ret = vcpu_get_perf_capabilities(vcpu) & PERF_CAP_PEBS_FORMAT; break; @@ -355,6 +357,9 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_CORE_PERF_FIXED_CTR_CTRL: msr_info->data = pmu->fixed_ctr_ctrl; break; + case MSR_CORE_PERF_GLOBAL_STATUS_SET: + msr_info->data = 0; + break; case MSR_IA32_PEBS_ENABLE: msr_info->data = pmu->pebs_enable; break; @@ -454,6 +459,17 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) if (!msr_info->host_initiated) pmu->global_status &= ~data; break; + case MSR_CORE_PERF_GLOBAL_STATUS_SET: + /* + * GLOBAL STATUS_SET, sets bits in GLOBAL_STATUS, so the + * set of reserved bits are the same. + */ + if (data & pmu->global_status_mask) + return 1; + + if (!msr_info->host_initiated) + pmu->global_status |= data; + break; default: if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 6c9c81e82e65..aae60461d0d9 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1471,6 +1471,7 @@ static const u32 msrs_to_save_pmu[] = { MSR_ARCH_PERFMON_FIXED_CTR0 + 2, MSR_CORE_PERF_FIXED_CTR_CTRL, MSR_CORE_PERF_GLOBAL_STATUS, MSR_CORE_PERF_GLOBAL_CTRL, MSR_CORE_PERF_GLOBAL_OVF_CTRL, + MSR_CORE_PERF_GLOBAL_STATUS_SET, MSR_IA32_PEBS_ENABLE, MSR_IA32_DS_AREA, MSR_PEBS_DATA_CFG, /* This part of MSRs should match KVM_INTEL_PMC_MAX_GENERIC. */ From patchwork Thu Sep 21 08:29:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Xiong Y" X-Patchwork-Id: 13394287 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 E89A2E7D0A2 for ; Thu, 21 Sep 2023 18:36:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229709AbjIUSgO (ORCPT ); Thu, 21 Sep 2023 14:36:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53548 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229807AbjIUSfw (ORCPT ); Thu, 21 Sep 2023 14:35:52 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5AB6A359E for ; Thu, 21 Sep 2023 10:50:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695318600; x=1726854600; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=r7FXe3U772ouoKUthr/KM3EloIe2uzXLn1WRaiCQgMs=; b=dvW8U2g/I3wPjMbo+XYI/igAfU9GtrH7TmOGFAU6ir4z0TUIHzjzhMTa rVZr5F6kW/b23EJqfHx/G49wfzL028I9C9kPMBM7ojmRDl8NRcE0yJ/ld xcngTuh+T6zeu8fPz2E4pgSqiVRE7SemWatXOc3rUAdnN5P0Nmy+pgcT0 mosaYaVGd37BAwcyryeqlGoaNX2I7MiquJhXkJXl3wwhrnr1xpH2h3XCy 9CiBPYTW7OwhfCaCbONFbcim+7tR4PLhoQNTOR9WEB7wx7mkR7zzTcH1q kIq73wN35SIA6tUm00mCgZUNm7XgcKPmrnc3IvIh93Ofuuk1CrhNfQd2N g==; X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="359841360" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="359841360" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:31:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="747001122" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="747001122" Received: from dorasunx-mobl1.ccr.corp.intel.com (HELO xiongzha-desk1.ccr.corp.intel.com) ([10.255.30.47]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:31:06 -0700 From: Xiong Zhang To: kvm@vger.kernel.org Cc: seanjc@google.com, like.xu.linux@gmail.com, dapeng1.mi@linux.intel.com, zhiyuan.lv@intel.com, zhenyu.z.wang@intel.com, kan.liang@intel.com, Xiong Zhang Subject: [PATCH v2 5/9] KVM: x86/pmu: Add MSR_CORE_PERF_GLOBAL_INUSE emulation Date: Thu, 21 Sep 2023 16:29:53 +0800 Message-Id: <20230921082957.44628-6-xiong.y.zhang@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230921082957.44628-1-xiong.y.zhang@intel.com> References: <20230921082957.44628-1-xiong.y.zhang@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Arch PMU v4 introduces a new MSR, MSR_CORE_PERF_GLOBAL_INUSE. It provides as "InUse" bit for each GP counter and fixed counter in processor. Additionally PMI InUse[bit 63] indicates if the PMI mechanism has been configured. Each bit's definition references Architectural Performance Monitoring Version 4 section of SDM. Signed-off-by: Xiong Zhang --- ChangeLog: v1->v2: Check INUSE_PMI bit before writing, Add this new MSR into msrs_to_save_pmu[] --- arch/x86/include/asm/msr-index.h | 4 ++ arch/x86/kvm/vmx/pmu_intel.c | 63 ++++++++++++++++++++++++++++++++ arch/x86/kvm/x86.c | 2 +- 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 50d231f76003..1879046ad0cb 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -1049,6 +1049,7 @@ #define MSR_CORE_PERF_GLOBAL_CTRL 0x0000038f #define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x00000390 #define MSR_CORE_PERF_GLOBAL_STATUS_SET 0x00000391 +#define MSR_CORE_PERF_GLOBAL_INUSE 0x00000392 #define MSR_PERF_METRICS 0x00000329 @@ -1061,6 +1062,9 @@ #define MSR_CORE_PERF_GLOBAL_OVF_CTRL_COND_CHGD_BIT 63 #define MSR_CORE_PERF_GLOBAL_OVF_CTRL_COND_CHGD (1ULL << MSR_CORE_PERF_GLOBAL_OVF_CTRL_COND_CHGD_BIT) +/* PERF_GLOBAL_INUSE bits */ +#define MSR_CORE_PERF_GLOBAL_INUSE_PMI BIT_ULL(63) + /* Geode defined MSRs */ #define MSR_GEODE_BUSCONT_CONF0 0x00001900 diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 957663b403f2..d19ccf85026b 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -207,6 +207,7 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr) case MSR_CORE_PERF_FIXED_CTR_CTRL: return kvm_pmu_has_perf_global_ctrl(pmu); case MSR_CORE_PERF_GLOBAL_STATUS_SET: + case MSR_CORE_PERF_GLOBAL_INUSE: return vcpu_to_pmu(vcpu)->version >= 4; case MSR_IA32_PEBS_ENABLE: ret = vcpu_get_perf_capabilities(vcpu) & PERF_CAP_PEBS_FORMAT; @@ -347,6 +348,61 @@ static bool intel_pmu_handle_lbr_msrs_access(struct kvm_vcpu *vcpu, return true; } +static u64 intel_pmu_global_inuse_emulation(struct kvm_pmu *pmu) +{ + u64 data = 0; + int i; + + for (i = 0; i < pmu->nr_arch_gp_counters; i++) { + struct kvm_pmc *pmc = &pmu->gp_counters[i]; + + /* + * IA32_PERF_GLOBAL_INUSE.PERFEVTSELn_InUse[bit n]: This bit + * reflects the logical state of (IA32_PERFEVTSELn[7:0]), + * n < CPUID.0AH.EAX[15:8]. + */ + if (pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT) + data |= 1 << i; + /* + * IA32_PERF_GLOBAL_INUSE.PMI_InUse[bit 63]: This bit is set if + * IA32_PERFEVTSELn.INT[bit 20], n < CPUID.0AH.EAX[15:8] is set. + */ + if ((pmc->eventsel & ARCH_PERFMON_EVENTSEL_INT) && + !(data & MSR_CORE_PERF_GLOBAL_INUSE_PMI)) + data |= MSR_CORE_PERF_GLOBAL_INUSE_PMI; + } + + for (i = 0; i < pmu->nr_arch_fixed_counters; i++) { + /* + * IA32_PERF_GLOBAL_INUSE.FCi_InUse[bit (i + 32)]: This bit + * reflects the logical state of + * IA32_FIXED_CTR_CTRL[i * 4 + 1, i * 4] != 0 + */ + if (pmu->fixed_ctr_ctrl & + intel_fixed_bits_by_idx(i, INTEL_FIXED_0_KERNEL | INTEL_FIXED_0_USER)) + data |= 1ULL << (i + INTEL_PMC_IDX_FIXED); + /* + * IA32_PERF_GLOBAL_INUSE.PMI_InUse[bit 63]: This bit is set if + * IA32_FIXED_CTR_CTRL.ENi_PMI, i = 0, 1, 2 is set. + */ + if ((pmu->fixed_ctr_ctrl & + intel_fixed_bits_by_idx(i, INTEL_FIXED_0_ENABLE_PMI)) && + !(data & MSR_CORE_PERF_GLOBAL_INUSE_PMI)) + data |= MSR_CORE_PERF_GLOBAL_INUSE_PMI; + } + + /* + * IA32_PERF_GLOBAL_INUSE.PMI_InUse[bit 63]: This bit is set if + * any IA32_PEBS_ENABLES bit is set, which enables PEBS for a GP or + * fixed counter. + */ + if (pmu->pebs_enable && + !(data & MSR_CORE_PERF_GLOBAL_INUSE_PMI)) + data |= MSR_CORE_PERF_GLOBAL_INUSE_PMI; + + return data; +} + static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); @@ -360,6 +416,9 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_CORE_PERF_GLOBAL_STATUS_SET: msr_info->data = 0; break; + case MSR_CORE_PERF_GLOBAL_INUSE: + msr_info->data = intel_pmu_global_inuse_emulation(pmu); + break; case MSR_IA32_PEBS_ENABLE: msr_info->data = pmu->pebs_enable; break; @@ -409,6 +468,10 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) if (pmu->fixed_ctr_ctrl != data) reprogram_fixed_counters(pmu, data); break; + case MSR_CORE_PERF_GLOBAL_INUSE: + if (!msr_info->host_initiated) + return 1; /* RO MSR */ + break; case MSR_IA32_PEBS_ENABLE: if (data & pmu->pebs_enable_mask) return 1; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index aae60461d0d9..4e70588e4355 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1471,7 +1471,7 @@ static const u32 msrs_to_save_pmu[] = { MSR_ARCH_PERFMON_FIXED_CTR0 + 2, MSR_CORE_PERF_FIXED_CTR_CTRL, MSR_CORE_PERF_GLOBAL_STATUS, MSR_CORE_PERF_GLOBAL_CTRL, MSR_CORE_PERF_GLOBAL_OVF_CTRL, - MSR_CORE_PERF_GLOBAL_STATUS_SET, + MSR_CORE_PERF_GLOBAL_STATUS_SET, MSR_CORE_PERF_GLOBAL_INUSE, MSR_IA32_PEBS_ENABLE, MSR_IA32_DS_AREA, MSR_PEBS_DATA_CFG, /* This part of MSRs should match KVM_INTEL_PMC_MAX_GENERIC. */ From patchwork Thu Sep 21 08:29:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Xiong Y" X-Patchwork-Id: 13394429 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 99D24E7D0A6 for ; Thu, 21 Sep 2023 19:46:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230109AbjIUTqz (ORCPT ); Thu, 21 Sep 2023 15:46:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55976 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231276AbjIUTqp (ORCPT ); Thu, 21 Sep 2023 15:46:45 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 659849011 for ; Thu, 21 Sep 2023 10:50:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695318600; x=1726854600; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FJjsN/0IeMFvugyIo3sBkjWr5M/Uc3Ntta/kt6prsRA=; b=kUNP1HBDrExTeXWpE7UVtKMxcMbM9dH8uKQ080S+NDuMSDxIverlTP0d 3NYWL91LT2GO8Qm6fbSF8Ff78C+vsSNrFy/jmDGgjDqcMZb1es7JHa+1w UaEiesDeqN85llleCOJ3H18wo0ZhHhzJfsrchUVT0wPkr5KCM8XHKYERL OYp7MKlmUlvA267gbs3pfZP/A+gSFIVSnOBaos7DivIWq40BOwWb33KTO TJbh75MZAegDwkRWw8UISuni0c+aWD+0NvxHBWQChlvjd1DqZtr5EIHMn 2T3LiW38FempPtMsqxd8NNnfr4UgIvjEUnH+7cnHmySH1Wdcoq37J0y1D g==; X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="359841372" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="359841372" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:31:14 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="747001144" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="747001144" Received: from dorasunx-mobl1.ccr.corp.intel.com (HELO xiongzha-desk1.ccr.corp.intel.com) ([10.255.30.47]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:31:11 -0700 From: Xiong Zhang To: kvm@vger.kernel.org Cc: seanjc@google.com, like.xu.linux@gmail.com, dapeng1.mi@linux.intel.com, zhiyuan.lv@intel.com, zhenyu.z.wang@intel.com, kan.liang@intel.com, Like Xu , Xiong Zhang Subject: [PATCH v2 6/9] KVM: x86/pmu: Add Intel PMU supported fixed counters mask Date: Thu, 21 Sep 2023 16:29:54 +0800 Message-Id: <20230921082957.44628-7-xiong.y.zhang@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230921082957.44628-1-xiong.y.zhang@intel.com> References: <20230921082957.44628-1-xiong.y.zhang@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Like Xu Per Intel SDM, fixed-function performance counter 'i' is supported: FxCtr[i]_is_supported := ECX[i] || (EDX[4:0] > i); if pmu.version >=5, ECX is supported fixed counters bit mask. if 1 < pmu.version < 5, EDX[4:0] is number of contiguous fixed-function performance counters starting from 0. which means that the KVM user space can use EDX to limit the number of fixed counters starting from 0 and at the same time, using ECX to enable part of other KVM supported fixed counters. i.e: pmu.version = 5, ECX= 0x5, EDX[4:0]=1, FxCtrl[2, 0] are supported, FxCtrl[1] isn't supported. Add Fixed counter bit mask into all_valid_pmc_idx, and use it to perform the semantic checks. Since fixed counter may be non-continuous, nr_arch_fixed_counters can not be used to enumerate fixed counters, for_each_set_bit_from() is used to enumerate fixed counters, and nr_arch_fixed_counters is deleted. Signed-off-by: Like Xu Signed-off-by: Xiong Zhang Reviewed-by: Dapeng Mi --- arch/x86/include/asm/kvm_host.h | 1 - arch/x86/kvm/pmu.h | 12 +++++- arch/x86/kvm/svm/pmu.c | 1 - arch/x86/kvm/vmx/pmu_intel.c | 69 ++++++++++++++++++++------------- 4 files changed, 52 insertions(+), 31 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 1a4def36d5bb..50d2e51bd143 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -515,7 +515,6 @@ struct kvm_pmc { struct kvm_pmu { u8 version; unsigned nr_arch_gp_counters; - unsigned nr_arch_fixed_counters; unsigned available_event_types; u64 fixed_ctr_ctrl; u64 fixed_ctr_ctrl_mask; diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index 7d9ba301c090..4bab4819ea6c 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -125,14 +125,22 @@ 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(INTEL_PMC_IDX_FIXED + idx, pmu->all_valid_pmc_idx); +} + /* returns fixed PMC with the specified MSR */ static inline struct kvm_pmc *get_fixed_pmc(struct kvm_pmu *pmu, u32 msr) { int base = MSR_CORE_PERF_FIXED_CTR0; - if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) { + if (msr >= base && msr < base + KVM_PMC_MAX_FIXED) { u32 index = array_index_nospec(msr - base, - pmu->nr_arch_fixed_counters); + KVM_PMC_MAX_FIXED); + + if (!fixed_ctr_is_supported(pmu, index)) + return NULL; return &pmu->fixed_counters[index]; } diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c index cef5a3d0abd0..d0a12e739989 100644 --- a/arch/x86/kvm/svm/pmu.c +++ b/arch/x86/kvm/svm/pmu.c @@ -213,7 +213,6 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu) pmu->raw_event_mask = AMD64_RAW_EVENT_MASK; /* not applicable to AMD; but clean them to prevent any fall out */ pmu->counter_bitmask[KVM_PMC_FIXED] = 0; - pmu->nr_arch_fixed_counters = 0; bitmap_set(pmu->all_valid_pmc_idx, 0, pmu->nr_arch_gp_counters); } diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index d19ccf85026b..8d7c4e34838f 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -72,10 +72,12 @@ static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data) { struct kvm_pmc *pmc; u8 old_fixed_ctr_ctrl = pmu->fixed_ctr_ctrl; - int i; + int s = INTEL_PMC_IDX_FIXED; pmu->fixed_ctr_ctrl = data; - for (i = 0; i < pmu->nr_arch_fixed_counters; i++) { + for_each_set_bit_from(s, pmu->all_valid_pmc_idx, + INTEL_PMC_IDX_FIXED + INTEL_PMC_MAX_FIXED) { + int i = s - INTEL_PMC_IDX_FIXED; u8 new_ctrl = fixed_ctrl_field(data, i); u8 old_ctrl = fixed_ctrl_field(old_fixed_ctr_ctrl, i); @@ -132,7 +134,7 @@ static bool intel_is_valid_rdpmc_ecx(struct kvm_vcpu *vcpu, unsigned int idx) idx &= ~(3u << 30); - return fixed ? idx < pmu->nr_arch_fixed_counters + return fixed ? fixed_ctr_is_supported(pmu, idx) : idx < pmu->nr_arch_gp_counters; } @@ -144,16 +146,17 @@ static struct kvm_pmc *intel_rdpmc_ecx_to_pmc(struct kvm_vcpu *vcpu, struct kvm_pmc *counters; unsigned int num_counters; + if (!intel_is_valid_rdpmc_ecx(vcpu, idx)) + return NULL; + idx &= ~(3u << 30); if (fixed) { counters = pmu->fixed_counters; - num_counters = pmu->nr_arch_fixed_counters; + num_counters = KVM_PMC_MAX_FIXED; } else { counters = pmu->gp_counters; num_counters = pmu->nr_arch_gp_counters; } - if (idx >= num_counters) - return NULL; *mask &= pmu->counter_bitmask[fixed ? KVM_PMC_FIXED : KVM_PMC_GP]; return &counters[array_index_nospec(idx, num_counters)]; } @@ -352,6 +355,7 @@ static u64 intel_pmu_global_inuse_emulation(struct kvm_pmu *pmu) { u64 data = 0; int i; + int s = INTEL_PMC_IDX_FIXED; for (i = 0; i < pmu->nr_arch_gp_counters; i++) { struct kvm_pmc *pmc = &pmu->gp_counters[i]; @@ -372,7 +376,10 @@ static u64 intel_pmu_global_inuse_emulation(struct kvm_pmu *pmu) data |= MSR_CORE_PERF_GLOBAL_INUSE_PMI; } - for (i = 0; i < pmu->nr_arch_fixed_counters; i++) { + for_each_set_bit_from(s, pmu->all_valid_pmc_idx, + INTEL_PMC_IDX_FIXED + INTEL_PMC_MAX_FIXED) { + i = s - INTEL_PMC_IDX_FIXED; + /* * IA32_PERF_GLOBAL_INUSE.FCi_InUse[bit (i + 32)]: This bit * reflects the logical state of @@ -380,7 +387,7 @@ static u64 intel_pmu_global_inuse_emulation(struct kvm_pmu *pmu) */ if (pmu->fixed_ctr_ctrl & intel_fixed_bits_by_idx(i, INTEL_FIXED_0_KERNEL | INTEL_FIXED_0_USER)) - data |= 1ULL << (i + INTEL_PMC_IDX_FIXED); + data |= 1ULL << s; /* * IA32_PERF_GLOBAL_INUSE.PMI_InUse[bit 63]: This bit is set if * IA32_FIXED_CTR_CTRL.ENi_PMI, i = 0, 1, 2 is set. @@ -575,12 +582,14 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) static void setup_fixed_pmc_eventsel(struct kvm_pmu *pmu) { - int i; + int s = INTEL_PMC_IDX_FIXED; BUILD_BUG_ON(ARRAY_SIZE(fixed_pmc_events) != KVM_PMC_MAX_FIXED); - for (i = 0; i < pmu->nr_arch_fixed_counters; i++) { - int index = array_index_nospec(i, KVM_PMC_MAX_FIXED); + for_each_set_bit_from(s, pmu->all_valid_pmc_idx, + INTEL_PMC_IDX_FIXED + INTEL_PMC_MAX_FIXED) { + int index = array_index_nospec(s - INTEL_PMC_IDX_FIXED, + KVM_PMC_MAX_FIXED); struct kvm_pmc *pmc = &pmu->fixed_counters[index]; u32 event = fixed_pmc_events[index]; @@ -601,7 +610,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) int i; pmu->nr_arch_gp_counters = 0; - pmu->nr_arch_fixed_counters = 0; pmu->counter_bitmask[KVM_PMC_GP] = 0; pmu->counter_bitmask[KVM_PMC_FIXED] = 0; pmu->version = 0; @@ -643,11 +651,22 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) pmu->available_event_types = ~entry->ebx & ((1ull << eax.split.mask_length) - 1); - if (pmu->version == 1) { - pmu->nr_arch_fixed_counters = 0; - } else { - pmu->nr_arch_fixed_counters = min_t(int, edx.split.num_counters_fixed, - kvm_pmu_cap.num_counters_fixed); + counter_mask = ~(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) { + for (i = 0; i < kvm_pmu_cap.num_counters_fixed; i++) { + /* + * FxCtr[i]_is_supported := + * CPUID.0xA.ECX[i] || EDX[4:0] > i + */ + if (!(entry->ecx & BIT_ULL(i) || edx.split.num_counters_fixed > i)) + continue; + + set_bit(INTEL_PMC_IDX_FIXED + i, pmu->all_valid_pmc_idx); + pmu->fixed_ctr_ctrl_mask &= ~(0xbull << (i * 4)); + counter_mask &= ~BIT_ULL(INTEL_PMC_IDX_FIXED + i); + } edx.split.bit_width_fixed = min_t(int, edx.split.bit_width_fixed, kvm_pmu_cap.bit_width_fixed); pmu->counter_bitmask[KVM_PMC_FIXED] = @@ -655,10 +674,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) setup_fixed_pmc_eventsel(pmu); } - for (i = 0; i < pmu->nr_arch_fixed_counters; i++) - pmu->fixed_ctr_ctrl_mask &= ~(0xbull << (i * 4)); - counter_mask = ~(((1ull << pmu->nr_arch_gp_counters) - 1) | - (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED)); pmu->global_ctrl_mask = counter_mask; /* @@ -684,11 +699,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) pmu->raw_event_mask |= (HSW_IN_TX|HSW_IN_TX_CHECKPOINTED); } - 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 = vcpu_get_perf_capabilities(vcpu); if (cpuid_model_is_consistent(vcpu) && (perf_capabilities & PMU_CAP_LBR_FMT)) @@ -701,9 +711,14 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) if (perf_capabilities & PERF_CAP_PEBS_FORMAT) { if (perf_capabilities & PERF_CAP_PEBS_BASELINE) { + int s = INTEL_PMC_IDX_FIXED; + int e = INTEL_PMC_IDX_FIXED + INTEL_PMC_MAX_FIXED; + pmu->pebs_enable_mask = counter_mask; pmu->reserved_bits &= ~ICL_EVENTSEL_ADAPTIVE; - for (i = 0; i < pmu->nr_arch_fixed_counters; i++) { + + for_each_set_bit_from(s, pmu->all_valid_pmc_idx, e) { + i = s - INTEL_PMC_IDX_FIXED; pmu->fixed_ctr_ctrl_mask &= ~(1ULL << (INTEL_PMC_IDX_FIXED + i * 4)); } From patchwork Thu Sep 21 08:29:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Xiong Y" X-Patchwork-Id: 13394524 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 E221FE7D0A8 for ; Thu, 21 Sep 2023 20:27:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231986AbjIUU1U (ORCPT ); Thu, 21 Sep 2023 16:27:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37976 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231946AbjIUU0r (ORCPT ); Thu, 21 Sep 2023 16:26:47 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A02DA266FB for ; Thu, 21 Sep 2023 10:50:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695318600; x=1726854600; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=IucKdVxoy2TAG2qynrJ/+2Adc5kZGk23C/Tq5g823xs=; b=XNEod4OJoS1ctMsSTqeGyCcEgdNLifgZeQ5iM+SrAKGpEf3BSmD6y+uT Ax9Y7qIGnieNs+3bVxKlMHEhFIP/qrMG5TuQxTPyho6fCPdW2vKnoGZrn uGRMRJSpcWS+ioC6R9o1h1lxezp4C1UHBrAm4NRMqz0cMjoqlfYQpcjsG y9Bmx33kaxLNz1aSt0rOUNuOUdRQWTZC326b8n4bVUKxL+cDwUPefJIfy IlrGGCEYLlg4LovYOizLM9+Sa6jlWHTLIHa+2gfLB0fd9VsG0Ioi6HoFE 8Xhppa2EEMRr9zN8C8sCMeN3Plv4t+Cg0fYtIJPsqVv2GdZKBNg400I8v g==; X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="359841378" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="359841378" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:31:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="747001164" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="747001164" Received: from dorasunx-mobl1.ccr.corp.intel.com (HELO xiongzha-desk1.ccr.corp.intel.com) ([10.255.30.47]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:31:16 -0700 From: Xiong Zhang To: kvm@vger.kernel.org Cc: seanjc@google.com, like.xu.linux@gmail.com, dapeng1.mi@linux.intel.com, zhiyuan.lv@intel.com, zhenyu.z.wang@intel.com, kan.liang@intel.com, Xiong Zhang Subject: [PATCH v2 7/9] KVM: x86/pmu: Add fixed counter enumeration for pmu v5 Date: Thu, 21 Sep 2023 16:29:55 +0800 Message-Id: <20230921082957.44628-8-xiong.y.zhang@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230921082957.44628-1-xiong.y.zhang@intel.com> References: <20230921082957.44628-1-xiong.y.zhang@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org With Arch PMU v5, CPUID.0AH.ECX is a bit mask which enumerates the supported Fixed Counters. If bit 'i' is set, it implies that Fixed Counter 'i' is supported. This commit add CPUID.0AH.ECX emulation for vPMU version 5, KVM support Fixed Counter enumeration starting from 0 by default, user could modify it through SET_CPUID2 ioctl. When perf driver supports fixed counter bitmap and exports it, KVM will get it from perf driver, and set it as KVM supported CPUID.0AH.ECX. Signed-off-by: Xiong Zhang --- arch/x86/kvm/cpuid.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 0544e30b4946..e10844e2f211 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1004,7 +1004,15 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) entry->eax = eax.full; entry->ebx = kvm_pmu_cap.events_mask; - entry->ecx = 0; + if (kvm_pmu_cap.version < 5) + entry->ecx = 0; + else + /* + * Todo: When perf driver supports Fixed counter bitmap + * and export it, KVM will get it from perf driver and set + * it into entry->ecx. + */ + entry->ecx = (1ULL << kvm_pmu_cap.num_counters_fixed) - 1; entry->edx = edx.full; break; } From patchwork Thu Sep 21 08:29:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Xiong Y" X-Patchwork-Id: 13394348 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 D0779E7D0A9 for ; Thu, 21 Sep 2023 19:04:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231267AbjIUTEb (ORCPT ); Thu, 21 Sep 2023 15:04:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42916 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229648AbjIUTEG (ORCPT ); Thu, 21 Sep 2023 15:04:06 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 70DE04E5F5 for ; Thu, 21 Sep 2023 10:50:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695318601; x=1726854601; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=PnYyz1ivEBWn1+J3Aq3LJfdHtekQpCKjYAwRui0RndI=; b=IvAgzJTyKkClhqY2sF6yKA0iDq79kOcwhc7T5kiHXQ9Ps4eAJaE9jz/i pdwtcIQqeGZ3WTWYwmn18qpTUVVBoW/OHgwC/iZ4wO6FNiD1YSnB9qI5S 3RbfwV9PyhflaYR/SaM2mumLNX097rrdBr81uJc842iRUME9mVJsbvVUo /UyZ1Kvg1dbLCICGMi8NESQmODUvxeGxNPYrOJvyUaxrxqxiIVK3kF5jT TBI5BIDHsUEQZQX2hOeVDrNmkqPAc7fg/ApO7dghjyPRXz7LkxqivjBaP QKTqJHIS3yWo51x4ZZnOQErXUPMnAbo13YQsBQPX5fll45QNFHAo2DUJO Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="359841382" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="359841382" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:31:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="747001182" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="747001182" Received: from dorasunx-mobl1.ccr.corp.intel.com (HELO xiongzha-desk1.ccr.corp.intel.com) ([10.255.30.47]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:31:21 -0700 From: Xiong Zhang To: kvm@vger.kernel.org Cc: seanjc@google.com, like.xu.linux@gmail.com, dapeng1.mi@linux.intel.com, zhiyuan.lv@intel.com, zhenyu.z.wang@intel.com, kan.liang@intel.com, Xiong Zhang Subject: [PATCH v2 8/9] KVM: x86/pmu: Upgrade pmu version to 5 on intel processor Date: Thu, 21 Sep 2023 16:29:56 +0800 Message-Id: <20230921082957.44628-9-xiong.y.zhang@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230921082957.44628-1-xiong.y.zhang@intel.com> References: <20230921082957.44628-1-xiong.y.zhang@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Modern intel processors have supported Architectural Performance Monitoring Version 5, this commit upgrade Intel vcpu's vPMU version from 2 to 5. Go through PMU features from version 3 to 5, the following features are not supported: 1. AnyThread counting: it is added in v3, and deprecated in v5. 2. Streamed Freeze_PerfMon_On_PMI in v4, since legacy Freeze_PerMon_ON_PMI isn't supported, the new one won't be supported neither. 3. IA32_PERF_GLOBAL_STATUS.ASCI[bit 60]: Related to SGX, and will be emulated by SGX developer later. 4. Domain Separation in v5. When INV flag in IA32_PERFEVTSELx is used, a counter stops counting when logical processor exits the C0 ACPI C-state. KVM has little information about guest ACPI C-state. When guest enable unsupported features through WRMSR, KVM will inject a #GP into guest. Signed-off-by: Xiong Zhang --- Changelog: v1->v2: kvm_pmu_cap.version will not exceed 2 for AMD, no need to differentiate between Intel and AMD. --- arch/x86/kvm/pmu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h index 4bab4819ea6c..b416094917fd 100644 --- a/arch/x86/kvm/pmu.h +++ b/arch/x86/kvm/pmu.h @@ -215,7 +215,7 @@ static inline void kvm_init_pmu_capability(const struct kvm_pmu_ops *pmu_ops) return; } - kvm_pmu_cap.version = min(kvm_pmu_cap.version, 2); + kvm_pmu_cap.version = min(kvm_pmu_cap.version, 5); kvm_pmu_cap.num_counters_gp = min(kvm_pmu_cap.num_counters_gp, pmu_ops->MAX_NR_GP_COUNTERS); kvm_pmu_cap.num_counters_fixed = min(kvm_pmu_cap.num_counters_fixed, From patchwork Thu Sep 21 08:29:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Xiong Y" X-Patchwork-Id: 13394349 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 0A20EE7D0A2 for ; Thu, 21 Sep 2023 19:04:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230394AbjIUTEa (ORCPT ); Thu, 21 Sep 2023 15:04:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42926 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229495AbjIUTEG (ORCPT ); Thu, 21 Sep 2023 15:04:06 -0400 Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 70C8C4E5D8 for ; Thu, 21 Sep 2023 10:50:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1695318601; x=1726854601; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=W9fNFA8xcVEA/iV9+MsAkTcTdm8KC9i+ViXMaeaufNc=; b=Cb0EFyzwgXav3Q2zhKKxuNBmqvZ9nO/upBefVn2yZpQMeTFb0929xvB8 x2r6AGgYWuhwYhSgrpsbNhV0HTEVOqtGhyv0TOJnDudvqsySWQqzlXHeC wN8TNMPfE2Et6VmtwB9XzQX2dj62ykRmhkuVV7u4Rg5PFUOtUVFv3/2yV bZoVqnkpm4GWuh0LxEij+jwGPxdudoim1zyryYHBapJ60ToFuS95JMEgS tvGGdo6GDKrw2XbtLSHdNGQKrexkCg/o2LXIW+wKJYbPsOVGV4JAr8RhE XMGsioqPjdBnrVovOAQHgKVKwVBplws8vHqfGu0+LrW0ZxtcANwYRjM5z A==; X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="359841386" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="359841386" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:31:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10839"; a="747001191" X-IronPort-AV: E=Sophos;i="6.03,164,1694761200"; d="scan'208";a="747001191" Received: from dorasunx-mobl1.ccr.corp.intel.com (HELO xiongzha-desk1.ccr.corp.intel.com) ([10.255.30.47]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2023 01:31:25 -0700 From: Xiong Zhang To: kvm@vger.kernel.org Cc: seanjc@google.com, like.xu.linux@gmail.com, dapeng1.mi@linux.intel.com, zhiyuan.lv@intel.com, zhenyu.z.wang@intel.com, kan.liang@intel.com, Xiong Zhang Subject: [PATCH v2 9/9] KVM: selftests: Add fixed counters enumeration test case Date: Thu, 21 Sep 2023 16:29:57 +0800 Message-Id: <20230921082957.44628-10-xiong.y.zhang@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230921082957.44628-1-xiong.y.zhang@intel.com> References: <20230921082957.44628-1-xiong.y.zhang@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org vPMU v5 adds fixed counter enumeration, which allows user space to specify which fixed counters are supported through emulated CPUID.0Ah.ECX. This commit adds a test case which specify the max fixed counter supported only, so guest can access the max fixed counter only, #GP exception will be happen once guest access other fixed counters. Signed-off-by: Xiong Zhang --- .../selftests/kvm/x86_64/vmx_pmu_caps_test.c | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c b/tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c index ebbcb0a3f743..c690cb389ae2 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_pmu_caps_test.c @@ -18,6 +18,8 @@ #include "kvm_util.h" #include "vmx.h" +uint8_t fixed_counter_num; + union perf_capabilities { struct { u64 lbr_format:6; @@ -233,6 +235,81 @@ static void test_lbr_perf_capabilities(union perf_capabilities host_cap) kvm_vm_free(vm); } +static void guest_v5_code(void) +{ + uint8_t vector, i; + uint64_t val; + + for (i = 0; i < fixed_counter_num; i++) { + vector = rdmsr_safe(MSR_CORE_PERF_FIXED_CTR0 + i, &val); + + /* + * Only the max fixed counter is supported, #GP will be generated + * when guest access other fixed counters. + */ + if (i == fixed_counter_num - 1) + __GUEST_ASSERT(vector != GP_VECTOR, + "Max Fixed counter is accessible, but get #GP"); + else + __GUEST_ASSERT(vector == GP_VECTOR, + "Fixed counter isn't accessible, but access is ok"); + } + + GUEST_DONE(); +} + +#define PMU_NR_FIXED_COUNTERS_MASK 0x1f + +static void test_fixed_counter_enumeration(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + int r; + struct kvm_cpuid_entry2 *ent; + struct ucall uc; + uint32_t fixed_counter_bit_mask; + + if (kvm_cpu_property(X86_PROPERTY_PMU_VERSION) < 5) + return; + + vm = vm_create_with_one_vcpu(&vcpu, guest_v5_code); + vm_init_descriptor_tables(vm); + vcpu_init_descriptor_tables(vcpu); + + ent = vcpu_get_cpuid_entry(vcpu, 0xa); + fixed_counter_num = ent->edx & PMU_NR_FIXED_COUNTERS_MASK; + TEST_ASSERT(fixed_counter_num > 0, "fixed counter isn't supported"); + fixed_counter_bit_mask = (1ul << fixed_counter_num) - 1; + TEST_ASSERT(ent->ecx == fixed_counter_bit_mask, + "cpuid.0xa.ecx != %x", fixed_counter_bit_mask); + + if (fixed_counter_num == 1) { + kvm_vm_free(vm); + return; + } + + /* Support the max Fixed Counter only */ + ent->ecx = 1UL << (fixed_counter_num - 1); + ent->edx &= ~(u32)PMU_NR_FIXED_COUNTERS_MASK; + + r = __vcpu_set_cpuid(vcpu); + TEST_ASSERT(!r, "Setting modified cpuid.0xa.ecx and edx failed"); + + vcpu_run(vcpu); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + break; + case UCALL_DONE: + break; + default: + TEST_FAIL("Unexpected ucall: %lu", uc.cmd); + } + + kvm_vm_free(vm); +} + int main(int argc, char *argv[]) { union perf_capabilities host_cap; @@ -253,4 +330,6 @@ int main(int argc, char *argv[]) test_immutable_perf_capabilities(host_cap); test_guest_wrmsr_perf_capabilities(host_cap); test_lbr_perf_capabilities(host_cap); + + test_fixed_counter_enumeration(); }