All the physical CPUs on the board should support the same VMX feature
set.
The hardware_enable() do the per-cpu check now.
In case of vmx/svm enabling failure, transfer a variable in
hardware_enable()
for error report.

Signed-off-by: Sheng Yang <[EMAIL PROTECTED]>
---
 drivers/kvm/kvm_main.c |    9 +++--
 drivers/kvm/svm.c      |    3 +-
 drivers/kvm/vmx.c      |   84
+++++++++++++++++++++++++++++-------------------
 3 files changed, 59 insertions(+), 37 deletions(-)

diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index bc11c2d..10443ea 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -2974,14 +2974,14 @@ static void decache_vcpus_on_cpu(int cpu)
        spin_unlock(&kvm_lock);
 }
 
-static void hardware_enable(void *junk)
+static void hardware_enable(void *rtn)
 {
        int cpu = raw_smp_processor_id();
 
        if (cpu_isset(cpu, cpus_hardware_enabled))
                return;
        cpu_set(cpu, cpus_hardware_enabled);
-       kvm_arch_ops->hardware_enable(NULL);
+       kvm_arch_ops->hardware_enable(rtn);
 }
 
 static void hardware_disable(void *junk)
@@ -3173,7 +3173,10 @@ int kvm_init_arch(struct kvm_arch_ops *ops,
struct module *module)
        if (r < 0)
                goto out;
 
-       on_each_cpu(hardware_enable, NULL, 0, 1);
+       on_each_cpu(hardware_enable, &r, 0, 1);
+       if (r < 0)
+               goto out;
+
        r = register_cpu_notifier(&kvm_cpu_notifier);
        if (r)
                goto out_free_1;
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 850a1b1..1e76417 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -285,7 +285,7 @@ static void svm_hardware_disable(void *garbage)
        }
 }
 
-static void svm_hardware_enable(void *garbage)
+static void svm_hardware_enable(void *rtn)
 {
 
        struct svm_cpu_data *svm_data;
@@ -298,6 +298,7 @@ static void svm_hardware_enable(void *garbage)
        struct desc_struct *gdt;
        int me = raw_smp_processor_id();
 
+       *(int*)rtn = 0;
        if (!has_svm()) {
                printk(KERN_ERR "svm_cpu_init: err EOPNOTSUPP on %d\n",
me);
                return;
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index e5721a5..8032c7e 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -756,31 +756,6 @@ static __init int vmx_disabled_by_bios(void)
        /* locked but not enabled */
 }
 
-static void hardware_enable(void *garbage)
-{
-       int cpu = raw_smp_processor_id();
-       u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
-       u64 old;
-
-       rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
-       if ((old & (MSR_IA32_FEATURE_CONTROL_LOCKED |
-                   MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED))
-           != (MSR_IA32_FEATURE_CONTROL_LOCKED |
-               MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED))
-               /* enable and lock */
-               wrmsrl(MSR_IA32_FEATURE_CONTROL, old |
-                      MSR_IA32_FEATURE_CONTROL_LOCKED |
-                      MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED);
-       write_cr4(read_cr4() | X86_CR4_VMXE); /* FIXME: not cpu hotplug
safe */
-       asm volatile (ASM_VMX_VMXON_RAX : : "a"(&phys_addr),
"m"(phys_addr)
-                     : "memory", "cc");
-}
-
-static void hardware_disable(void *garbage)
-{
-       asm volatile (ASM_VMX_VMXOFF : : : "cc");
-}
-
 static __init int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt,
                                      u32 msr, u32* result)
 {
@@ -856,18 +831,61 @@ static __init int setup_vmcs_config(void)
        if (((vmx_msr_high >> 18) & 15) != 6)
                return -1;
 
-       vmcs_config.size = vmx_msr_high & 0x1fff;
-       vmcs_config.order = get_order(vmcs_config.size);
-       vmcs_config.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;
+       if (vmcs_config.size == 0) {
+               /* called in hardware_setup(), initialization */
+               vmcs_config.size = vmx_msr_high & 0x1fff;
+               vmcs_config.order = get_order(vmcs_config.size);
+               vmcs_config.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;
+       } else if ((vmcs_config.size != (vmx_msr_high & 0x1fff))
+               || (vmcs_config.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)) {
+               /* called in hardware_enable(), check consistence */
+               printk(KERN_ERR "kvm: CPUs feature inconsistence!\n");
+               return -1;
+       }
 
        return 0;
 }
 
+static void hardware_enable(void *rtn)
+{
+       int cpu = raw_smp_processor_id();
+       u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
+       u64 old;
+
+       rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
+       if ((old & (MSR_IA32_FEATURE_CONTROL_LOCKED |
+                   MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED))
+           != (MSR_IA32_FEATURE_CONTROL_LOCKED |
+               MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED))
+               /* enable and lock */
+               wrmsrl(MSR_IA32_FEATURE_CONTROL, old |
+                      MSR_IA32_FEATURE_CONTROL_LOCKED |
+                      MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED);
+
+       *(int*)rtn = setup_vmcs_config(); /* check cpus' feature
consistence */
+       if (rtn < 0)
+               return;
+
+       write_cr4(read_cr4() | X86_CR4_VMXE); /* FIXME: not cpu hotplug
safe */
+       asm volatile (ASM_VMX_VMXON_RAX : : "a"(&phys_addr),
"m"(phys_addr)
+                     : "memory", "cc");
+
+}
+
+static void hardware_disable(void *garbage)
+{
+       asm volatile (ASM_VMX_VMXOFF : : : "cc");
+}
+
 static struct vmcs *alloc_vmcs_cpu(int cpu)
 {
        int node = cpu_to_node(cpu);
-- 
1.5.2

Attachment: Add-cpu-consistence-check-in-vmx.patch
Description: Add-cpu-consistence-check-in-vmx.patch

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to