aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2013-10-04 12:29:08 +0200
committerJan Beulich <jbeulich@suse.com>2013-10-04 12:29:08 +0200
commit1332d0e907fd5b6075241d36257f8faef5ec97a7 (patch)
treec6cbe04d13373ab8e6366ba39ab3f294bf0eebd9
parent190b667ac20e8175758f4a3a0f13c4d990e6af7e (diff)
downloadxen-1332d0e907fd5b6075241d36257f8faef5ec97a7.tar.gz
xen-1332d0e907fd5b6075241d36257f8faef5ec97a7.tar.bz2
xen-1332d0e907fd5b6075241d36257f8faef5ec97a7.zip
VMX: clean up capability checks
VMCS size validation on APs should check against BP's size. No need for a separate cpu_has_vmx_ins_outs_instr_info variable anymore. Use proper symbolics. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Jun Nakajima <jun.nakajima@intel.com>
-rw-r--r--xen/arch/x86/hvm/vmx/vmcs.c44
-rw-r--r--xen/include/asm-x86/hvm/vmx/vmcs.h10
2 files changed, 35 insertions, 19 deletions
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index b64ec6fa13..65265048f3 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -70,7 +70,6 @@ u32 vmx_secondary_exec_control __read_mostly;
u32 vmx_vmexit_control __read_mostly;
u32 vmx_vmentry_control __read_mostly;
u64 vmx_ept_vpid_cap __read_mostly;
-bool_t cpu_has_vmx_ins_outs_instr_info __read_mostly;
static DEFINE_PER_CPU_READ_MOSTLY(struct vmcs_struct *, vmxon_region);
static DEFINE_PER_CPU(struct vmcs_struct *, current_vmcs);
@@ -294,24 +293,33 @@ static int vmx_init_vmcs_config(void)
if ( !vmx_pin_based_exec_control )
{
/* First time through. */
- vmcs_revision_id = vmx_basic_msr_low;
+ vmcs_revision_id = vmx_basic_msr_low & VMX_BASIC_REVISION_MASK;
vmx_pin_based_exec_control = _vmx_pin_based_exec_control;
vmx_cpu_based_exec_control = _vmx_cpu_based_exec_control;
vmx_secondary_exec_control = _vmx_secondary_exec_control;
vmx_ept_vpid_cap = _vmx_ept_vpid_cap;
vmx_vmexit_control = _vmx_vmexit_control;
vmx_vmentry_control = _vmx_vmentry_control;
- cpu_has_vmx_ins_outs_instr_info = !!(vmx_basic_msr_high & (1U<<22));
vmx_basic_msr = ((u64)vmx_basic_msr_high << 32) |
vmx_basic_msr_low;
vmx_display_features();
+
+ /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */
+ if ( (vmx_basic_msr_high & (VMX_BASIC_VMCS_SIZE_MASK >> 32)) >
+ PAGE_SIZE )
+ {
+ printk("VMX: CPU%d VMCS size is too big (%Lu bytes)\n",
+ smp_processor_id(),
+ vmx_basic_msr_high & (VMX_BASIC_VMCS_SIZE_MASK >> 32));
+ return -EINVAL;
+ }
}
else
{
/* Globals are already initialised: re-check them. */
mismatch |= cap_check(
"VMCS revision ID",
- vmcs_revision_id, vmx_basic_msr_low);
+ vmcs_revision_id, vmx_basic_msr_low & VMX_BASIC_REVISION_MASK);
mismatch |= cap_check(
"Pin-Based Exec Control",
vmx_pin_based_exec_control, _vmx_pin_based_exec_control);
@@ -331,13 +339,21 @@ static int vmx_init_vmcs_config(void)
"EPT and VPID Capability",
vmx_ept_vpid_cap, _vmx_ept_vpid_cap);
if ( cpu_has_vmx_ins_outs_instr_info !=
- !!(vmx_basic_msr_high & (1U<<22)) )
+ !!(vmx_basic_msr_high & (VMX_BASIC_INS_OUT_INFO >> 32)) )
{
printk("VMX INS/OUTS Instruction Info: saw %d expected %d\n",
- !!(vmx_basic_msr_high & (1U<<22)),
+ !!(vmx_basic_msr_high & (VMX_BASIC_INS_OUT_INFO >> 32)),
cpu_has_vmx_ins_outs_instr_info);
mismatch = 1;
}
+ if ( (vmx_basic_msr_high & (VMX_BASIC_VMCS_SIZE_MASK >> 32)) !=
+ ((vmx_basic_msr & VMX_BASIC_VMCS_SIZE_MASK) >> 32) )
+ {
+ printk("VMX: CPU%d unexpected VMCS size %Lu\n",
+ smp_processor_id(),
+ vmx_basic_msr_high & (VMX_BASIC_VMCS_SIZE_MASK >> 32));
+ mismatch = 1;
+ }
if ( mismatch )
{
printk("VMX: Capabilities fatally differ between CPU%d and CPU0\n",
@@ -346,16 +362,8 @@ static int vmx_init_vmcs_config(void)
}
}
- /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */
- if ( (vmx_basic_msr_high & 0x1fff) > PAGE_SIZE )
- {
- printk("VMX: CPU%d VMCS size is too big (%u bytes)\n",
- smp_processor_id(), vmx_basic_msr_high & 0x1fff);
- return -EINVAL;
- }
-
/* IA-32 SDM Vol 3B: 64-bit CPUs always have VMX_BASIC_MSR[48]==0. */
- if ( vmx_basic_msr_high & (1u<<16) )
+ if ( vmx_basic_msr_high & (VMX_BASIC_32BIT_ADDRESSES >> 32) )
{
printk("VMX: CPU%d limits VMX structure pointers to 32 bits\n",
smp_processor_id());
@@ -363,10 +371,12 @@ static int vmx_init_vmcs_config(void)
}
/* Require Write-Back (WB) memory type for VMCS accesses. */
- if ( ((vmx_basic_msr_high >> 18) & 15) != 6 )
+ opt = (vmx_basic_msr_high & (VMX_BASIC_MEMORY_TYPE_MASK >> 32)) /
+ ((VMX_BASIC_MEMORY_TYPE_MASK & -VMX_BASIC_MEMORY_TYPE_MASK) >> 32);
+ if ( opt != MTRR_TYPE_WRBACK )
{
printk("VMX: CPU%d has unexpected VMCS access type %u\n",
- smp_processor_id(), (vmx_basic_msr_high >> 18) & 15);
+ smp_processor_id(), opt);
return -EINVAL;
}
diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h
index 8c123c7655..b50352f673 100644
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -210,8 +210,6 @@ extern u32 vmx_vmentry_control;
#define SECONDARY_EXEC_ENABLE_VMCS_SHADOWING 0x00004000
extern u32 vmx_secondary_exec_control;
-extern bool_t cpu_has_vmx_ins_outs_instr_info;
-
#define VMX_EPT_EXEC_ONLY_SUPPORTED 0x00000001
#define VMX_EPT_WALK_LENGTH_4_SUPPORTED 0x00000040
#define VMX_EPT_MEMORY_TYPE_UC 0x00000100
@@ -278,6 +276,12 @@ extern bool_t cpu_has_vmx_ins_outs_instr_info;
#define VMX_INTR_SHADOW_SMI 0x00000004
#define VMX_INTR_SHADOW_NMI 0x00000008
+#define VMX_BASIC_REVISION_MASK 0x7fffffff
+#define VMX_BASIC_VMCS_SIZE_MASK (0x1fffULL << 32)
+#define VMX_BASIC_32BIT_ADDRESSES (1ULL << 48)
+#define VMX_BASIC_DUAL_MONITOR (1ULL << 49)
+#define VMX_BASIC_MEMORY_TYPE_MASK (0xfULL << 50)
+#define VMX_BASIC_INS_OUT_INFO (1ULL << 54)
/*
* bit 55 of IA32_VMX_BASIC MSR, indicating whether any VMX controls that
* default to 1 may be cleared to 0.
@@ -285,6 +289,8 @@ extern bool_t cpu_has_vmx_ins_outs_instr_info;
#define VMX_BASIC_DEFAULT1_ZERO (1ULL << 55)
extern u64 vmx_basic_msr;
+#define cpu_has_vmx_ins_outs_instr_info \
+ (!!(vmx_basic_msr & VMX_BASIC_INS_OUT_INFO))
/* Guest interrupt status */
#define VMX_GUEST_INTR_STATUS_SUBFIELD_BITMASK 0x0FF