diff options
Diffstat (limited to 'drivers/kvm/vmx.c')
-rw-r--r-- | drivers/kvm/vmx.c | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index 2b30274656f..c4b8bfea441 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c @@ -840,13 +840,13 @@ static __init int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt, /* Ensure minimum (required) set of control bits are supported. */ if (ctl_min & ~ctl) - return -1; + return -EIO; *result = ctl; return 0; } -static __init int setup_vmcs_config(void) +static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) { u32 vmx_msr_low, vmx_msr_high; u32 min, opt; @@ -859,7 +859,7 @@ static __init int setup_vmcs_config(void) opt = 0; if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS, &_pin_based_exec_control) < 0) - return -1; + return -EIO; min = CPU_BASED_HLT_EXITING | #ifdef CONFIG_X86_64 @@ -872,7 +872,7 @@ static __init int setup_vmcs_config(void) opt = 0; if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS, &_cpu_based_exec_control) < 0) - return -1; + return -EIO; min = 0; #ifdef CONFIG_X86_64 @@ -881,37 +881,37 @@ static __init int setup_vmcs_config(void) opt = 0; if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS, &_vmexit_control) < 0) - return -1; + return -EIO; min = opt = 0; if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS, &_vmentry_control) < 0) - return -1; + return -EIO; rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high); /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */ if ((vmx_msr_high & 0x1fff) > PAGE_SIZE) - return -1; + return -EIO; #ifdef CONFIG_X86_64 /* IA-32 SDM Vol 3B: 64-bit CPUs always have VMX_BASIC_MSR[48]==0. */ if (vmx_msr_high & (1u<<16)) - return -1; + return -EIO; #endif /* Require Write-Back (WB) memory type for VMCS accesses. */ if (((vmx_msr_high >> 18) & 15) != 6) - return -1; + return -EIO; - vmcs_config.size = vmx_msr_high & 0x1fff; - vmcs_config.order = get_order(vmcs_config.size); - vmcs_config.revision_id = vmx_msr_low; + vmcs_conf->size = vmx_msr_high & 0x1fff; + vmcs_conf->order = get_order(vmcs_config.size); + vmcs_conf->revision_id = vmx_msr_low; - vmcs_config.pin_based_exec_ctrl = _pin_based_exec_control; - vmcs_config.cpu_based_exec_ctrl = _cpu_based_exec_control; - vmcs_config.vmexit_ctrl = _vmexit_control; - vmcs_config.vmentry_ctrl = _vmentry_control; + vmcs_conf->pin_based_exec_ctrl = _pin_based_exec_control; + vmcs_conf->cpu_based_exec_ctrl = _cpu_based_exec_control; + vmcs_conf->vmexit_ctrl = _vmexit_control; + vmcs_conf->vmentry_ctrl = _vmentry_control; return 0; } @@ -971,8 +971,8 @@ static __init int alloc_kvm_area(void) static __init int hardware_setup(void) { - if (setup_vmcs_config() < 0) - return -1; + if (setup_vmcs_config(&vmcs_config) < 0) + return -EIO; return alloc_kvm_area(); } @@ -2414,11 +2414,26 @@ free_vcpu: return ERR_PTR(err); } +static void __init vmx_check_processor_compat(void *rtn) +{ + struct vmcs_config vmcs_conf; + + *(int *)rtn = 0; + if (setup_vmcs_config(&vmcs_conf) < 0) + *(int *)rtn = -EIO; + if (memcmp(&vmcs_config, &vmcs_conf, sizeof(struct vmcs_config)) != 0) { + printk(KERN_ERR "kvm: CPU %d feature inconsistency!\n", + smp_processor_id()); + *(int *)rtn = -EIO; + } +} + static struct kvm_arch_ops vmx_arch_ops = { .cpu_has_kvm_support = cpu_has_kvm_support, .disabled_by_bios = vmx_disabled_by_bios, .hardware_setup = hardware_setup, .hardware_unsetup = hardware_unsetup, + .check_processor_compatibility = vmx_check_processor_compat, .hardware_enable = hardware_enable, .hardware_disable = hardware_disable, |