aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm
diff options
context:
space:
mode:
authorYang, Sheng <sheng.yang@intel.com>2007-07-31 07:23:01 -0400
committerAvi Kivity <avi@qumranet.com>2007-10-13 04:18:22 -0400
commit002c7f7c32a6123f0894d7d579ffae8e98911830 (patch)
tree91d46dd1d6f04f25e4f658eb8620fe69c1557c17 /drivers/kvm
parent39214915f50f6ac2350355f2db63910d968fa790 (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')
-rw-r--r--drivers/kvm/kvm.h1
-rw-r--r--drivers/kvm/kvm_main.c10
-rw-r--r--drivers/kvm/svm.c6
-rw-r--r--drivers/kvm/vmx.c51
4 files changed, 50 insertions, 18 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 7a34706f42be..cfda3abff89a 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -420,6 +420,7 @@ struct kvm_arch_ops {
420 int (*disabled_by_bios)(void); /* __init */ 420 int (*disabled_by_bios)(void); /* __init */
421 void (*hardware_enable)(void *dummy); /* __init */ 421 void (*hardware_enable)(void *dummy); /* __init */
422 void (*hardware_disable)(void *dummy); 422 void (*hardware_disable)(void *dummy);
423 void (*check_processor_compatibility)(void *rtn);
423 int (*hardware_setup)(void); /* __init */ 424 int (*hardware_setup)(void); /* __init */
424 void (*hardware_unsetup)(void); /* __exit */ 425 void (*hardware_unsetup)(void); /* __exit */
425 426
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 5dee3024579d..2be6b1ca1a06 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -3102,6 +3102,7 @@ int kvm_init_arch(struct kvm_arch_ops *ops, unsigned int vcpu_size,
3102 struct module *module) 3102 struct module *module)
3103{ 3103{
3104 int r; 3104 int r;
3105 int cpu;
3105 3106
3106 if (kvm_arch_ops) { 3107 if (kvm_arch_ops) {
3107 printk(KERN_ERR "kvm: already loaded the other module\n"); 3108 printk(KERN_ERR "kvm: already loaded the other module\n");
@@ -3123,6 +3124,14 @@ int kvm_init_arch(struct kvm_arch_ops *ops, unsigned int vcpu_size,
3123 if (r < 0) 3124 if (r < 0)
3124 goto out; 3125 goto out;
3125 3126
3127 for_each_online_cpu(cpu) {
3128 smp_call_function_single(cpu,
3129 kvm_arch_ops->check_processor_compatibility,
3130 &r, 0, 1);
3131 if (r < 0)
3132 goto out_free_0;
3133 }
3134
3126 on_each_cpu(hardware_enable, NULL, 0, 1); 3135 on_each_cpu(hardware_enable, NULL, 0, 1);
3127 r = register_cpu_notifier(&kvm_cpu_notifier); 3136 r = register_cpu_notifier(&kvm_cpu_notifier);
3128 if (r) 3137 if (r)
@@ -3169,6 +3178,7 @@ out_free_2:
3169 unregister_cpu_notifier(&kvm_cpu_notifier); 3178 unregister_cpu_notifier(&kvm_cpu_notifier);
3170out_free_1: 3179out_free_1:
3171 on_each_cpu(hardware_disable, NULL, 0, 1); 3180 on_each_cpu(hardware_disable, NULL, 0, 1);
3181out_free_0:
3172 kvm_arch_ops->hardware_unsetup(); 3182 kvm_arch_ops->hardware_unsetup();
3173out: 3183out:
3174 kvm_arch_ops = NULL; 3184 kvm_arch_ops = NULL;
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 5277084f3a35..827bc2774e73 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -1798,11 +1798,17 @@ svm_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
1798 hypercall[3] = 0xc3; 1798 hypercall[3] = 0xc3;
1799} 1799}
1800 1800
1801static void svm_check_processor_compat(void *rtn)
1802{
1803 *(int *)rtn = 0;
1804}
1805
1801static struct kvm_arch_ops svm_arch_ops = { 1806static struct kvm_arch_ops svm_arch_ops = {
1802 .cpu_has_kvm_support = has_svm, 1807 .cpu_has_kvm_support = has_svm,
1803 .disabled_by_bios = is_disabled, 1808 .disabled_by_bios = is_disabled,
1804 .hardware_setup = svm_hardware_setup, 1809 .hardware_setup = svm_hardware_setup,
1805 .hardware_unsetup = svm_hardware_unsetup, 1810 .hardware_unsetup = svm_hardware_unsetup,
1811 .check_processor_compatibility = svm_check_processor_compat,
1806 .hardware_enable = svm_hardware_enable, 1812 .hardware_enable = svm_hardware_enable,
1807 .hardware_disable = svm_hardware_disable, 1813 .hardware_disable = svm_hardware_disable,
1808 1814
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
849static __init int setup_vmcs_config(void) 849static __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
972static __init int hardware_setup(void) 972static __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
2417static 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
2417static struct kvm_arch_ops vmx_arch_ops = { 2431static 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