[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <2e0f3fb63c810dd924907bccf9256f6f193b02ec.camel@redhat.com>
Date: Thu, 04 Jul 2024 21:59:20 -0400
From: Maxim Levitsky <mlevitsk@...hat.com>
To: Sean Christopherson <seanjc@...gle.com>, Paolo Bonzini
<pbonzini@...hat.com>, Vitaly Kuznetsov <vkuznets@...hat.com>
Cc: 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 26/49] KVM: x86: Add a macro to init CPUID features
that KVM emulates in software
On Fri, 2024-05-17 at 10:39 -0700, Sean Christopherson wrote:
> Now that kvm_cpu_cap_init() is a macro with its own scope, add EMUL_F() to
> OR-in features that KVM emulates in software, i.e. that don't depend on
> the feature being available in hardware. The contained scope
> of kvm_cpu_cap_init() allows using a local variable to track the set of
> emulated leaves, which in addition to avoiding confusing and/or
> unnecessary variables, helps prevent misuse of EMUL_F().
>
> Signed-off-by: Sean Christopherson <seanjc@...gle.com>
> ---
> arch/x86/kvm/cpuid.c | 36 +++++++++++++++++++++---------------
> 1 file changed, 21 insertions(+), 15 deletions(-)
>
> diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
> index 1064e4d68718..33e3e77de1b7 100644
> --- a/arch/x86/kvm/cpuid.c
> +++ b/arch/x86/kvm/cpuid.c
> @@ -94,6 +94,16 @@ u32 xstate_required_size(u64 xstate_bv, bool compacted)
> F(name); \
> })
>
> +/*
> + * Emulated Feature - For features that KVM emulates in software irrespective
> + * of host CPU/kernel support.
> + */
> +#define EMUL_F(name) \
> +({ \
> + kvm_cpu_cap_emulated |= F(name); \
> + F(name); \
> +})
To me it feels more and more that this patch series doesn't go into the right direction.
How about we just abandon the whole concept of masks and instead just have a list of statements
Pretty much the opposite of the patch series I confess:
#define CAP_PASSTHOUGH 0x01
#define CAP_EMULATED 0x02
#define CAP_AMD_ALIASED 0x04 // for AMD aliased features
#define CAP_SCATTERED 0x08
#define CAP_X86_64 0x10 // supported only on 64 bit hypervisors
...
/* CPUID_1_ECX*/
/* TMA is not passed though because: xyz*/
kvm_cpu_cap_init(TMA, 0);
kvm_cpu_cap_init(SSSE3, CAP_PASSTHOUGH);
/* CNXT_ID is not passed though because: xyz*/
kvm_cpu_cap_init(CNXT_ID, 0);
kvm_cpu_cap_init(RESERVED, 0);
kvm_cpu_cap_init(FMA, CAP_PASSTHOUGH);
...
/* KVM always emulates TSC_ADJUST */
kvm_cpu_cap_init(TSC_ADJUST, CAP_EMULATED | CAP_SCATTERED);
...
/* CPUID_D_1_EAX*/
/* XFD is disabled on 32 bit systems because: xyz*/
kvm_cpu_cap_init(XFD, CAP_PASSTHOUGH | CAP_X86_64)
'kvm_cpu_cap_init' can be a macro if needed to have the compile checks.
There are several advantages to this:
- more readability, plus if needed each statement can be amended with a comment.
- No weird hacks in 'F*' macros, which additionally eventually evaluate into a bit, which is confusing.
In fact no need to even have them at all.
- No need to verify that bitmask belongs to a feature word.
- Merge friendly - each capability has its own line.
Disadvantages:
- Longer list - IMHO not a problem, since it is very easy to read / search
and can have as much comments as needed.
For example this is how the kernel lists the CPUID features and this list IMHO
is very manageable.
- Slower - kvm_set_cpu_caps is called exactly once per KVM module load, thus
performance is the last thing I would care about in this function.
Another note about this patch: It is somewhat confusing that EMUL_F just forces a feature in kvm caps,
regardless of CPU support, because KVM also has KVM_GET_EMULATED_CPUID and it has a different meaning.
Users can easily confuse the EMUL_F for something that sets a feature bit in the KVM_GET_EMULATED_CPUID.
Best regards,
Maxim Levitsky
> +
> /*
> * Aliased Features - For features in 0x8000_0001.EDX that are duplicates of
> * identical 0x1.EDX features, and thus are aliased from 0x1 to 0x8000_0001.
> @@ -649,6 +659,7 @@ do { \
> 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; \
> \
> if (leaf < NCAPINTS) \
> kvm_cpu_caps[leaf] &= (mask); \
> @@ -656,6 +667,7 @@ do { \
> kvm_cpu_caps[leaf] = (mask); \
> \
> kvm_cpu_caps[leaf] &= raw_cpuid_get(cpuid); \
> + kvm_cpu_caps[leaf] |= kvm_cpu_cap_emulated; \
> } while (0)
>
> /*
> @@ -684,12 +696,10 @@ void kvm_set_cpu_caps(void)
> 0 /* TM2 */ | F(SSSE3) | 0 /* CNXT-ID */ | 0 /* Reserved */ |
> F(FMA) | F(CX16) | 0 /* xTPR Update */ | F(PDCM) |
> F(PCID) | 0 /* Reserved, DCA */ | F(XMM4_1) |
> - F(XMM4_2) | F(X2APIC) | F(MOVBE) | F(POPCNT) |
> + F(XMM4_2) | EMUL_F(X2APIC) | F(MOVBE) | F(POPCNT) |
> 0 /* Reserved*/ | F(AES) | F(XSAVE) | 0 /* OSXSAVE */ | F(AVX) |
> F(F16C) | F(RDRAND)
> );
> - /* KVM emulates x2apic in software irrespective of host support. */
> - kvm_cpu_cap_set(X86_FEATURE_X2APIC);
>
> kvm_cpu_cap_init(CPUID_1_EDX,
> F(FPU) | F(VME) | F(DE) | F(PSE) |
> @@ -703,13 +713,13 @@ void kvm_set_cpu_caps(void)
> );
>
> kvm_cpu_cap_init(CPUID_7_0_EBX,
> - F(FSGSBASE) | F(SGX) | F(BMI1) | F(HLE) | F(AVX2) |
> - F(FDP_EXCPTN_ONLY) | F(SMEP) | F(BMI2) | F(ERMS) | F(INVPCID) |
> - F(RTM) | F(ZERO_FCS_FDS) | 0 /*MPX*/ | F(AVX512F) |
> - F(AVX512DQ) | F(RDSEED) | F(ADX) | F(SMAP) | F(AVX512IFMA) |
> - F(CLFLUSHOPT) | F(CLWB) | 0 /*INTEL_PT*/ | F(AVX512PF) |
> - F(AVX512ER) | F(AVX512CD) | F(SHA_NI) | F(AVX512BW) |
> - F(AVX512VL));
> + F(FSGSBASE) | EMUL_F(TSC_ADJUST) | F(SGX) | F(BMI1) | F(HLE) |
> + F(AVX2) | F(FDP_EXCPTN_ONLY) | F(SMEP) | F(BMI2) | F(ERMS) |
> + F(INVPCID) | F(RTM) | F(ZERO_FCS_FDS) | 0 /*MPX*/ |
> + F(AVX512F) | F(AVX512DQ) | F(RDSEED) | F(ADX) | F(SMAP) |
> + F(AVX512IFMA) | F(CLFLUSHOPT) | F(CLWB) | 0 /*INTEL_PT*/ |
> + F(AVX512PF) | F(AVX512ER) | F(AVX512CD) | F(SHA_NI) |
> + F(AVX512BW) | F(AVX512VL));
>
> kvm_cpu_cap_init(CPUID_7_ECX,
> F(AVX512VBMI) | RAW_F(LA57) | F(PKU) | 0 /*OSPKE*/ | F(RDPID) |
> @@ -728,16 +738,12 @@ void kvm_set_cpu_caps(void)
>
> kvm_cpu_cap_init(CPUID_7_EDX,
> F(AVX512_4VNNIW) | F(AVX512_4FMAPS) | F(SPEC_CTRL) |
> - F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES) | F(INTEL_STIBP) |
> + F(SPEC_CTRL_SSBD) | EMUL_F(ARCH_CAPABILITIES) | F(INTEL_STIBP) |
> F(MD_CLEAR) | F(AVX512_VP2INTERSECT) | F(FSRM) |
> F(SERIALIZE) | F(TSXLDTRK) | F(AVX512_FP16) |
> F(AMX_TILE) | F(AMX_INT8) | F(AMX_BF16) | F(FLUSH_L1D)
> );
>
> - /* TSC_ADJUST and ARCH_CAPABILITIES are emulated in software. */
> - kvm_cpu_cap_set(X86_FEATURE_TSC_ADJUST);
> - kvm_cpu_cap_set(X86_FEATURE_ARCH_CAPABILITIES);
> -
> if (boot_cpu_has(X86_FEATURE_IBPB) && boot_cpu_has(X86_FEATURE_IBRS))
> kvm_cpu_cap_set(X86_FEATURE_SPEC_CTRL);
> if (boot_cpu_has(X86_FEATURE_STIBP))
Powered by blists - more mailing lists