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: Sean Christopherson <sean.j.christopherson@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:

committed by
Paolo Bonzini

parent
daa0d8c3a4
commit
a7c48c3f56
@@ -281,8 +281,9 @@ out:
|
|||||||
return r;
|
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];
|
*word &= boot_cpu_data.x86_capability[wordnum];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -56,18 +56,41 @@ static const struct cpuid_reg reverse_cpuid[] = {
|
|||||||
[CPUID_7_1_EAX] = { 7, 1, CPUID_EAX},
|
[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)
|
static __always_inline struct cpuid_reg x86_feature_cpuid(unsigned x86_feature)
|
||||||
{
|
{
|
||||||
unsigned x86_leaf = x86_feature / 32;
|
unsigned x86_leaf = x86_feature / 32;
|
||||||
|
|
||||||
BUILD_BUG_ON(x86_leaf >= ARRAY_SIZE(reverse_cpuid));
|
reverse_cpuid_check(x86_leaf);
|
||||||
BUILD_BUG_ON(reverse_cpuid[x86_leaf].function == 0);
|
|
||||||
|
|
||||||
return reverse_cpuid[x86_leaf];
|
return reverse_cpuid[x86_leaf];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user