Message ID | 20221226111710.51831-2-likexu@tencent.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4e01:0:0:0:0:0 with SMTP id p1csp858371wrt; Mon, 26 Dec 2022 03:19:44 -0800 (PST) X-Google-Smtp-Source: AMrXdXsRL+3cakSvTZl7l5tmELUu8pMz20gSV21Ree0pCYUGp9eBEJcoaS/0oTWFjECjCmvvYDpm X-Received: by 2002:aa7:d04d:0:b0:47d:b4e6:a631 with SMTP id n13-20020aa7d04d000000b0047db4e6a631mr15221000edo.7.1672053583999; Mon, 26 Dec 2022 03:19:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1672053583; cv=none; d=google.com; s=arc-20160816; b=lRgxGjox+W74etmdy9USOirgQx3zs4w0EBsqD+0VlF7jQaHEe4e00IepXYHdV9xR9Y pNThnl5PjqS93/fVXWE3QzFtswt3/2W6LlfF5cmZxuOFdTry+oW/4Dqalzlyq0kAfPlZ RPCfFfBb2RsOfE6fZdFVj8F+ouhAR2A07i5Xqz2Vwq9iFX9bQL4YZbSkMXNn3oYWKY0s W1tMVAiiPMWhLwHH2aFIgkhdDSbN2iievSGfYn39XL8ZCamHuwPcaIVZ5nKEb3tDQnU2 wzpQBLfvuBQRtnTehzMYCnaAwxtJcFBGH/RUOlLcpHaJ+wGGsfz+DhMxAevBkcemFJOJ dAYg== 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=Cyx9dY3OzBvOxLsd6YY1TSqE0kQ174iZYU6DkzM6T5g=; b=zynhXVZOR48EvrqNUypRnDEknBBXxrBqiFtg0OKpzFIa+0SLLvzP/HTDj1/1JkDXza VFOQhmT5VXy3yEtBFDfuGj+/P4XHzwH1i/fykBCeKALoZ1pLOCq0FJjhwB4XXlJ/dCiu NYR2qV48gZlm2ynfbrrISO4w0yIfrWuRJIyim52xj/vH2OPc4DrArgCpElaH7Pr2PcZ4 DocOY6qp2HwQ/KvnpGx+Dhpkr8B6P1h+dJgLduDXNhRAunMLGiGtFfGFfKRe/GVu8/Hi TFnE7cXzyVSPYRZAOUegbWiMT5vQ4QxNmIem8fb8WQ0bUGD8kIJz6Jr+mCA3IYPmb81E GNVQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=IOAhnnml; 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=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i18-20020a05640242d200b0047f2b102941si10596605edc.361.2022.12.26.03.19.20; Mon, 26 Dec 2022 03:19:43 -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=@gmail.com header.s=20210112 header.b=IOAhnnml; 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=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231712AbiLZLRi (ORCPT <rfc822;eddaouddi.ayoub@gmail.com> + 99 others); Mon, 26 Dec 2022 06:17:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56466 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231738AbiLZLRd (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Mon, 26 Dec 2022 06:17:33 -0500 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9E94562CB; Mon, 26 Dec 2022 03:17:32 -0800 (PST) Received: by mail-pl1-x635.google.com with SMTP id b2so10490036pld.7; Mon, 26 Dec 2022 03:17:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Cyx9dY3OzBvOxLsd6YY1TSqE0kQ174iZYU6DkzM6T5g=; b=IOAhnnmlAmDC8ZsvQQvXRZns9yfUaGkgc4DCIh8yVpCdRHbZMQ2AjgwWu/I0tTUmu7 w/8DXg2bRGVIML1f4BXjYv8Az2s1oN+jRAWm/awGXBYy6AdcL7V2kSbcP2eOcnZfL5w0 Waf76luqWB3mKN4yZ4l+x8y/b7cED3OfQNC1auuXdEbhqMhMv1vb5t+KSJGYnEixVuXF 7VRhS6VMR3cMP1or/g8MEcfeN5dd5sguTy2rLp047Od8JpOQaYUS4pINPoe+7Wv8IKDe +3OIUcyG2fjz0mbdXO9n4xk7beFXIL3ILMV/X1g0yIp/x3jcGvajXHVE6jiKdjo33bOR CodA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Cyx9dY3OzBvOxLsd6YY1TSqE0kQ174iZYU6DkzM6T5g=; b=RaN2vpJxZFIwfVLVQ4cJaeytzKwEsC7ObL1CkBOgq1VxOPwo8YtUIMgBijTQwdifz7 2xUDIkmzRA1G4a2HYqk6STQWe+mARRGgCoBLH5sMPn5I1Bc8Vw2/khz/3S6oLtwPQTPb M97tNe+fXlomUHbF/EefB571zYRO/SL2Wzmwtph13FzJJ6/b7NMIT1GLj/rri2Y0x5sB iq0ua1J4RmiRI0HdfYueWZ69u5bO1x+9fJgQAq4xvs564zFKhkmTjbCaVLgBCJYJ8oFy a1eS2+AG5mWueMkUjsczbCW6hlO2uyeglU0do+/vfZLVvfHN5LSvTKrC+n4Ojiz3F8AP V3xA== X-Gm-Message-State: AFqh2kpVxPvQtcVX8qxaKxz2YMcHLT//pudvVAZZf634U7SWXipXUHym 6bYcF3LRPk6i7WT2UtSteqw= X-Received: by 2002:a17:90a:598f:b0:21a:1b9b:139c with SMTP id l15-20020a17090a598f00b0021a1b9b139cmr20716416pji.47.1672053452068; Mon, 26 Dec 2022 03:17:32 -0800 (PST) Received: from localhost.localdomain ([103.7.29.32]) by smtp.gmail.com with ESMTPSA id dw6-20020a17090b094600b00223f495dc28sm6281490pjb.14.2022.12.26.03.17.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Dec 2022 03:17:31 -0800 (PST) From: Like Xu <like.xu.linux@gmail.com> X-Google-Original-From: Like Xu <likexu@tencent.com> To: Paolo Bonzini <pbonzini@redhat.com> Cc: Sean Christopherson <seanjc@google.com>, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Aaron Lewis <aaronlewis@google.com> Subject: [PATCH 1/3] KVM: x86: Omit PMU MSRs from KVM_GET_MSR_INDEX_LIST if !enable_pmu Date: Mon, 26 Dec 2022 19:17:08 +0800 Message-Id: <20221226111710.51831-2-likexu@tencent.com> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20221226111710.51831-1-likexu@tencent.com> References: <20221226111710.51831-1-likexu@tencent.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1753275259005154650?= X-GMAIL-MSGID: =?utf-8?q?1753275259005154650?= |
Series |
KVM: x86/pmu: Fix accesses to PMU MSRs in two corner cases
|
|
Commit Message
Like Xu
Dec. 26, 2022, 11:17 a.m. UTC
From: Like Xu <likexu@tencent.com> When the PMU is disabled, don't bother sharing the PMU MSRs with userspace through KVM_GET_MSR_INDEX_LIST. Instead, filter them out so userspace doesn't have to keep track of them. Note that 'enable_pmu' is read-only, so userspace has no control over whether the PMU MSRs are included in the list or not. Suggested-by: Sean Christopherson <seanjc@google.com> Co-developed-by: Aaron Lewis <aaronlewis@google.com> Signed-off-by: Aaron Lewis <aaronlewis@google.com> Signed-off-by: Like Xu <likexu@tencent.com> --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/x86.c | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-)
Comments
On 12/26/2022 7:17 PM, Like Xu wrote: > From: Like Xu <likexu@tencent.com> > > When the PMU is disabled, don't bother sharing the PMU MSRs with > userspace through KVM_GET_MSR_INDEX_LIST. Instead, filter them out > so userspace doesn't have to keep track of them. > > Note that 'enable_pmu' is read-only, so userspace has no control over > whether the PMU MSRs are included in the list or not. > > Suggested-by: Sean Christopherson <seanjc@google.com> > Co-developed-by: Aaron Lewis <aaronlewis@google.com> > Signed-off-by: Aaron Lewis <aaronlewis@google.com> > Signed-off-by: Like Xu <likexu@tencent.com> > --- > arch/x86/include/asm/kvm_host.h | 1 + > arch/x86/kvm/x86.c | 22 ++++++++++++++++++++-- > 2 files changed, 21 insertions(+), 2 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index f35f1ff4427b..2ed710b393eb 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -514,6 +514,7 @@ struct kvm_pmc { > #define MSR_ARCH_PERFMON_PERFCTR_MAX (MSR_ARCH_PERFMON_PERFCTR0 + KVM_INTEL_PMC_MAX_GENERIC - 1) > #define MSR_ARCH_PERFMON_EVENTSEL_MAX (MSR_ARCH_PERFMON_EVENTSEL0 + KVM_INTEL_PMC_MAX_GENERIC - 1) > #define KVM_PMC_MAX_FIXED 3 > +#define MSR_ARCH_PERFMON_FIXED_CTR_MAX (MSR_ARCH_PERFMON_FIXED_CTR0 + KVM_PMC_MAX_FIXED - 1) > #define KVM_AMD_PMC_MAX_GENERIC 6 > struct kvm_pmu { > unsigned nr_arch_gp_counters; > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 5c3ce39cdccb..f570367463c8 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -7054,15 +7054,32 @@ static void kvm_init_msr_list(void) > continue; > break; > case MSR_ARCH_PERFMON_PERFCTR0 ... MSR_ARCH_PERFMON_PERFCTR_MAX: > - if (msrs_to_save_all[i] - MSR_ARCH_PERFMON_PERFCTR0 >= > + if (!enable_pmu || msrs_to_save_all[i] - MSR_ARCH_PERFMON_PERFCTR0 >= > min(KVM_INTEL_PMC_MAX_GENERIC, kvm_pmu_cap.num_counters_gp)) > continue; > break; > case MSR_ARCH_PERFMON_EVENTSEL0 ... MSR_ARCH_PERFMON_EVENTSEL_MAX: > - if (msrs_to_save_all[i] - MSR_ARCH_PERFMON_EVENTSEL0 >= > + if (!enable_pmu || msrs_to_save_all[i] - MSR_ARCH_PERFMON_EVENTSEL0 >= > min(KVM_INTEL_PMC_MAX_GENERIC, kvm_pmu_cap.num_counters_gp)) > continue; > break; > + case MSR_ARCH_PERFMON_FIXED_CTR0 ... MSR_ARCH_PERFMON_FIXED_CTR_MAX: > + if (!enable_pmu || msrs_to_save_all[i] - MSR_ARCH_PERFMON_FIXED_CTR0 >= > + min(KVM_PMC_MAX_FIXED, kvm_pmu_cap.num_counters_fixed)) > + continue; > + break; > + case MSR_F15H_PERF_CTL0 ... MSR_F15H_PERF_CTR5: > + case MSR_K7_EVNTSEL0 ... MSR_K7_PERFCTR3: > + case MSR_CORE_PERF_FIXED_CTR_CTRL: > + case MSR_CORE_PERF_GLOBAL_STATUS: > + case MSR_CORE_PERF_GLOBAL_CTRL: > + case MSR_CORE_PERF_GLOBAL_OVF_CTRL: > + case MSR_IA32_DS_AREA: > + case MSR_IA32_PEBS_ENABLE: > + case MSR_PEBS_DATA_CFG: > + if (!enable_pmu) > + continue; > + break; I prefer use a helper to wrap the hunk of PMU msr checks and move the helper to the "default" branch of switch, it makes the code looks nicer: default: if(!enable_pmu && !kvm_pmu_valid_msrlist(msr)) continue; > case MSR_IA32_XFD: > case MSR_IA32_XFD_ERR: > if (!kvm_cpu_cap_has(X86_FEATURE_XFD)) > @@ -13468,3 +13485,4 @@ static void __exit kvm_x86_exit(void) > */ > } > module_exit(kvm_x86_exit); > + Extra newline.
On 12/27/2022 8:59 AM, Yang, Weijiang wrote: > On 12/26/2022 7:17 PM, Like Xu wrote: >> From: Like Xu <likexu@tencent.com> >> >> When the PMU is disabled, don't bother sharing the PMU MSRs with >> userspace through KVM_GET_MSR_INDEX_LIST. Instead, filter them out >> so userspace doesn't have to keep track of them. >> >> Note that 'enable_pmu' is read-only, so userspace has no control over >> whether the PMU MSRs are included in the list or not. [...] >> + case MSR_ARCH_PERFMON_FIXED_CTR0 ... MSR_ARCH_PERFMON_FIXED_CTR_MAX: >> + if (!enable_pmu || msrs_to_save_all[i] - MSR_ARCH_PERFMON_FIXED_CTR0 >= >> + min(KVM_PMC_MAX_FIXED, kvm_pmu_cap.num_counters_fixed)) >> + continue; >> + break; >> + case MSR_F15H_PERF_CTL0 ... MSR_F15H_PERF_CTR5: >> + case MSR_K7_EVNTSEL0 ... MSR_K7_PERFCTR3: >> + case MSR_CORE_PERF_FIXED_CTR_CTRL: >> + case MSR_CORE_PERF_GLOBAL_STATUS: >> + case MSR_CORE_PERF_GLOBAL_CTRL: >> + case MSR_CORE_PERF_GLOBAL_OVF_CTRL: >> + case MSR_IA32_DS_AREA: >> + case MSR_IA32_PEBS_ENABLE: >> + case MSR_PEBS_DATA_CFG: >> + if (!enable_pmu) >> + continue; >> + break; > > I prefer use a helper to wrap the hunk of PMU msr checks and move the > helper to > > the "default" branch of switch, it makes the code looks nicer: > > default: > > if(!enable_pmu && !kvm_pmu_valid_msrlist(msr)) Typo, should be: if (!enable_pmu || !kvm_pmu_valid_msrlist(msr)) > > continue; > > >> case MSR_IA32_XFD: >> case MSR_IA32_XFD_ERR: >> if (!kvm_cpu_cap_has(X86_FEATURE_XFD)) >> @@ -13468,3 +13485,4 @@ static void __exit kvm_x86_exit(void) >> */ >> } >> module_exit(kvm_x86_exit); >> + > > Extra newline. > > >
On Tue, Dec 27, 2022, Yang, Weijiang wrote: > > On 12/26/2022 7:17 PM, Like Xu wrote: > > From: Like Xu <likexu@tencent.com> > > > > When the PMU is disabled, don't bother sharing the PMU MSRs with > > userspace through KVM_GET_MSR_INDEX_LIST. Instead, filter them out > > so userspace doesn't have to keep track of them. > > > > Note that 'enable_pmu' is read-only, so userspace has no control over > > whether the PMU MSRs are included in the list or not. > > > > Suggested-by: Sean Christopherson <seanjc@google.com> > > Co-developed-by: Aaron Lewis <aaronlewis@google.com> > > Signed-off-by: Aaron Lewis <aaronlewis@google.com> > > Signed-off-by: Like Xu <likexu@tencent.com> > > --- > > arch/x86/include/asm/kvm_host.h | 1 + > > arch/x86/kvm/x86.c | 22 ++++++++++++++++++++-- > > 2 files changed, 21 insertions(+), 2 deletions(-) > > > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > > index f35f1ff4427b..2ed710b393eb 100644 > > --- a/arch/x86/include/asm/kvm_host.h > > +++ b/arch/x86/include/asm/kvm_host.h > > @@ -514,6 +514,7 @@ struct kvm_pmc { > > #define MSR_ARCH_PERFMON_PERFCTR_MAX (MSR_ARCH_PERFMON_PERFCTR0 + KVM_INTEL_PMC_MAX_GENERIC - 1) > > #define MSR_ARCH_PERFMON_EVENTSEL_MAX (MSR_ARCH_PERFMON_EVENTSEL0 + KVM_INTEL_PMC_MAX_GENERIC - 1) > > #define KVM_PMC_MAX_FIXED 3 > > +#define MSR_ARCH_PERFMON_FIXED_CTR_MAX (MSR_ARCH_PERFMON_FIXED_CTR0 + KVM_PMC_MAX_FIXED - 1) > > #define KVM_AMD_PMC_MAX_GENERIC 6 > > struct kvm_pmu { > > unsigned nr_arch_gp_counters; > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > > index 5c3ce39cdccb..f570367463c8 100644 > > --- a/arch/x86/kvm/x86.c > > +++ b/arch/x86/kvm/x86.c > > @@ -7054,15 +7054,32 @@ static void kvm_init_msr_list(void) > > continue; > > break; > > case MSR_ARCH_PERFMON_PERFCTR0 ... MSR_ARCH_PERFMON_PERFCTR_MAX: > > - if (msrs_to_save_all[i] - MSR_ARCH_PERFMON_PERFCTR0 >= > > + if (!enable_pmu || msrs_to_save_all[i] - MSR_ARCH_PERFMON_PERFCTR0 >= > > min(KVM_INTEL_PMC_MAX_GENERIC, kvm_pmu_cap.num_counters_gp)) > > continue; > > break; > > case MSR_ARCH_PERFMON_EVENTSEL0 ... MSR_ARCH_PERFMON_EVENTSEL_MAX: > > - if (msrs_to_save_all[i] - MSR_ARCH_PERFMON_EVENTSEL0 >= > > + if (!enable_pmu || msrs_to_save_all[i] - MSR_ARCH_PERFMON_EVENTSEL0 >= > > min(KVM_INTEL_PMC_MAX_GENERIC, kvm_pmu_cap.num_counters_gp)) > > continue; > > break; > > + case MSR_ARCH_PERFMON_FIXED_CTR0 ... MSR_ARCH_PERFMON_FIXED_CTR_MAX: > > + if (!enable_pmu || msrs_to_save_all[i] - MSR_ARCH_PERFMON_FIXED_CTR0 >= > > + min(KVM_PMC_MAX_FIXED, kvm_pmu_cap.num_counters_fixed)) The num_counters_fixed check is a separate change, no? > > + continue; > > + break; > > + case MSR_F15H_PERF_CTL0 ... MSR_F15H_PERF_CTR5: > > + case MSR_K7_EVNTSEL0 ... MSR_K7_PERFCTR3: > > + case MSR_CORE_PERF_FIXED_CTR_CTRL: > > + case MSR_CORE_PERF_GLOBAL_STATUS: > > + case MSR_CORE_PERF_GLOBAL_CTRL: > > + case MSR_CORE_PERF_GLOBAL_OVF_CTRL: > > + case MSR_IA32_DS_AREA: > > + case MSR_IA32_PEBS_ENABLE: > > + case MSR_PEBS_DATA_CFG: Rather than duplicating all list entries, which will be a maintenance problem, what about moving PMU MSRs to a separate array? Sample patch (that applies on top of the num_counters_fixed change) at the bottom. > > + if (!enable_pmu) > > + continue; > > + break; > > > I prefer use a helper to wrap the hunk of PMU msr checks and move the helper > to the "default" branch of switch, it makes the code looks nicer: > > default: That won't work as "default" is used to catch MSRs that always exist from the guest's perspective. And even if that weren't the case, I don't like the idea of utilizing "default" for PMU MSRs. The default=>PMU logic in kvm_{g,s}et_msr_common() isn't ideal, but it's the lesser of all evils. But in this case there's no need since common KVM code knows all possible MSRs that might be saved. --- arch/x86/kvm/x86.c | 161 ++++++++++++++++++++++++--------------------- 1 file changed, 87 insertions(+), 74 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1cc8036d9e91..87bb7024e18f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1419,7 +1419,7 @@ EXPORT_SYMBOL_GPL(kvm_emulate_rdpmc); * may depend on host virtualization features rather than host cpu features. */ -static const u32 msrs_to_save_all[] = { +static const u32 msrs_to_save_base[] = { MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, MSR_STAR, #ifdef CONFIG_X86_64 @@ -1436,6 +1436,10 @@ static const u32 msrs_to_save_all[] = { MSR_IA32_RTIT_ADDR3_A, MSR_IA32_RTIT_ADDR3_B, MSR_IA32_UMWAIT_CONTROL, + MSR_IA32_XFD, MSR_IA32_XFD_ERR, +}; + +static const u32 msrs_to_save_pmu[] = { MSR_ARCH_PERFMON_FIXED_CTR0, MSR_ARCH_PERFMON_FIXED_CTR1, MSR_ARCH_PERFMON_FIXED_CTR0 + 2, MSR_CORE_PERF_FIXED_CTR_CTRL, MSR_CORE_PERF_GLOBAL_STATUS, @@ -1460,11 +1464,10 @@ static const u32 msrs_to_save_all[] = { MSR_F15H_PERF_CTL3, MSR_F15H_PERF_CTL4, MSR_F15H_PERF_CTL5, MSR_F15H_PERF_CTR0, MSR_F15H_PERF_CTR1, MSR_F15H_PERF_CTR2, MSR_F15H_PERF_CTR3, MSR_F15H_PERF_CTR4, MSR_F15H_PERF_CTR5, - - MSR_IA32_XFD, MSR_IA32_XFD_ERR, }; -static u32 msrs_to_save[ARRAY_SIZE(msrs_to_save_all)]; +static u32 msrs_to_save[ARRAY_SIZE(msrs_to_save_base) + + ARRAY_SIZE(msrs_to_save_pmu)]; static unsigned num_msrs_to_save; static const u32 emulated_msrs_all[] = { @@ -7001,9 +7004,83 @@ long kvm_arch_vm_ioctl(struct file *filp, return r; } -static void kvm_init_msr_list(void) +static void kvm_probe_msr_to_save(u32 msr_index) { u32 dummy[2]; + + if (rdmsr_safe(msr_index, &dummy[0], &dummy[1])) + return; + + /* + * Even MSRs that are valid in the host may not be exposed to the + * guests in some cases. + */ + switch (msr_index) { + case MSR_IA32_BNDCFGS: + if (!kvm_mpx_supported()) + return; + break; + case MSR_TSC_AUX: + if (!kvm_cpu_cap_has(X86_FEATURE_RDTSCP) && + !kvm_cpu_cap_has(X86_FEATURE_RDPID)) + return; + break; + case MSR_IA32_UMWAIT_CONTROL: + if (!kvm_cpu_cap_has(X86_FEATURE_WAITPKG)) + return; + break; + case MSR_IA32_RTIT_CTL: + case MSR_IA32_RTIT_STATUS: + if (!kvm_cpu_cap_has(X86_FEATURE_INTEL_PT)) + return; + break; + case MSR_IA32_RTIT_CR3_MATCH: + if (!kvm_cpu_cap_has(X86_FEATURE_INTEL_PT) || + !intel_pt_validate_hw_cap(PT_CAP_cr3_filtering)) + return; + break; + case MSR_IA32_RTIT_OUTPUT_BASE: + case MSR_IA32_RTIT_OUTPUT_MASK: + if (!kvm_cpu_cap_has(X86_FEATURE_INTEL_PT) || + (!intel_pt_validate_hw_cap(PT_CAP_topa_output) && + !intel_pt_validate_hw_cap(PT_CAP_single_range_output))) + return; + break; + case MSR_IA32_RTIT_ADDR0_A ... MSR_IA32_RTIT_ADDR3_B: + if (!kvm_cpu_cap_has(X86_FEATURE_INTEL_PT) || + (msr_index - MSR_IA32_RTIT_ADDR0_A >= + intel_pt_validate_hw_cap(PT_CAP_num_address_ranges) * 2)) + return; + break; + case MSR_ARCH_PERFMON_PERFCTR0 ... MSR_ARCH_PERFMON_PERFCTR_MAX: + if (msr_index - MSR_ARCH_PERFMON_PERFCTR0 >= + min(KVM_INTEL_PMC_MAX_GENERIC, kvm_pmu_cap.num_counters_gp)) + return; + break; + case MSR_ARCH_PERFMON_EVENTSEL0 ... MSR_ARCH_PERFMON_EVENTSEL_MAX: + if (msr_index - MSR_ARCH_PERFMON_EVENTSEL0 >= + min(KVM_INTEL_PMC_MAX_GENERIC, kvm_pmu_cap.num_counters_gp)) + return; + break; + case MSR_ARCH_PERFMON_FIXED_CTR0 ... MSR_ARCH_PERFMON_FIXED_CTR_MAX: + if (msr_index - MSR_ARCH_PERFMON_FIXED_CTR0 >= + min(KVM_PMC_MAX_FIXED, kvm_pmu_cap.num_counters_fixed)) + return; + break; + case MSR_IA32_XFD: + case MSR_IA32_XFD_ERR: + if (!kvm_cpu_cap_has(X86_FEATURE_XFD)) + return; + break; + default: + break; + } + + msrs_to_save[num_msrs_to_save++] = msr_index; +} + +static void kvm_init_msr_list(void) +{ unsigned i; BUILD_BUG_ON_MSG(KVM_PMC_MAX_FIXED != 3, @@ -7013,76 +7090,12 @@ static void kvm_init_msr_list(void) num_emulated_msrs = 0; num_msr_based_features = 0; - for (i = 0; i < ARRAY_SIZE(msrs_to_save_all); i++) { - if (rdmsr_safe(msrs_to_save_all[i], &dummy[0], &dummy[1]) < 0) - continue; + for (i = 0; i < ARRAY_SIZE(msrs_to_save_base); i++) + kvm_probe_msr_to_save(msrs_to_save_base[i]); - /* - * Even MSRs that are valid in the host may not be exposed - * to the guests in some cases. - */ - switch (msrs_to_save_all[i]) { - case MSR_IA32_BNDCFGS: - if (!kvm_mpx_supported()) - continue; - break; - case MSR_TSC_AUX: - if (!kvm_cpu_cap_has(X86_FEATURE_RDTSCP) && - !kvm_cpu_cap_has(X86_FEATURE_RDPID)) - continue; - break; - case MSR_IA32_UMWAIT_CONTROL: - if (!kvm_cpu_cap_has(X86_FEATURE_WAITPKG)) - continue; - break; - case MSR_IA32_RTIT_CTL: - case MSR_IA32_RTIT_STATUS: - if (!kvm_cpu_cap_has(X86_FEATURE_INTEL_PT)) - continue; - break; - case MSR_IA32_RTIT_CR3_MATCH: - if (!kvm_cpu_cap_has(X86_FEATURE_INTEL_PT) || - !intel_pt_validate_hw_cap(PT_CAP_cr3_filtering)) - continue; - break; - case MSR_IA32_RTIT_OUTPUT_BASE: - case MSR_IA32_RTIT_OUTPUT_MASK: - if (!kvm_cpu_cap_has(X86_FEATURE_INTEL_PT) || - (!intel_pt_validate_hw_cap(PT_CAP_topa_output) && - !intel_pt_validate_hw_cap(PT_CAP_single_range_output))) - continue; - break; - case MSR_IA32_RTIT_ADDR0_A ... MSR_IA32_RTIT_ADDR3_B: - if (!kvm_cpu_cap_has(X86_FEATURE_INTEL_PT) || - msrs_to_save_all[i] - MSR_IA32_RTIT_ADDR0_A >= - intel_pt_validate_hw_cap(PT_CAP_num_address_ranges) * 2) - continue; - break; - case MSR_ARCH_PERFMON_PERFCTR0 ... MSR_ARCH_PERFMON_PERFCTR_MAX: - if (msrs_to_save_all[i] - MSR_ARCH_PERFMON_PERFCTR0 >= - min(KVM_INTEL_PMC_MAX_GENERIC, kvm_pmu_cap.num_counters_gp)) - continue; - break; - case MSR_ARCH_PERFMON_EVENTSEL0 ... MSR_ARCH_PERFMON_EVENTSEL_MAX: - if (msrs_to_save_all[i] - MSR_ARCH_PERFMON_EVENTSEL0 >= - min(KVM_INTEL_PMC_MAX_GENERIC, kvm_pmu_cap.num_counters_gp)) - continue; - break; - case MSR_ARCH_PERFMON_FIXED_CTR0 ... MSR_ARCH_PERFMON_FIXED_CTR_MAX: - if (msrs_to_save_all[i] - MSR_ARCH_PERFMON_FIXED_CTR0 >= - min(KVM_PMC_MAX_FIXED, kvm_pmu_cap.num_counters_fixed)) - continue; - break; - case MSR_IA32_XFD: - case MSR_IA32_XFD_ERR: - if (!kvm_cpu_cap_has(X86_FEATURE_XFD)) - continue; - break; - default: - break; - } - - msrs_to_save[num_msrs_to_save++] = msrs_to_save_all[i]; + if (enable_pmu) { + for (i = 0; i < ARRAY_SIZE(msrs_to_save_pmu); i++) + kvm_probe_msr_to_save(msrs_to_save_pmu[i]); } for (i = 0; i < ARRAY_SIZE(emulated_msrs_all); i++) { base-commit: 248deec419748c75f3a0fd6c075fc7687441b7ea --
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index f35f1ff4427b..2ed710b393eb 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -514,6 +514,7 @@ struct kvm_pmc { #define MSR_ARCH_PERFMON_PERFCTR_MAX (MSR_ARCH_PERFMON_PERFCTR0 + KVM_INTEL_PMC_MAX_GENERIC - 1) #define MSR_ARCH_PERFMON_EVENTSEL_MAX (MSR_ARCH_PERFMON_EVENTSEL0 + KVM_INTEL_PMC_MAX_GENERIC - 1) #define KVM_PMC_MAX_FIXED 3 +#define MSR_ARCH_PERFMON_FIXED_CTR_MAX (MSR_ARCH_PERFMON_FIXED_CTR0 + KVM_PMC_MAX_FIXED - 1) #define KVM_AMD_PMC_MAX_GENERIC 6 struct kvm_pmu { unsigned nr_arch_gp_counters; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 5c3ce39cdccb..f570367463c8 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -7054,15 +7054,32 @@ static void kvm_init_msr_list(void) continue; break; case MSR_ARCH_PERFMON_PERFCTR0 ... MSR_ARCH_PERFMON_PERFCTR_MAX: - if (msrs_to_save_all[i] - MSR_ARCH_PERFMON_PERFCTR0 >= + if (!enable_pmu || msrs_to_save_all[i] - MSR_ARCH_PERFMON_PERFCTR0 >= min(KVM_INTEL_PMC_MAX_GENERIC, kvm_pmu_cap.num_counters_gp)) continue; break; case MSR_ARCH_PERFMON_EVENTSEL0 ... MSR_ARCH_PERFMON_EVENTSEL_MAX: - if (msrs_to_save_all[i] - MSR_ARCH_PERFMON_EVENTSEL0 >= + if (!enable_pmu || msrs_to_save_all[i] - MSR_ARCH_PERFMON_EVENTSEL0 >= min(KVM_INTEL_PMC_MAX_GENERIC, kvm_pmu_cap.num_counters_gp)) continue; break; + case MSR_ARCH_PERFMON_FIXED_CTR0 ... MSR_ARCH_PERFMON_FIXED_CTR_MAX: + if (!enable_pmu || msrs_to_save_all[i] - MSR_ARCH_PERFMON_FIXED_CTR0 >= + min(KVM_PMC_MAX_FIXED, kvm_pmu_cap.num_counters_fixed)) + continue; + break; + case MSR_F15H_PERF_CTL0 ... MSR_F15H_PERF_CTR5: + case MSR_K7_EVNTSEL0 ... MSR_K7_PERFCTR3: + case MSR_CORE_PERF_FIXED_CTR_CTRL: + case MSR_CORE_PERF_GLOBAL_STATUS: + case MSR_CORE_PERF_GLOBAL_CTRL: + case MSR_CORE_PERF_GLOBAL_OVF_CTRL: + case MSR_IA32_DS_AREA: + case MSR_IA32_PEBS_ENABLE: + case MSR_PEBS_DATA_CFG: + if (!enable_pmu) + continue; + break; case MSR_IA32_XFD: case MSR_IA32_XFD_ERR: if (!kvm_cpu_cap_has(X86_FEATURE_XFD)) @@ -13468,3 +13485,4 @@ static void __exit kvm_x86_exit(void) */ } module_exit(kvm_x86_exit); +