x86/cpu: Detect VMX features on Intel, Centaur and Zhaoxin CPUs
Add an entry in struct cpuinfo_x86 to track VMX capabilities and fill the capabilities during IA32_FEAT_CTL MSR initialization. Make the VMX capabilities dependent on IA32_FEAT_CTL and X86_FEATURE_NAMES so as to avoid unnecessary overhead on CPUs that can't possibly support VMX, or when /proc/cpuinfo is not available. Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> Signed-off-by: Borislav Petkov <bp@suse.de> Link: https://lkml.kernel.org/r/20191221044513.21680-11-sean.j.christopherson@intel.com
This commit is contained in:
parent
159348784f
commit
b47ce1fed4
|
@ -391,6 +391,10 @@ config IA32_FEAT_CTL
|
|||
def_bool y
|
||||
depends on CPU_SUP_INTEL || CPU_SUP_CENTAUR || CPU_SUP_ZHAOXIN
|
||||
|
||||
config X86_VMX_FEATURE_NAMES
|
||||
def_bool y
|
||||
depends on IA32_FEAT_CTL && X86_FEATURE_NAMES
|
||||
|
||||
menuconfig PROCESSOR_SELECT
|
||||
bool "Supported processor vendors" if EXPERT
|
||||
---help---
|
||||
|
|
|
@ -85,6 +85,9 @@ struct cpuinfo_x86 {
|
|||
#ifdef CONFIG_X86_64
|
||||
/* Number of 4K pages in DTLB/ITLB combined(in pages): */
|
||||
int x86_tlbsize;
|
||||
#endif
|
||||
#ifdef CONFIG_X86_VMX_FEATURE_NAMES
|
||||
__u32 vmx_capability[NVMXINTS];
|
||||
#endif
|
||||
__u8 x86_virt_bits;
|
||||
__u8 x86_phys_bits;
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
#ifndef _ASM_X86_VMXFEATURES_H
|
||||
#define _ASM_X86_VMXFEATURES_H
|
||||
|
||||
/*
|
||||
* Defines VMX CPU feature bits
|
||||
*/
|
||||
#define NVMXINTS 3 /* N 32-bit words worth of info */
|
||||
|
||||
/*
|
||||
* Note: If the comment begins with a quoted string, that string is used
|
||||
* in /proc/cpuinfo instead of the macro name. If the string is "",
|
||||
|
|
|
@ -1449,6 +1449,9 @@ static void identify_cpu(struct cpuinfo_x86 *c)
|
|||
#endif
|
||||
c->x86_cache_alignment = c->x86_clflush_size;
|
||||
memset(&c->x86_capability, 0, sizeof(c->x86_capability));
|
||||
#ifdef CONFIG_X86_VMX_FEATURE_NAMES
|
||||
memset(&c->vmx_capability, 0, sizeof(c->vmx_capability));
|
||||
#endif
|
||||
|
||||
generic_identify(c);
|
||||
|
||||
|
|
|
@ -4,10 +4,80 @@
|
|||
#include <asm/cpufeature.h>
|
||||
#include <asm/msr-index.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/vmx.h>
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "x86/cpu: " fmt
|
||||
|
||||
#ifdef CONFIG_X86_VMX_FEATURE_NAMES
|
||||
enum vmx_feature_leafs {
|
||||
MISC_FEATURES = 0,
|
||||
PRIMARY_CTLS,
|
||||
SECONDARY_CTLS,
|
||||
NR_VMX_FEATURE_WORDS,
|
||||
};
|
||||
|
||||
#define VMX_F(x) BIT(VMX_FEATURE_##x & 0x1f)
|
||||
|
||||
static void init_vmx_capabilities(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u32 supported, funcs, ept, vpid, ign;
|
||||
|
||||
BUILD_BUG_ON(NVMXINTS != NR_VMX_FEATURE_WORDS);
|
||||
|
||||
/*
|
||||
* The high bits contain the allowed-1 settings, i.e. features that can
|
||||
* be turned on. The low bits contain the allowed-0 settings, i.e.
|
||||
* features that can be turned off. Ignore the allowed-0 settings,
|
||||
* if a feature can be turned on then it's supported.
|
||||
*
|
||||
* Use raw rdmsr() for primary processor controls and pin controls MSRs
|
||||
* as they exist on any CPU that supports VMX, i.e. we want the WARN if
|
||||
* the RDMSR faults.
|
||||
*/
|
||||
rdmsr(MSR_IA32_VMX_PROCBASED_CTLS, ign, supported);
|
||||
c->vmx_capability[PRIMARY_CTLS] = supported;
|
||||
|
||||
rdmsr_safe(MSR_IA32_VMX_PROCBASED_CTLS2, &ign, &supported);
|
||||
c->vmx_capability[SECONDARY_CTLS] = supported;
|
||||
|
||||
rdmsr(MSR_IA32_VMX_PINBASED_CTLS, ign, supported);
|
||||
rdmsr_safe(MSR_IA32_VMX_VMFUNC, &ign, &funcs);
|
||||
|
||||
/*
|
||||
* Except for EPT+VPID, which enumerates support for both in a single
|
||||
* MSR, low for EPT, high for VPID.
|
||||
*/
|
||||
rdmsr_safe(MSR_IA32_VMX_EPT_VPID_CAP, &ept, &vpid);
|
||||
|
||||
/* Pin, EPT, VPID and VM-Func are merged into a single word. */
|
||||
WARN_ON_ONCE(supported >> 16);
|
||||
WARN_ON_ONCE(funcs >> 4);
|
||||
c->vmx_capability[MISC_FEATURES] = (supported & 0xffff) |
|
||||
((vpid & 0x1) << 16) |
|
||||
((funcs & 0xf) << 28);
|
||||
|
||||
/* EPT bits are full on scattered and must be manually handled. */
|
||||
if (ept & VMX_EPT_EXECUTE_ONLY_BIT)
|
||||
c->vmx_capability[MISC_FEATURES] |= VMX_F(EPT_EXECUTE_ONLY);
|
||||
if (ept & VMX_EPT_AD_BIT)
|
||||
c->vmx_capability[MISC_FEATURES] |= VMX_F(EPT_AD);
|
||||
if (ept & VMX_EPT_1GB_PAGE_BIT)
|
||||
c->vmx_capability[MISC_FEATURES] |= VMX_F(EPT_1GB);
|
||||
|
||||
/* Synthetic APIC features that are aggregates of multiple features. */
|
||||
if ((c->vmx_capability[PRIMARY_CTLS] & VMX_F(VIRTUAL_TPR)) &&
|
||||
(c->vmx_capability[SECONDARY_CTLS] & VMX_F(VIRT_APIC_ACCESSES)))
|
||||
c->vmx_capability[MISC_FEATURES] |= VMX_F(FLEXPRIORITY);
|
||||
|
||||
if ((c->vmx_capability[PRIMARY_CTLS] & VMX_F(VIRTUAL_TPR)) &&
|
||||
(c->vmx_capability[SECONDARY_CTLS] & VMX_F(APIC_REGISTER_VIRT)) &&
|
||||
(c->vmx_capability[SECONDARY_CTLS] & VMX_F(VIRT_INTR_DELIVERY)) &&
|
||||
(c->vmx_capability[MISC_FEATURES] & VMX_F(POSTED_INTR)))
|
||||
c->vmx_capability[MISC_FEATURES] |= VMX_F(APICV);
|
||||
}
|
||||
#endif /* CONFIG_X86_VMX_FEATURE_NAMES */
|
||||
|
||||
void init_ia32_feat_ctl(struct cpuinfo_x86 *c)
|
||||
{
|
||||
bool tboot = tboot_enabled();
|
||||
|
@ -50,5 +120,9 @@ update_caps:
|
|||
pr_err_once("VMX (%s TXT) disabled by BIOS\n",
|
||||
tboot ? "inside" : "outside");
|
||||
clear_cpu_cap(c, X86_FEATURE_VMX);
|
||||
} else {
|
||||
#ifdef CONFIG_X86_VMX_FEATURE_NAMES
|
||||
init_vmx_capabilities(c);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue