[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <6d3dd38ae5860be5c578d3212aa94ace460950b6.camel@redhat.com>
Date: Mon, 05 Aug 2024 14:07:58 +0300
From: mlevitsk@...hat.com
To: Sean Christopherson <seanjc@...gle.com>
Cc: Paolo Bonzini <pbonzini@...hat.com>, Vitaly Kuznetsov
<vkuznets@...hat.com>, kvm@...r.kernel.org, linux-kernel@...r.kernel.org,
Hou Wenlong <houwenlong.hwl@...group.com>, Kechen Lu <kechenl@...dia.com>,
Oliver Upton <oliver.upton@...ux.dev>, Binbin Wu
<binbin.wu@...ux.intel.com>, Yang Weijiang <weijiang.yang@...el.com>,
Robert Hoo <robert.hoo.linux@...il.com>
Subject: Re: [PATCH v2 23/49] KVM: x86: Handle kernel- and KVM-defined CPUID
words in a single helper
У чт, 2024-07-25 у 12:18 -0700, Sean Christopherson пише:
> > On Wed, Jul 24, 2024, Maxim Levitsky wrote:
> > > > On Mon, 2024-07-08 at 14:18 -0700, Sean Christopherson wrote:
> > > > > > And in the unlikely case that we royally screw up and fail
> > > > > > to call kvm_cpu_cap_init() on a word, starting with 0xff would result in all
> > > > > > features in the uninitialized word being treated as supported.
> > > > Yes, but IMHO the chances of this happening are very low.
> > > >
> > > > I understand your concerns though, but then IMHO it's better to keep the
> > > > kvm_cpu_cap_init_kvm_defined, because this way at least the function name
> > > > cleanly describes the difference instead of the difference being buried in the function
> > > > itself (the comment helps but still it is less noticeable than a function name).
> > > >
> > > > I don't have a very strong opinion on this though,
> > > > because IMHO the kvm_cpu_cap_init_kvm_defined is also not very user friendly,
> > > > so if you really think that the new code is more readable, let it be.
> >
> > Hmm, the main motiviation of this patch was to avoid duplicate code in later
> > patches, but looking at the end result, I don't think that eliminating the
> > KVM-defined variants is necessary, e.g. ending up with this should work, too.
> >
> > #define __kvm_cpu_cap_init(leaf) \
> > do { \
> > const struct cpuid_reg cpuid = x86_feature_cpuid(leaf * 32); \
> > const u32 __maybe_unused kvm_cpu_cap_init_in_progress = leaf; \
> > u32 kvm_cpu_cap_emulated = 0; \
> > u32 kvm_cpu_cap_synthesized = 0; \
> > \
> > kvm_cpu_caps[leaf] &= (raw_cpuid_get(cpuid) | \
> > kvm_cpu_cap_synthesized); \
> > kvm_cpu_caps[leaf] |= kvm_cpu_cap_emulated; \
> > } while (0)
> >
> > /* For kernel-defined leafs, mask the boot CPU's pre-populated value. */
> > #define kvm_cpu_cap_init(leaf, mask) \
> > do {
> > BUILD_BUG_ON(leaf >= NCAPINTS); \
> > kvm_cpu_caps[leaf] &= (mask); \
> > \
> > __kvm_cpu_cap_init(leaf); \
> > } while (0)
> >
> > /* For KVM-defined leafs, explicitly set the leaf, KVM is the sole authority. */
> > #define kvm_cpu_cap_init_kvm_defined(leaf, mask) \
> > do { \
> > BUILD_BUG_ON(leaf < NCAPINTS); \
> > kvm_cpu_caps[leaf] = (mask); \
> > \
> > __kvm_cpu_cap_init(leaf); \
> > } while (0)
> >
> > That said, unless someone really likes kvm_cpu_cap_init_kvm_defined(), I am
> > leaning toward keeping this patch (but rewriting the changelog). IMO, whether a
> > leaf is KVM-only or known to the kernel is a plumbing detail that really shouldn't
> > affect anything in kvm_set_cpu_caps(). Literally the only difference is whether
> > or not there are kernel capabilities to account for. The "types" of features isn't
> > restricted in any way, e.g. CPUID_12_EAX is KVM-only and contains only scattered
> > features, but CPUID_7_1_EDX is KVM-only and contains only "regular" features.
> >
> > And if a feature changes from KVM-only to kernel-managed, we'd need to update the
> > caller. This is unlikely, but it seems like an unnecessary maintenance burden.
> >
> > Ooh, and thinking more on that and on the argument against initializing the KVM-
> > only leafs to all ones, I think we should remove this:
> >
> > memcpy(&kvm_cpu_caps, &boot_cpu_data.x86_capability,
> > sizeof(kvm_cpu_caps) - (NKVMCAPINTS * sizeof(*kvm_cpu_caps)));
> >
> > and instead explicitly mask the boot_cpu_data.x86_capability[leaf]. It's _way_
> > more likely that the kernel adds a leaf without updating KVM, in which case
> > copying the kernel capabilities without masking them against KVM's capabilities
> > would over-report the set of supported features. The odds of over-reproring are
> > still low, as KVM limit the max leaf in __do_cpuid_func(), but unless I'm missing
> > something, the memcpy() trick adds no value in the current code base.
Nothing against this.
> >
> > E.g.
> >
> > diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
> > index dbc3f6ce9203..593de2c1811b 100644
> > --- a/arch/x86/kvm/cpuid.c
> > +++ b/arch/x86/kvm/cpuid.c
> > @@ -730,18 +730,20 @@ do { \
> > } while (0)
> >
> > /*
> > - * For kernel-defined leafs, mask the boot CPU's pre-populated value. For KVM-
> > - * defined leafs, explicitly set the leaf, as KVM is the one and only authority.
> > + * For leafs that are managed by the kernel, mask the boot CPU's capabilities,
> > + * which are populated by the kernel. For KVM-only leafs, as KVM is the one
> > + * and only authority.
> > */
> > #define kvm_cpu_cap_init(leaf, mask) \
> > do { \
> > const struct cpuid_reg cpuid = x86_feature_cpuid(leaf * 32); \
> > const u32 __maybe_unused kvm_cpu_cap_init_in_progress = leaf; \
> > + const u32 kernel_cpu_caps = boot_cpu_data.x86_capability[leaf]; \
> > u32 kvm_cpu_cap_emulated = 0; \
> > u32 kvm_cpu_cap_synthesized = 0; \
> > \
> > if (leaf < NCAPINTS) \
> > - kvm_cpu_caps[leaf] &= (mask); \
> > + kvm_cpu_caps[leaf] = kernel_cpu_caps & (mask); \
> > else \
> > kvm_cpu_caps[leaf] = (mask); \
I am not going to argue much about this, I still think that assigning directly
using a mask is confusing.
Using kernel_cpu_caps is indeed better regardless of other issues.
Best regards,
Maxim Levitsky
> > \
> > @@ -763,9 +765,6 @@ void kvm_set_cpu_caps(void)
> > BUILD_BUG_ON(sizeof(kvm_cpu_caps) - (NKVMCAPINTS * sizeof(*kvm_cpu_caps)) >
> > sizeof(boot_cpu_data.x86_capability));
> >
> > - memcpy(&kvm_cpu_caps, &boot_cpu_data.x86_capability,
> > - sizeof(kvm_cpu_caps) - (NKVMCAPINTS * sizeof(*kvm_cpu_caps)));
> > -
> > kvm_cpu_cap_init(CPUID_1_ECX,
> > /*
> > * NOTE: MONITOR (and MWAIT) are emulated as NOP, but *not*
> >
Powered by blists - more mailing lists