struct module *module)
 {
        int r;
+       int cpu;
 
        if (kvm_arch_ops) {
                printk(KERN_ERR "kvm: already loaded the other module\n");
        if (r < 0)
                goto out;
 
+       for_each_online_cpu(cpu) {
+               smp_call_function_single(cpu,
+                               kvm_arch_ops->check_processor_compatibility,
+                               &r, 0, 1);
+               if (r < 0)
+                       goto out_free_0;
+       }
+
        on_each_cpu(hardware_enable, NULL, 0, 1);
        r = register_cpu_notifier(&kvm_cpu_notifier);
        if (r)
        unregister_cpu_notifier(&kvm_cpu_notifier);
 out_free_1:
        on_each_cpu(hardware_disable, NULL, 0, 1);
+out_free_0:
        kvm_arch_ops->hardware_unsetup();
 out:
        kvm_arch_ops = NULL;
 
        hypercall[3] = 0xc3;
 }
 
+static void svm_check_processor_compat(void *rtn)
+{
+       *(int *)rtn = 0;
+}
+
 static struct kvm_arch_ops svm_arch_ops = {
        .cpu_has_kvm_support = has_svm,
        .disabled_by_bios = is_disabled,
        .hardware_setup = svm_hardware_setup,
        .hardware_unsetup = svm_hardware_unsetup,
+       .check_processor_compatibility = svm_check_processor_compat,
        .hardware_enable = svm_hardware_enable,
        .hardware_disable = svm_hardware_disable,
 
 
 
        /* 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;
        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
        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
        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;
 }
 
 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();
 }
 
        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,