Commit a7c48c3f authored by Sean Christopherson's avatar Sean Christopherson Committed by Paolo Bonzini
Browse files

KVM: x86: Expand build-time assertion on reverse CPUID usage



Add build-time checks to ensure KVM isn't trying to do a reverse CPUID
lookup on Linux-defined feature bits, along with comments to explain
the gory details of X86_FEATUREs and bit().

No functional change intended.

Signed-off-by: default avatarSean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent daa0d8c3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -281,8 +281,9 @@ out:
	return r;
}

static void cpuid_mask(u32 *word, int wordnum)
static __always_inline void cpuid_mask(u32 *word, int wordnum)
{
	reverse_cpuid_check(wordnum);
	*word &= boot_cpu_data.x86_capability[wordnum];
}

+28 −5
Original line number Diff line number Diff line
@@ -56,18 +56,41 @@ static const struct cpuid_reg reverse_cpuid[] = {
	[CPUID_7_1_EAX]       = {         7, 1, CPUID_EAX},
};

static inline u32 bit(int bitno)
/*
 * Reverse CPUID and its derivatives can only be used for hardware-defined
 * feature words, i.e. words whose bits directly correspond to a CPUID leaf.
 * Retrieving a feature bit or masking guest CPUID from a Linux-defined word
 * is nonsensical as the bit number/mask is an arbitrary software-defined value
 * and can't be used by KVM to query/control guest capabilities.  And obviously
 * the leaf being queried must have an entry in the lookup table.
 */
static __always_inline void reverse_cpuid_check(unsigned x86_leaf)
{
	return BIT(bitno & 31);
	BUILD_BUG_ON(x86_leaf == CPUID_LNX_1);
	BUILD_BUG_ON(x86_leaf == CPUID_LNX_2);
	BUILD_BUG_ON(x86_leaf == CPUID_LNX_3);
	BUILD_BUG_ON(x86_leaf == CPUID_LNX_4);
	BUILD_BUG_ON(x86_leaf >= ARRAY_SIZE(reverse_cpuid));
	BUILD_BUG_ON(reverse_cpuid[x86_leaf].function == 0);
}

/*
 * Retrieve the bit mask from an X86_FEATURE_* definition.  Features contain
 * the hardware defined bit number (stored in bits 4:0) and a software defined
 * "word" (stored in bits 31:5).  The word is used to index into arrays of
 * bit masks that hold the per-cpu feature capabilities, e.g. this_cpu_has().
 */
static __always_inline u32 bit(int x86_feature)
{
	reverse_cpuid_check(x86_feature / 32);
	return 1 << (x86_feature & 31);
}

static __always_inline struct cpuid_reg x86_feature_cpuid(unsigned x86_feature)
{
	unsigned x86_leaf = x86_feature / 32;

	BUILD_BUG_ON(x86_leaf >= ARRAY_SIZE(reverse_cpuid));
	BUILD_BUG_ON(reverse_cpuid[x86_leaf].function == 0);

	reverse_cpuid_check(x86_leaf);
	return reverse_cpuid[x86_leaf];
}