[kvm-unit-tests PATCH 02/16] x86: Encode X86_FEATURE_* definitions using a structure
Mi, Dapeng
dapeng1.mi at linux.intel.com
Mon Jun 9 23:08:43 PDT 2025
On 5/30/2025 6:19 AM, Sean Christopherson wrote:
> Encode X86_FEATURE_* macros using a new "struct x86_cpu_feature" instead
> of manually packing the values into a u64. Using a structure eliminates
> open code shifts and masks, and is largely self-documenting.
>
> Note, the code and naming scheme are stolen from KVM selftests.
>
> Signed-off-by: Sean Christopherson <seanjc at google.com>
> ---
> lib/x86/processor.h | 171 ++++++++++++++++++++++++--------------------
> 1 file changed, 95 insertions(+), 76 deletions(-)
>
> diff --git a/lib/x86/processor.h b/lib/x86/processor.h
> index a0be04c5..3ac6711d 100644
> --- a/lib/x86/processor.h
> +++ b/lib/x86/processor.h
> @@ -6,6 +6,7 @@
> #include "msr.h"
> #include <bitops.h>
> #include <stdint.h>
> +#include <util.h>
>
> #define CANONICAL_48_VAL 0xffffaaaaaaaaaaaaull
> #define CANONICAL_57_VAL 0xffaaaaaaaaaaaaaaull
> @@ -232,100 +233,118 @@ static inline bool is_intel(void)
> return strcmp((char *)name, "GenuineIntel") == 0;
> }
>
> -#define CPUID(a, b, c, d) ((((unsigned long long) a) << 32) | (b << 16) | \
> - (c << 8) | d)
> -
> /*
> - * Each X86_FEATURE_XXX definition is 64-bit and contains the following
> - * CPUID meta-data:
> - *
> - * [63:32] : input value for EAX
> - * [31:16] : input value for ECX
> - * [15:8] : output register
> - * [7:0] : bit position in output register
> + * Pack the information into a 64-bit value so that each X86_FEATURE_XXX can be
> + * passed by value with no overhead.
> */
> +struct x86_cpu_feature {
> + u32 function;
> + u16 index;
> + u8 reg;
> + u8 bit;
> +};
> +
> +#define X86_CPU_FEATURE(fn, idx, gpr, __bit) \
> +({ \
> + struct x86_cpu_feature feature = { \
> + .function = fn, \
> + .index = idx, \
> + .reg = gpr, \
> + .bit = __bit, \
> + }; \
> + \
> + static_assert((fn & 0xc0000000) == 0 || \
> + (fn & 0xc0000000) == 0x40000000 || \
> + (fn & 0xc0000000) == 0x80000000 || \
> + (fn & 0xc0000000) == 0xc0000000); \
> + static_assert(idx < BIT(sizeof(feature.index) * BITS_PER_BYTE)); \
> + feature; \
> +})
>
> /*
> * Basic Leafs, a.k.a. Intel defined
> */
> -#define X86_FEATURE_MWAIT (CPUID(0x1, 0, ECX, 3))
> -#define X86_FEATURE_VMX (CPUID(0x1, 0, ECX, 5))
> -#define X86_FEATURE_PDCM (CPUID(0x1, 0, ECX, 15))
> -#define X86_FEATURE_PCID (CPUID(0x1, 0, ECX, 17))
> -#define X86_FEATURE_X2APIC (CPUID(0x1, 0, ECX, 21))
> -#define X86_FEATURE_MOVBE (CPUID(0x1, 0, ECX, 22))
> -#define X86_FEATURE_TSC_DEADLINE_TIMER (CPUID(0x1, 0, ECX, 24))
> -#define X86_FEATURE_XSAVE (CPUID(0x1, 0, ECX, 26))
> -#define X86_FEATURE_OSXSAVE (CPUID(0x1, 0, ECX, 27))
> -#define X86_FEATURE_RDRAND (CPUID(0x1, 0, ECX, 30))
> -#define X86_FEATURE_MCE (CPUID(0x1, 0, EDX, 7))
> -#define X86_FEATURE_APIC (CPUID(0x1, 0, EDX, 9))
> -#define X86_FEATURE_CLFLUSH (CPUID(0x1, 0, EDX, 19))
> -#define X86_FEATURE_DS (CPUID(0x1, 0, EDX, 21))
> -#define X86_FEATURE_XMM (CPUID(0x1, 0, EDX, 25))
> -#define X86_FEATURE_XMM2 (CPUID(0x1, 0, EDX, 26))
> -#define X86_FEATURE_TSC_ADJUST (CPUID(0x7, 0, EBX, 1))
> -#define X86_FEATURE_HLE (CPUID(0x7, 0, EBX, 4))
> -#define X86_FEATURE_SMEP (CPUID(0x7, 0, EBX, 7))
> -#define X86_FEATURE_INVPCID (CPUID(0x7, 0, EBX, 10))
> -#define X86_FEATURE_RTM (CPUID(0x7, 0, EBX, 11))
> -#define X86_FEATURE_SMAP (CPUID(0x7, 0, EBX, 20))
> -#define X86_FEATURE_PCOMMIT (CPUID(0x7, 0, EBX, 22))
> -#define X86_FEATURE_CLFLUSHOPT (CPUID(0x7, 0, EBX, 23))
> -#define X86_FEATURE_CLWB (CPUID(0x7, 0, EBX, 24))
> -#define X86_FEATURE_INTEL_PT (CPUID(0x7, 0, EBX, 25))
> -#define X86_FEATURE_UMIP (CPUID(0x7, 0, ECX, 2))
> -#define X86_FEATURE_PKU (CPUID(0x7, 0, ECX, 3))
> -#define X86_FEATURE_LA57 (CPUID(0x7, 0, ECX, 16))
> -#define X86_FEATURE_RDPID (CPUID(0x7, 0, ECX, 22))
> -#define X86_FEATURE_SHSTK (CPUID(0x7, 0, ECX, 7))
> -#define X86_FEATURE_IBT (CPUID(0x7, 0, EDX, 20))
> -#define X86_FEATURE_SPEC_CTRL (CPUID(0x7, 0, EDX, 26))
> -#define X86_FEATURE_FLUSH_L1D (CPUID(0x7, 0, EDX, 28))
> -#define X86_FEATURE_ARCH_CAPABILITIES (CPUID(0x7, 0, EDX, 29))
> -#define X86_FEATURE_PKS (CPUID(0x7, 0, ECX, 31))
> -#define X86_FEATURE_LAM (CPUID(0x7, 1, EAX, 26))
> +#define X86_FEATURE_MWAIT X86_CPU_FEATURE(0x1, 0, ECX, 3)
> +#define X86_FEATURE_VMX X86_CPU_FEATURE(0x1, 0, ECX, 5)
> +#define X86_FEATURE_PDCM X86_CPU_FEATURE(0x1, 0, ECX, 15)
> +#define X86_FEATURE_PCID X86_CPU_FEATURE(0x1, 0, ECX, 17)
> +#define X86_FEATURE_X2APIC X86_CPU_FEATURE(0x1, 0, ECX, 21)
> +#define X86_FEATURE_MOVBE X86_CPU_FEATURE(0x1, 0, ECX, 22)
> +#define X86_FEATURE_TSC_DEADLINE_TIMER X86_CPU_FEATURE(0x1, 0, ECX, 24)
> +#define X86_FEATURE_XSAVE X86_CPU_FEATURE(0x1, 0, ECX, 26)
> +#define X86_FEATURE_OSXSAVE X86_CPU_FEATURE(0x1, 0, ECX, 27)
> +#define X86_FEATURE_RDRAND X86_CPU_FEATURE(0x1, 0, ECX, 30)
> +#define X86_FEATURE_MCE X86_CPU_FEATURE(0x1, 0, EDX, 7)
> +#define X86_FEATURE_APIC X86_CPU_FEATURE(0x1, 0, EDX, 9)
> +#define X86_FEATURE_CLFLUSH X86_CPU_FEATURE(0x1, 0, EDX, 19)
> +#define X86_FEATURE_DS X86_CPU_FEATURE(0x1, 0, EDX, 21)
> +#define X86_FEATURE_XMM X86_CPU_FEATURE(0x1, 0, EDX, 25)
> +#define X86_FEATURE_XMM2 X86_CPU_FEATURE(0x1, 0, EDX, 26)
> +#define X86_FEATURE_TSC_ADJUST X86_CPU_FEATURE(0x7, 0, EBX, 1)
> +#define X86_FEATURE_HLE X86_CPU_FEATURE(0x7, 0, EBX, 4)
> +#define X86_FEATURE_SMEP X86_CPU_FEATURE(0x7, 0, EBX, 7)
> +#define X86_FEATURE_INVPCID X86_CPU_FEATURE(0x7, 0, EBX, 10)
> +#define X86_FEATURE_RTM X86_CPU_FEATURE(0x7, 0, EBX, 11)
> +#define X86_FEATURE_SMAP X86_CPU_FEATURE(0x7, 0, EBX, 20)
> +#define X86_FEATURE_PCOMMIT X86_CPU_FEATURE(0x7, 0, EBX, 22)
> +#define X86_FEATURE_CLFLUSHOPT X86_CPU_FEATURE(0x7, 0, EBX, 23)
> +#define X86_FEATURE_CLWB X86_CPU_FEATURE(0x7, 0, EBX, 24)
> +#define X86_FEATURE_INTEL_PT X86_CPU_FEATURE(0x7, 0, EBX, 25)
> +#define X86_FEATURE_UMIP X86_CPU_FEATURE(0x7, 0, ECX, 2)
> +#define X86_FEATURE_PKU X86_CPU_FEATURE(0x7, 0, ECX, 3)
> +#define X86_FEATURE_LA57 X86_CPU_FEATURE(0x7, 0, ECX, 16)
> +#define X86_FEATURE_RDPID X86_CPU_FEATURE(0x7, 0, ECX, 22)
> +#define X86_FEATURE_SHSTK X86_CPU_FEATURE(0x7, 0, ECX, 7)
> +#define X86_FEATURE_IBT X86_CPU_FEATURE(0x7, 0, EDX, 20)
> +#define X86_FEATURE_SPEC_CTRL X86_CPU_FEATURE(0x7, 0, EDX, 26)
> +#define X86_FEATURE_FLUSH_L1D X86_CPU_FEATURE(0x7, 0, EDX, 28)
> +#define X86_FEATURE_ARCH_CAPABILITIES X86_CPU_FEATURE(0x7, 0, EDX, 29)
> +#define X86_FEATURE_PKS X86_CPU_FEATURE(0x7, 0, ECX, 31)
> +#define X86_FEATURE_LAM X86_CPU_FEATURE(0x7, 1, EAX, 26)
>
> /*
> * KVM defined leafs
> */
> -#define KVM_FEATURE_ASYNC_PF (CPUID(0x40000001, 0, EAX, 4))
> -#define KVM_FEATURE_ASYNC_PF_INT (CPUID(0x40000001, 0, EAX, 14))
> +#define KVM_FEATURE_ASYNC_PF X86_CPU_FEATURE(0x40000001, 0, EAX, 4)
> +#define KVM_FEATURE_ASYNC_PF_INT X86_CPU_FEATURE(0x40000001, 0, EAX, 14)
>
> /*
> * Extended Leafs, a.k.a. AMD defined
> */
> -#define X86_FEATURE_SVM (CPUID(0x80000001, 0, ECX, 2))
> -#define X86_FEATURE_PERFCTR_CORE (CPUID(0x80000001, 0, ECX, 23))
> -#define X86_FEATURE_NX (CPUID(0x80000001, 0, EDX, 20))
> -#define X86_FEATURE_GBPAGES (CPUID(0x80000001, 0, EDX, 26))
> -#define X86_FEATURE_RDTSCP (CPUID(0x80000001, 0, EDX, 27))
> -#define X86_FEATURE_LM (CPUID(0x80000001, 0, EDX, 29))
> -#define X86_FEATURE_RDPRU (CPUID(0x80000008, 0, EBX, 4))
> -#define X86_FEATURE_AMD_IBPB (CPUID(0x80000008, 0, EBX, 12))
> -#define X86_FEATURE_NPT (CPUID(0x8000000A, 0, EDX, 0))
> -#define X86_FEATURE_LBRV (CPUID(0x8000000A, 0, EDX, 1))
> -#define X86_FEATURE_NRIPS (CPUID(0x8000000A, 0, EDX, 3))
> -#define X86_FEATURE_TSCRATEMSR (CPUID(0x8000000A, 0, EDX, 4))
> -#define X86_FEATURE_PAUSEFILTER (CPUID(0x8000000A, 0, EDX, 10))
> -#define X86_FEATURE_PFTHRESHOLD (CPUID(0x8000000A, 0, EDX, 12))
> -#define X86_FEATURE_VGIF (CPUID(0x8000000A, 0, EDX, 16))
> -#define X86_FEATURE_VNMI (CPUID(0x8000000A, 0, EDX, 25))
> -#define X86_FEATURE_AMD_PMU_V2 (CPUID(0x80000022, 0, EAX, 0))
> +#define X86_FEATURE_SVM X86_CPU_FEATURE(0x80000001, 0, ECX, 2)
> +#define X86_FEATURE_PERFCTR_CORE X86_CPU_FEATURE(0x80000001, 0, ECX, 23)
> +#define X86_FEATURE_NX X86_CPU_FEATURE(0x80000001, 0, EDX, 20)
> +#define X86_FEATURE_GBPAGES X86_CPU_FEATURE(0x80000001, 0, EDX, 26)
> +#define X86_FEATURE_RDTSCP X86_CPU_FEATURE(0x80000001, 0, EDX, 27)
> +#define X86_FEATURE_LM X86_CPU_FEATURE(0x80000001, 0, EDX, 29)
> +#define X86_FEATURE_RDPRU X86_CPU_FEATURE(0x80000008, 0, EBX, 4)
> +#define X86_FEATURE_AMD_IBPB X86_CPU_FEATURE(0x80000008, 0, EBX, 12)
> +#define X86_FEATURE_NPT X86_CPU_FEATURE(0x8000000A, 0, EDX, 0)
> +#define X86_FEATURE_LBRV X86_CPU_FEATURE(0x8000000A, 0, EDX, 1)
> +#define X86_FEATURE_NRIPS X86_CPU_FEATURE(0x8000000A, 0, EDX, 3)
> +#define X86_FEATURE_TSCRATEMSR X86_CPU_FEATURE(0x8000000A, 0, EDX, 4)
> +#define X86_FEATURE_PAUSEFILTER X86_CPU_FEATURE(0x8000000A, 0, EDX, 10)
> +#define X86_FEATURE_PFTHRESHOLD X86_CPU_FEATURE(0x8000000A, 0, EDX, 12)
> +#define X86_FEATURE_VGIF X86_CPU_FEATURE(0x8000000A, 0, EDX, 16)
> +#define X86_FEATURE_VNMI X86_CPU_FEATURE(0x8000000A, 0, EDX, 25)
The code looks good to me except the indent style (mixed tab and space).
Although it's not introduced by this patch, we'd better make them identical
by this chance.
Reviewed-by: Dapeng Mi <dapeng1.mi at linux.intel.com>
> +#define X86_FEATURE_AMD_PMU_V2 X86_CPU_FEATURE(0x80000022, 0, EAX, 0)
>
> -static inline bool this_cpu_has(u64 feature)
> +static inline u32 __this_cpu_has(u32 function, u32 index, u8 reg, u8 lo, u8 hi)
> {
> - u32 input_eax = feature >> 32;
> - u32 input_ecx = (feature >> 16) & 0xffff;
> - u32 output_reg = (feature >> 8) & 0xff;
> - u8 bit = feature & 0xff;
> - struct cpuid c;
> - u32 *tmp;
> + union {
> + struct cpuid cpuid;
> + u32 gprs[4];
> + } c;
>
> - c = cpuid_indexed(input_eax, input_ecx);
> - tmp = (u32 *)&c;
> + c.cpuid = cpuid_indexed(function, index);
>
> - return ((*(tmp + (output_reg % 32))) & (1 << bit));
> + return (c.gprs[reg] & GENMASK(hi, lo)) >> lo;
> +}
> +
> +static inline bool this_cpu_has(struct x86_cpu_feature feature)
> +{
> + return __this_cpu_has(feature.function, feature.index,
> + feature.reg, feature.bit, feature.bit);
> }
>
> struct far_pointer32 {
More information about the kvm-riscv
mailing list