diff options
author | Yang, Sheng <sheng.yang@intel.com> | 2007-07-31 07:23:01 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-10-13 04:18:22 -0400 |
commit | 002c7f7c32a6123f0894d7d579ffae8e98911830 (patch) | |
tree | 91d46dd1d6f04f25e4f658eb8620fe69c1557c17 /drivers/kvm/vmx.c | |
parent | 39214915f50f6ac2350355f2db63910d968fa790 (diff) |
KVM: VMX: Add cpu consistency check
All the physical CPUs on the board should support the same VMX feature
set. Add check_processor_compatibility to kvm_arch_ops for the consistency
check.
Signed-off-by: Sheng Yang <sheng.yang@intel.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
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 2b30274656f4..c4b8bfea4410 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, | |||
840 | 840 | ||
841 | /* Ensure minimum (required) set of control bits are supported. */ | 841 | /* Ensure minimum (required) set of control bits are supported. */ |
842 | if (ctl_min & ~ctl) | 842 | if (ctl_min & ~ctl) |
843 | return -1; | 843 | return -EIO; |
844 | 844 | ||
845 | *result = ctl; | 845 | *result = ctl; |
846 | return 0; | 846 | return 0; |
847 | } | 847 | } |
848 | 848 | ||
849 | static __init int setup_vmcs_config(void) | 849 | static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) |
850 | { | 850 | { |
851 | u32 vmx_msr_low, vmx_msr_high; | 851 | u32 vmx_msr_low, vmx_msr_high; |
852 | u32 min, opt; | 852 | u32 min, opt; |
@@ -859,7 +859,7 @@ static __init int setup_vmcs_config(void) | |||
859 | opt = 0; | 859 | opt = 0; |
860 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS, | 860 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS, |
861 | &_pin_based_exec_control) < 0) | 861 | &_pin_based_exec_control) < 0) |
862 | return -1; | 862 | return -EIO; |
863 | 863 | ||
864 | min = CPU_BASED_HLT_EXITING | | 864 | min = CPU_BASED_HLT_EXITING | |
865 | #ifdef CONFIG_X86_64 | 865 | #ifdef CONFIG_X86_64 |
@@ -872,7 +872,7 @@ static __init int setup_vmcs_config(void) | |||
872 | opt = 0; | 872 | opt = 0; |
873 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS, | 873 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS, |
874 | &_cpu_based_exec_control) < 0) | 874 | &_cpu_based_exec_control) < 0) |
875 | return -1; | 875 | return -EIO; |
876 | 876 | ||
877 | min = 0; | 877 | min = 0; |
878 | #ifdef CONFIG_X86_64 | 878 | #ifdef CONFIG_X86_64 |
@@ -881,37 +881,37 @@ static __init int setup_vmcs_config(void) | |||
881 | opt = 0; | 881 | opt = 0; |
882 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS, | 882 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS, |
883 | &_vmexit_control) < 0) | 883 | &_vmexit_control) < 0) |
884 | return -1; | 884 | return -EIO; |
885 | 885 | ||
886 | min = opt = 0; | 886 | min = opt = 0; |
887 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS, | 887 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS, |
888 | &_vmentry_control) < 0) | 888 | &_vmentry_control) < 0) |
889 | return -1; | 889 | return -EIO; |
890 | 890 | ||
891 | rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high); | 891 | rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high); |
892 | 892 | ||
893 | /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */ | 893 | /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */ |
894 | if ((vmx_msr_high & 0x1fff) > PAGE_SIZE) | 894 | if ((vmx_msr_high & 0x1fff) > PAGE_SIZE) |
895 | return -1; | 895 | return -EIO; |
896 | 896 | ||
897 | #ifdef CONFIG_X86_64 | 897 | #ifdef CONFIG_X86_64 |
898 | /* IA-32 SDM Vol 3B: 64-bit CPUs always have VMX_BASIC_MSR[48]==0. */ | 898 | /* IA-32 SDM Vol 3B: 64-bit CPUs always have VMX_BASIC_MSR[48]==0. */ |
899 | if (vmx_msr_high & (1u<<16)) | 899 | if (vmx_msr_high & (1u<<16)) |
900 | return -1; | 900 | return -EIO; |
901 | #endif | 901 | #endif |
902 | 902 | ||
903 | /* Require Write-Back (WB) memory type for VMCS accesses. */ | 903 | /* Require Write-Back (WB) memory type for VMCS accesses. */ |
904 | if (((vmx_msr_high >> 18) & 15) != 6) | 904 | if (((vmx_msr_high >> 18) & 15) != 6) |
905 | return -1; | 905 | return -EIO; |
906 | 906 | ||
907 | vmcs_config.size = vmx_msr_high & 0x1fff; | 907 | vmcs_conf->size = vmx_msr_high & 0x1fff; |
908 | vmcs_config.order = get_order(vmcs_config.size); | 908 | vmcs_conf->order = get_order(vmcs_config.size); |
909 | vmcs_config.revision_id = vmx_msr_low; | 909 | vmcs_conf->revision_id = vmx_msr_low; |
910 | 910 | ||
911 | vmcs_config.pin_based_exec_ctrl = _pin_based_exec_control; | 911 | vmcs_conf->pin_based_exec_ctrl = _pin_based_exec_control; |
912 | vmcs_config.cpu_based_exec_ctrl = _cpu_based_exec_control; | 912 | vmcs_conf->cpu_based_exec_ctrl = _cpu_based_exec_control; |
913 | vmcs_config.vmexit_ctrl = _vmexit_control; | 913 | vmcs_conf->vmexit_ctrl = _vmexit_control; |
914 | vmcs_config.vmentry_ctrl = _vmentry_control; | 914 | vmcs_conf->vmentry_ctrl = _vmentry_control; |
915 | 915 | ||
916 | return 0; | 916 | return 0; |
917 | } | 917 | } |
@@ -971,8 +971,8 @@ static __init int alloc_kvm_area(void) | |||
971 | 971 | ||
972 | static __init int hardware_setup(void) | 972 | static __init int hardware_setup(void) |
973 | { | 973 | { |
974 | if (setup_vmcs_config() < 0) | 974 | if (setup_vmcs_config(&vmcs_config) < 0) |
975 | return -1; | 975 | return -EIO; |
976 | return alloc_kvm_area(); | 976 | return alloc_kvm_area(); |
977 | } | 977 | } |
978 | 978 | ||
@@ -2414,11 +2414,26 @@ free_vcpu: | |||
2414 | return ERR_PTR(err); | 2414 | return ERR_PTR(err); |
2415 | } | 2415 | } |
2416 | 2416 | ||
2417 | static void __init vmx_check_processor_compat(void *rtn) | ||
2418 | { | ||
2419 | struct vmcs_config vmcs_conf; | ||
2420 | |||
2421 | *(int *)rtn = 0; | ||
2422 | if (setup_vmcs_config(&vmcs_conf) < 0) | ||
2423 | *(int *)rtn = -EIO; | ||
2424 | if (memcmp(&vmcs_config, &vmcs_conf, sizeof(struct vmcs_config)) != 0) { | ||
2425 | printk(KERN_ERR "kvm: CPU %d feature inconsistency!\n", | ||
2426 | smp_processor_id()); | ||
2427 | *(int *)rtn = -EIO; | ||
2428 | } | ||
2429 | } | ||
2430 | |||
2417 | static struct kvm_arch_ops vmx_arch_ops = { | 2431 | static struct kvm_arch_ops vmx_arch_ops = { |
2418 | .cpu_has_kvm_support = cpu_has_kvm_support, | 2432 | .cpu_has_kvm_support = cpu_has_kvm_support, |
2419 | .disabled_by_bios = vmx_disabled_by_bios, | 2433 | .disabled_by_bios = vmx_disabled_by_bios, |
2420 | .hardware_setup = hardware_setup, | 2434 | .hardware_setup = hardware_setup, |
2421 | .hardware_unsetup = hardware_unsetup, | 2435 | .hardware_unsetup = hardware_unsetup, |
2436 | .check_processor_compatibility = vmx_check_processor_compat, | ||
2422 | .hardware_enable = hardware_enable, | 2437 | .hardware_enable = hardware_enable, |
2423 | .hardware_disable = hardware_disable, | 2438 | .hardware_disable = hardware_disable, |
2424 | 2439 | ||