KVM: Replace get_mt_mask_shift with get_mt_mask
[safe/jmp/linux-2.6] / arch / x86 / kvm / vmx.c
index 2adfacb..59b080c 100644 (file)
@@ -16,7 +16,6 @@
  */
 
 #include "irq.h"
-#include "vmx.h"
 #include "mmu.h"
 
 #include <linux/kvm_host.h>
 #include <linux/sched.h>
 #include <linux/moduleparam.h>
 #include "kvm_cache_regs.h"
+#include "x86.h"
 
 #include <asm/io.h>
 #include <asm/desc.h>
+#include <asm/vmx.h>
+#include <asm/virtext.h>
 
 #define __ex(x) __kvm_handle_fault_on_reboot(x)
 
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
-static int bypass_guest_pf = 1;
-module_param(bypass_guest_pf, bool, 0);
+static int __read_mostly bypass_guest_pf = 1;
+module_param(bypass_guest_pf, bool, S_IRUGO);
 
-static int enable_vpid = 1;
-module_param(enable_vpid, bool, 0);
+static int __read_mostly enable_vpid = 1;
+module_param_named(vpid, enable_vpid, bool, 0444);
 
-static int flexpriority_enabled = 1;
-module_param(flexpriority_enabled, bool, 0);
+static int __read_mostly flexpriority_enabled = 1;
+module_param_named(flexpriority, flexpriority_enabled, bool, S_IRUGO);
 
-static int enable_ept = 1;
-module_param(enable_ept, bool, 0);
+static int __read_mostly enable_ept = 1;
+module_param_named(ept, enable_ept, bool, S_IRUGO);
+
+static int __read_mostly emulate_invalid_guest_state = 0;
+module_param(emulate_invalid_guest_state, bool, S_IRUGO);
 
 struct vmcs {
        u32 revision_id;
@@ -57,6 +62,7 @@ struct vmcs {
 struct vcpu_vmx {
        struct kvm_vcpu       vcpu;
        struct list_head      local_vcpus_link;
+       unsigned long         host_rsp;
        int                   launched;
        u8                    fail;
        u32                   idt_vectoring_info;
@@ -84,6 +90,13 @@ struct vcpu_vmx {
                } irq;
        } rmode;
        int vpid;
+       bool emulation_required;
+       enum emulation_result invalid_state_emulation_result;
+
+       /* Support for vnmi-less CPUs */
+       int soft_vnmi_blocked;
+       ktime_t entry_time;
+       s64 vnmi_blocked_time;
 };
 
 static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
@@ -98,9 +111,10 @@ static DEFINE_PER_CPU(struct vmcs *, vmxarea);
 static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
 static DEFINE_PER_CPU(struct list_head, vcpus_on_cpu);
 
-static struct page *vmx_io_bitmap_a;
-static struct page *vmx_io_bitmap_b;
-static struct page *vmx_msr_bitmap;
+static unsigned long *vmx_io_bitmap_a;
+static unsigned long *vmx_io_bitmap_b;
+static unsigned long *vmx_msr_bitmap_legacy;
+static unsigned long *vmx_msr_bitmap_longmode;
 
 static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
 static DEFINE_SPINLOCK(vmx_vpid_lock);
@@ -116,7 +130,7 @@ static struct vmcs_config {
        u32 vmentry_ctrl;
 } vmcs_config;
 
-struct vmx_capability {
+static struct vmx_capability {
        u32 ept;
        u32 vpid;
 } vmx_capability;
@@ -177,21 +191,21 @@ static inline int is_page_fault(u32 intr_info)
 {
        return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
                             INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK);
+               (INTR_TYPE_HARD_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK);
 }
 
 static inline int is_no_device(u32 intr_info)
 {
        return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
                             INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_EXCEPTION | NM_VECTOR | INTR_INFO_VALID_MASK);
+               (INTR_TYPE_HARD_EXCEPTION | NM_VECTOR | INTR_INFO_VALID_MASK);
 }
 
 static inline int is_invalid_opcode(u32 intr_info)
 {
        return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
                             INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_EXCEPTION | UD_VECTOR | INTR_INFO_VALID_MASK);
+               (INTR_TYPE_HARD_EXCEPTION | UD_VECTOR | INTR_INFO_VALID_MASK);
 }
 
 static inline int is_external_interrupt(u32 intr_info)
@@ -202,68 +216,69 @@ static inline int is_external_interrupt(u32 intr_info)
 
 static inline int cpu_has_vmx_msr_bitmap(void)
 {
-       return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS);
+       return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS;
 }
 
 static inline int cpu_has_vmx_tpr_shadow(void)
 {
-       return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW);
+       return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW;
 }
 
 static inline int vm_need_tpr_shadow(struct kvm *kvm)
 {
-       return ((cpu_has_vmx_tpr_shadow()) && (irqchip_in_kernel(kvm)));
+       return (cpu_has_vmx_tpr_shadow()) && (irqchip_in_kernel(kvm));
 }
 
 static inline int cpu_has_secondary_exec_ctrls(void)
 {
-       return (vmcs_config.cpu_based_exec_ctrl &
-               CPU_BASED_ACTIVATE_SECONDARY_CONTROLS);
+       return vmcs_config.cpu_based_exec_ctrl &
+               CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
 }
 
 static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
 {
-       return flexpriority_enabled
-               && (vmcs_config.cpu_based_2nd_exec_ctrl &
-                   SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
+       return vmcs_config.cpu_based_2nd_exec_ctrl &
+               SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+}
+
+static inline bool cpu_has_vmx_flexpriority(void)
+{
+       return cpu_has_vmx_tpr_shadow() &&
+               cpu_has_vmx_virtualize_apic_accesses();
 }
 
 static inline int cpu_has_vmx_invept_individual_addr(void)
 {
-       return (!!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT));
+       return !!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT);
 }
 
 static inline int cpu_has_vmx_invept_context(void)
 {
-       return (!!(vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT));
+       return !!(vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT);
 }
 
 static inline int cpu_has_vmx_invept_global(void)
 {
-       return (!!(vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT));
+       return !!(vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT);
 }
 
 static inline int cpu_has_vmx_ept(void)
 {
-       return (vmcs_config.cpu_based_2nd_exec_ctrl &
-               SECONDARY_EXEC_ENABLE_EPT);
-}
-
-static inline int vm_need_ept(void)
-{
-       return (cpu_has_vmx_ept() && enable_ept);
+       return vmcs_config.cpu_based_2nd_exec_ctrl &
+               SECONDARY_EXEC_ENABLE_EPT;
 }
 
 static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm)
 {
-       return ((cpu_has_vmx_virtualize_apic_accesses()) &&
-               (irqchip_in_kernel(kvm)));
+       return flexpriority_enabled &&
+               (cpu_has_vmx_virtualize_apic_accesses()) &&
+               (irqchip_in_kernel(kvm));
 }
 
 static inline int cpu_has_vmx_vpid(void)
 {
-       return (vmcs_config.cpu_based_2nd_exec_ctrl &
-               SECONDARY_EXEC_ENABLE_VPID);
+       return vmcs_config.cpu_based_2nd_exec_ctrl &
+               SECONDARY_EXEC_ENABLE_VPID;
 }
 
 static inline int cpu_has_virtual_nmis(void)
@@ -271,6 +286,11 @@ static inline int cpu_has_virtual_nmis(void)
        return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
 }
 
+static inline bool report_flexpriority(void)
+{
+       return flexpriority_enabled;
+}
+
 static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
 {
        int i;
@@ -368,7 +388,7 @@ static inline void ept_sync_global(void)
 
 static inline void ept_sync_context(u64 eptp)
 {
-       if (vm_need_ept()) {
+       if (enable_ept) {
                if (cpu_has_vmx_invept_context())
                        __invept(VMX_EPT_EXTENT_CONTEXT, eptp, 0);
                else
@@ -378,7 +398,7 @@ static inline void ept_sync_context(u64 eptp)
 
 static inline void ept_sync_individual_addr(u64 eptp, gpa_t gpa)
 {
-       if (vm_need_ept()) {
+       if (enable_ept) {
                if (cpu_has_vmx_invept_individual_addr())
                        __invept(VMX_EPT_EXTENT_INDIVIDUAL_ADDR,
                                        eptp, gpa);
@@ -468,11 +488,16 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
        eb = (1u << PF_VECTOR) | (1u << UD_VECTOR);
        if (!vcpu->fpu_active)
                eb |= 1u << NM_VECTOR;
-       if (vcpu->guest_debug.enabled)
-               eb |= 1u << 1;
+       if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
+               if (vcpu->guest_debug &
+                   (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
+                       eb |= 1u << DB_VECTOR;
+               if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
+                       eb |= 1u << BP_VECTOR;
+       }
        if (vcpu->arch.rmode.active)
                eb = ~0;
-       if (vm_need_ept())
+       if (enable_ept)
                eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
        vmcs_write32(EXCEPTION_BITMAP, eb);
 }
@@ -728,25 +753,39 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
        if (interruptibility & 3)
                vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
                             interruptibility & ~3);
-       vcpu->arch.interrupt_window_open = 1;
 }
 
 static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
                                bool has_error_code, u32 error_code)
 {
-       vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
-                    nr | INTR_TYPE_EXCEPTION
-                    | (has_error_code ? INTR_INFO_DELIVER_CODE_MASK : 0)
-                    | INTR_INFO_VALID_MASK);
-       if (has_error_code)
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       u32 intr_info = nr | INTR_INFO_VALID_MASK;
+
+       if (has_error_code) {
                vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
-}
+               intr_info |= INTR_INFO_DELIVER_CODE_MASK;
+       }
 
-static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
-{
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       if (vcpu->arch.rmode.active) {
+               vmx->rmode.irq.pending = true;
+               vmx->rmode.irq.vector = nr;
+               vmx->rmode.irq.rip = kvm_rip_read(vcpu);
+               if (nr == BP_VECTOR || nr == OF_VECTOR)
+                       vmx->rmode.irq.rip++;
+               intr_info |= INTR_TYPE_SOFT_INTR;
+               vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
+               vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
+               kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1);
+               return;
+       }
 
-       return !(vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+       if (nr == BP_VECTOR || nr == OF_VECTOR) {
+               vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
+               intr_info |= INTR_TYPE_SOFT_EXCEPTION;
+       } else
+               intr_info |= INTR_TYPE_HARD_EXCEPTION;
+
+       vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
 }
 
 /*
@@ -774,6 +813,7 @@ static void move_msr_up(struct vcpu_vmx *vmx, int from, int to)
 static void setup_msrs(struct vcpu_vmx *vmx)
 {
        int save_nmsrs;
+       unsigned long *msr_bitmap;
 
        vmx_load_host_state(vmx);
        save_nmsrs = 0;
@@ -809,6 +849,15 @@ static void setup_msrs(struct vcpu_vmx *vmx)
                __find_msr_index(vmx, MSR_KERNEL_GS_BASE);
 #endif
        vmx->msr_offset_efer = __find_msr_index(vmx, MSR_EFER);
+
+       if (cpu_has_vmx_msr_bitmap()) {
+               if (is_long_mode(&vmx->vcpu))
+                       msr_bitmap = vmx_msr_bitmap_longmode;
+               else
+                       msr_bitmap = vmx_msr_bitmap_legacy;
+
+               vmcs_write64(MSR_BITMAP, __pa(msr_bitmap));
+       }
 }
 
 /*
@@ -828,11 +877,8 @@ static u64 guest_read_tsc(void)
  * writes 'guest_tsc' into guest's timestamp counter "register"
  * guest_tsc = host_tsc + tsc_offset ==> tsc_offset = guest_tsc - host_tsc
  */
-static void guest_write_tsc(u64 guest_tsc)
+static void guest_write_tsc(u64 guest_tsc, u64 host_tsc)
 {
-       u64 host_tsc;
-
-       rdtscll(host_tsc);
        vmcs_write64(TSC_OFFSET, guest_tsc - host_tsc);
 }
 
@@ -875,6 +921,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
                data = vmcs_readl(GUEST_SYSENTER_ESP);
                break;
        default:
+               vmx_load_host_state(to_vmx(vcpu));
                msr = find_msr_entry(to_vmx(vcpu), msr_index);
                if (msr) {
                        data = msr->data;
@@ -896,14 +943,15 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        struct kvm_msr_entry *msr;
+       u64 host_tsc;
        int ret = 0;
 
        switch (msr_index) {
-#ifdef CONFIG_X86_64
        case MSR_EFER:
                vmx_load_host_state(vmx);
                ret = kvm_set_msr_common(vcpu, msr_index, data);
                break;
+#ifdef CONFIG_X86_64
        case MSR_FS_BASE:
                vmcs_writel(GUEST_FS_BASE, data);
                break;
@@ -921,7 +969,8 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
                vmcs_writel(GUEST_SYSENTER_ESP, data);
                break;
        case MSR_IA32_TIME_STAMP_COUNTER:
-               guest_write_tsc(data);
+               rdtscll(host_tsc);
+               guest_write_tsc(data, host_tsc);
                break;
        case MSR_P6_PERFCTR0:
        case MSR_P6_PERFCTR1:
@@ -935,6 +984,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
                pr_unimpl(vcpu, "unimplemented perfctr wrmsr: 0x%x data 0x%llx\n", msr_index, data);
 
                break;
+       case MSR_IA32_CR_PAT:
+               if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
+                       vmcs_write64(GUEST_IA32_PAT, data);
+                       vcpu->arch.pat = data;
+                       break;
+               }
+               /* Otherwise falls through to kvm_set_msr_common */
        default:
                vmx_load_host_state(vmx);
                msr = find_msr_entry(vmx, msr_index);
@@ -963,63 +1019,35 @@ static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
        }
 }
 
-static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
+static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
 {
-       unsigned long dr7 = 0x400;
-       int old_singlestep;
-
-       old_singlestep = vcpu->guest_debug.singlestep;
-
-       vcpu->guest_debug.enabled = dbg->enabled;
-       if (vcpu->guest_debug.enabled) {
-               int i;
+       int old_debug = vcpu->guest_debug;
+       unsigned long flags;
 
-               dr7 |= 0x200;  /* exact */
-               for (i = 0; i < 4; ++i) {
-                       if (!dbg->breakpoints[i].enabled)
-                               continue;
-                       vcpu->guest_debug.bp[i] = dbg->breakpoints[i].address;
-                       dr7 |= 2 << (i*2);    /* global enable */
-                       dr7 |= 0 << (i*4+16); /* execution breakpoint */
-               }
+       vcpu->guest_debug = dbg->control;
+       if (!(vcpu->guest_debug & KVM_GUESTDBG_ENABLE))
+               vcpu->guest_debug = 0;
 
-               vcpu->guest_debug.singlestep = dbg->singlestep;
-       } else
-               vcpu->guest_debug.singlestep = 0;
-
-       if (old_singlestep && !vcpu->guest_debug.singlestep) {
-               unsigned long flags;
+       if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)
+               vmcs_writel(GUEST_DR7, dbg->arch.debugreg[7]);
+       else
+               vmcs_writel(GUEST_DR7, vcpu->arch.dr7);
 
-               flags = vmcs_readl(GUEST_RFLAGS);
+       flags = vmcs_readl(GUEST_RFLAGS);
+       if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
+               flags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
+       else if (old_debug & KVM_GUESTDBG_SINGLESTEP)
                flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
-               vmcs_writel(GUEST_RFLAGS, flags);
-       }
+       vmcs_writel(GUEST_RFLAGS, flags);
 
        update_exception_bitmap(vcpu);
-       vmcs_writel(GUEST_DR7, dr7);
 
        return 0;
 }
 
-static int vmx_get_irq(struct kvm_vcpu *vcpu)
-{
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
-       u32 idtv_info_field;
-
-       idtv_info_field = vmx->idt_vectoring_info;
-       if (idtv_info_field & INTR_INFO_VALID_MASK) {
-               if (is_external_interrupt(idtv_info_field))
-                       return idtv_info_field & VECTORING_INFO_VECTOR_MASK;
-               else
-                       printk(KERN_DEBUG "pending exception: not handled yet\n");
-       }
-       return -1;
-}
-
 static __init int cpu_has_kvm_support(void)
 {
-       unsigned long ecx = cpuid_ecx(1);
-       return test_bit(5, &ecx); /* CPUID.1:ECX.VMX[bit 5] -> VT */
+       return cpu_has_vmx();
 }
 
 static __init int vmx_disabled_by_bios(void)
@@ -1027,9 +1055,9 @@ static __init int vmx_disabled_by_bios(void)
        u64 msr;
 
        rdmsrl(MSR_IA32_FEATURE_CONTROL, msr);
-       return (msr & (IA32_FEATURE_CONTROL_LOCKED_BIT |
-                      IA32_FEATURE_CONTROL_VMXON_ENABLED_BIT))
-           == IA32_FEATURE_CONTROL_LOCKED_BIT;
+       return (msr & (FEATURE_CONTROL_LOCKED |
+                      FEATURE_CONTROL_VMXON_ENABLED))
+           == FEATURE_CONTROL_LOCKED;
        /* locked but not enabled */
 }
 
@@ -1041,14 +1069,14 @@ static void hardware_enable(void *garbage)
 
        INIT_LIST_HEAD(&per_cpu(vcpus_on_cpu, cpu));
        rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
-       if ((old & (IA32_FEATURE_CONTROL_LOCKED_BIT |
-                   IA32_FEATURE_CONTROL_VMXON_ENABLED_BIT))
-           != (IA32_FEATURE_CONTROL_LOCKED_BIT |
-               IA32_FEATURE_CONTROL_VMXON_ENABLED_BIT))
+       if ((old & (FEATURE_CONTROL_LOCKED |
+                   FEATURE_CONTROL_VMXON_ENABLED))
+           != (FEATURE_CONTROL_LOCKED |
+               FEATURE_CONTROL_VMXON_ENABLED))
                /* enable and lock */
                wrmsrl(MSR_IA32_FEATURE_CONTROL, old |
-                      IA32_FEATURE_CONTROL_LOCKED_BIT |
-                      IA32_FEATURE_CONTROL_VMXON_ENABLED_BIT);
+                      FEATURE_CONTROL_LOCKED |
+                      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)
@@ -1065,13 +1093,22 @@ static void vmclear_local_vcpus(void)
                __vcpu_clear(vmx);
 }
 
-static void hardware_disable(void *garbage)
+
+/* Just like cpu_vmxoff(), but with the __kvm_handle_fault_on_reboot()
+ * tricks.
+ */
+static void kvm_cpu_vmxoff(void)
 {
-       vmclear_local_vcpus();
        asm volatile (__ex(ASM_VMX_VMXOFF) : : : "cc");
        write_cr4(read_cr4() & ~X86_CR4_VMXE);
 }
 
+static void hardware_disable(void *garbage)
+{
+       vmclear_local_vcpus();
+       kvm_cpu_vmxoff();
+}
+
 static __init int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt,
                                      u32 msr, u32 *result)
 {
@@ -1116,7 +1153,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
              CPU_BASED_CR3_STORE_EXITING |
              CPU_BASED_USE_IO_BITMAPS |
              CPU_BASED_MOV_DR_EXITING |
-             CPU_BASED_USE_TSC_OFFSETING;
+             CPU_BASED_USE_TSC_OFFSETING |
+             CPU_BASED_INVLPG_EXITING;
        opt = CPU_BASED_TPR_SHADOW |
              CPU_BASED_USE_MSR_BITMAPS |
              CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
@@ -1145,9 +1183,11 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
                _cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW;
 #endif
        if (_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_EPT) {
-               /* CR3 accesses don't need to cause VM Exits when EPT enabled */
+               /* CR3 accesses and invlpg don't need to cause VM Exits when EPT
+                  enabled */
                min &= ~(CPU_BASED_CR3_LOAD_EXITING |
-                        CPU_BASED_CR3_STORE_EXITING);
+                        CPU_BASED_CR3_STORE_EXITING |
+                        CPU_BASED_INVLPG_EXITING);
                if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
                                        &_cpu_based_exec_control) < 0)
                        return -EIO;
@@ -1159,12 +1199,13 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
 #ifdef CONFIG_X86_64
        min |= VM_EXIT_HOST_ADDR_SPACE_SIZE;
 #endif
-       opt = 0;
+       opt = VM_EXIT_SAVE_IA32_PAT | VM_EXIT_LOAD_IA32_PAT;
        if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS,
                                &_vmexit_control) < 0)
                return -EIO;
 
-       min = opt = 0;
+       min = 0;
+       opt = VM_ENTRY_LOAD_IA32_PAT;
        if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,
                                &_vmentry_control) < 0)
                return -EIO;
@@ -1257,6 +1298,18 @@ static __init int hardware_setup(void)
        if (boot_cpu_has(X86_FEATURE_NX))
                kvm_enable_efer_bits(EFER_NX);
 
+       if (!cpu_has_vmx_vpid())
+               enable_vpid = 0;
+
+       if (!cpu_has_vmx_ept())
+               enable_ept = 0;
+
+       if (!cpu_has_vmx_flexpriority())
+               flexpriority_enabled = 0;
+
+       if (!cpu_has_vmx_tpr_shadow())
+               kvm_x86_ops->update_cr8_intercept = NULL;
+
        return alloc_kvm_area();
 }
 
@@ -1284,7 +1337,9 @@ static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save)
 static void enter_pmode(struct kvm_vcpu *vcpu)
 {
        unsigned long flags;
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
 
+       vmx->emulation_required = 1;
        vcpu->arch.rmode.active = 0;
 
        vmcs_writel(GUEST_TR_BASE, vcpu->arch.rmode.tr.base);
@@ -1301,6 +1356,9 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
 
        update_exception_bitmap(vcpu);
 
+       if (emulate_invalid_guest_state)
+               return;
+
        fix_pmode_dataseg(VCPU_SREG_ES, &vcpu->arch.rmode.es);
        fix_pmode_dataseg(VCPU_SREG_DS, &vcpu->arch.rmode.ds);
        fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->arch.rmode.gs);
@@ -1341,7 +1399,9 @@ static void fix_rmode_seg(int seg, struct kvm_save_segment *save)
 static void enter_rmode(struct kvm_vcpu *vcpu)
 {
        unsigned long flags;
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
 
+       vmx->emulation_required = 1;
        vcpu->arch.rmode.active = 1;
 
        vcpu->arch.rmode.tr.base = vmcs_readl(GUEST_TR_BASE);
@@ -1363,6 +1423,9 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
        vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | X86_CR4_VME);
        update_exception_bitmap(vcpu);
 
+       if (emulate_invalid_guest_state)
+               goto continue_rmode;
+
        vmcs_write16(GUEST_SS_SELECTOR, vmcs_readl(GUEST_SS_BASE) >> 4);
        vmcs_write32(GUEST_SS_LIMIT, 0xffff);
        vmcs_write32(GUEST_SS_AR_BYTES, 0xf3);
@@ -1378,10 +1441,34 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
        fix_rmode_seg(VCPU_SREG_GS, &vcpu->arch.rmode.gs);
        fix_rmode_seg(VCPU_SREG_FS, &vcpu->arch.rmode.fs);
 
+continue_rmode:
        kvm_mmu_reset_context(vcpu);
        init_rmode(vcpu->kvm);
 }
 
+static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
+{
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       struct kvm_msr_entry *msr = find_msr_entry(vmx, MSR_EFER);
+
+       vcpu->arch.shadow_efer = efer;
+       if (!msr)
+               return;
+       if (efer & EFER_LMA) {
+               vmcs_write32(VM_ENTRY_CONTROLS,
+                            vmcs_read32(VM_ENTRY_CONTROLS) |
+                            VM_ENTRY_IA32E_MODE);
+               msr->data = efer;
+       } else {
+               vmcs_write32(VM_ENTRY_CONTROLS,
+                            vmcs_read32(VM_ENTRY_CONTROLS) &
+                            ~VM_ENTRY_IA32E_MODE);
+
+               msr->data = efer & ~EFER_LME;
+       }
+       setup_msrs(vmx);
+}
+
 #ifdef CONFIG_X86_64
 
 static void enter_lmode(struct kvm_vcpu *vcpu)
@@ -1396,13 +1483,8 @@ static void enter_lmode(struct kvm_vcpu *vcpu)
                             (guest_tr_ar & ~AR_TYPE_MASK)
                             | AR_TYPE_BUSY_64_TSS);
        }
-
        vcpu->arch.shadow_efer |= EFER_LMA;
-
-       find_msr_entry(to_vmx(vcpu), MSR_EFER)->data |= EFER_LMA | EFER_LME;
-       vmcs_write32(VM_ENTRY_CONTROLS,
-                    vmcs_read32(VM_ENTRY_CONTROLS)
-                    | VM_ENTRY_IA32E_MODE);
+       vmx_set_efer(vcpu, vcpu->arch.shadow_efer);
 }
 
 static void exit_lmode(struct kvm_vcpu *vcpu)
@@ -1419,7 +1501,7 @@ static void exit_lmode(struct kvm_vcpu *vcpu)
 static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
 {
        vpid_sync_vcpu_all(to_vmx(vcpu));
-       if (vm_need_ept())
+       if (enable_ept)
                ept_sync_context(construct_eptp(vcpu->arch.mmu.root_hpa));
 }
 
@@ -1504,7 +1586,7 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
        }
 #endif
 
-       if (vm_need_ept())
+       if (enable_ept)
                ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu);
 
        vmcs_writel(CR0_READ_SHADOW, cr0);
@@ -1533,7 +1615,7 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
        u64 eptp;
 
        guest_cr3 = cr3;
-       if (vm_need_ept()) {
+       if (enable_ept) {
                eptp = construct_eptp(cr3);
                vmcs_write64(EPT_POINTER, eptp);
                ept_sync_context(eptp);
@@ -1554,37 +1636,13 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
                    KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
 
        vcpu->arch.cr4 = cr4;
-       if (vm_need_ept())
+       if (enable_ept)
                ept_update_paging_mode_cr4(&hw_cr4, vcpu);
 
        vmcs_writel(CR4_READ_SHADOW, cr4);
        vmcs_writel(GUEST_CR4, hw_cr4);
 }
 
-static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
-{
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
-       struct kvm_msr_entry *msr = find_msr_entry(vmx, MSR_EFER);
-
-       vcpu->arch.shadow_efer = efer;
-       if (!msr)
-               return;
-       if (efer & EFER_LMA) {
-               vmcs_write32(VM_ENTRY_CONTROLS,
-                                    vmcs_read32(VM_ENTRY_CONTROLS) |
-                                    VM_ENTRY_IA32E_MODE);
-               msr->data = efer;
-
-       } else {
-               vmcs_write32(VM_ENTRY_CONTROLS,
-                                    vmcs_read32(VM_ENTRY_CONTROLS) &
-                                    ~VM_ENTRY_IA32E_MODE);
-
-               msr->data = efer & ~EFER_LME;
-       }
-       setup_msrs(vmx);
-}
-
 static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
 {
        struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
@@ -1602,7 +1660,7 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu,
        var->limit = vmcs_read32(sf->limit);
        var->selector = vmcs_read16(sf->selector);
        ar = vmcs_read32(sf->ar_bytes);
-       if (ar & AR_UNUSABLE_MASK)
+       if ((ar & AR_UNUSABLE_MASK) && !emulate_invalid_guest_state)
                ar = 0;
        var->type = ar & 15;
        var->s = (ar >> 4) & 1;
@@ -1711,6 +1769,196 @@ static void vmx_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
        vmcs_writel(GUEST_GDTR_BASE, dt->base);
 }
 
+static bool rmode_segment_valid(struct kvm_vcpu *vcpu, int seg)
+{
+       struct kvm_segment var;
+       u32 ar;
+
+       vmx_get_segment(vcpu, &var, seg);
+       ar = vmx_segment_access_rights(&var);
+
+       if (var.base != (var.selector << 4))
+               return false;
+       if (var.limit != 0xffff)
+               return false;
+       if (ar != 0xf3)
+               return false;
+
+       return true;
+}
+
+static bool code_segment_valid(struct kvm_vcpu *vcpu)
+{
+       struct kvm_segment cs;
+       unsigned int cs_rpl;
+
+       vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
+       cs_rpl = cs.selector & SELECTOR_RPL_MASK;
+
+       if (cs.unusable)
+               return false;
+       if (~cs.type & (AR_TYPE_CODE_MASK|AR_TYPE_ACCESSES_MASK))
+               return false;
+       if (!cs.s)
+               return false;
+       if (cs.type & AR_TYPE_WRITEABLE_MASK) {
+               if (cs.dpl > cs_rpl)
+                       return false;
+       } else {
+               if (cs.dpl != cs_rpl)
+                       return false;
+       }
+       if (!cs.present)
+               return false;
+
+       /* TODO: Add Reserved field check, this'll require a new member in the kvm_segment_field structure */
+       return true;
+}
+
+static bool stack_segment_valid(struct kvm_vcpu *vcpu)
+{
+       struct kvm_segment ss;
+       unsigned int ss_rpl;
+
+       vmx_get_segment(vcpu, &ss, VCPU_SREG_SS);
+       ss_rpl = ss.selector & SELECTOR_RPL_MASK;
+
+       if (ss.unusable)
+               return true;
+       if (ss.type != 3 && ss.type != 7)
+               return false;
+       if (!ss.s)
+               return false;
+       if (ss.dpl != ss_rpl) /* DPL != RPL */
+               return false;
+       if (!ss.present)
+               return false;
+
+       return true;
+}
+
+static bool data_segment_valid(struct kvm_vcpu *vcpu, int seg)
+{
+       struct kvm_segment var;
+       unsigned int rpl;
+
+       vmx_get_segment(vcpu, &var, seg);
+       rpl = var.selector & SELECTOR_RPL_MASK;
+
+       if (var.unusable)
+               return true;
+       if (!var.s)
+               return false;
+       if (!var.present)
+               return false;
+       if (~var.type & (AR_TYPE_CODE_MASK|AR_TYPE_WRITEABLE_MASK)) {
+               if (var.dpl < rpl) /* DPL < RPL */
+                       return false;
+       }
+
+       /* TODO: Add other members to kvm_segment_field to allow checking for other access
+        * rights flags
+        */
+       return true;
+}
+
+static bool tr_valid(struct kvm_vcpu *vcpu)
+{
+       struct kvm_segment tr;
+
+       vmx_get_segment(vcpu, &tr, VCPU_SREG_TR);
+
+       if (tr.unusable)
+               return false;
+       if (tr.selector & SELECTOR_TI_MASK)     /* TI = 1 */
+               return false;
+       if (tr.type != 3 && tr.type != 11) /* TODO: Check if guest is in IA32e mode */
+               return false;
+       if (!tr.present)
+               return false;
+
+       return true;
+}
+
+static bool ldtr_valid(struct kvm_vcpu *vcpu)
+{
+       struct kvm_segment ldtr;
+
+       vmx_get_segment(vcpu, &ldtr, VCPU_SREG_LDTR);
+
+       if (ldtr.unusable)
+               return true;
+       if (ldtr.selector & SELECTOR_TI_MASK)   /* TI = 1 */
+               return false;
+       if (ldtr.type != 2)
+               return false;
+       if (!ldtr.present)
+               return false;
+
+       return true;
+}
+
+static bool cs_ss_rpl_check(struct kvm_vcpu *vcpu)
+{
+       struct kvm_segment cs, ss;
+
+       vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
+       vmx_get_segment(vcpu, &ss, VCPU_SREG_SS);
+
+       return ((cs.selector & SELECTOR_RPL_MASK) ==
+                (ss.selector & SELECTOR_RPL_MASK));
+}
+
+/*
+ * Check if guest state is valid. Returns true if valid, false if
+ * not.
+ * We assume that registers are always usable
+ */
+static bool guest_state_valid(struct kvm_vcpu *vcpu)
+{
+       /* real mode guest state checks */
+       if (!(vcpu->arch.cr0 & X86_CR0_PE)) {
+               if (!rmode_segment_valid(vcpu, VCPU_SREG_CS))
+                       return false;
+               if (!rmode_segment_valid(vcpu, VCPU_SREG_SS))
+                       return false;
+               if (!rmode_segment_valid(vcpu, VCPU_SREG_DS))
+                       return false;
+               if (!rmode_segment_valid(vcpu, VCPU_SREG_ES))
+                       return false;
+               if (!rmode_segment_valid(vcpu, VCPU_SREG_FS))
+                       return false;
+               if (!rmode_segment_valid(vcpu, VCPU_SREG_GS))
+                       return false;
+       } else {
+       /* protected mode guest state checks */
+               if (!cs_ss_rpl_check(vcpu))
+                       return false;
+               if (!code_segment_valid(vcpu))
+                       return false;
+               if (!stack_segment_valid(vcpu))
+                       return false;
+               if (!data_segment_valid(vcpu, VCPU_SREG_DS))
+                       return false;
+               if (!data_segment_valid(vcpu, VCPU_SREG_ES))
+                       return false;
+               if (!data_segment_valid(vcpu, VCPU_SREG_FS))
+                       return false;
+               if (!data_segment_valid(vcpu, VCPU_SREG_GS))
+                       return false;
+               if (!tr_valid(vcpu))
+                       return false;
+               if (!ldtr_valid(vcpu))
+                       return false;
+       }
+       /* TODO:
+        * - Add checks on RIP
+        * - Add checks on RFLAGS
+        */
+
+       return true;
+}
+
 static int init_rmode_tss(struct kvm *kvm)
 {
        gfn_t fn = rmode_tss_base(kvm) >> PAGE_SHIFT;
@@ -1722,7 +1970,8 @@ static int init_rmode_tss(struct kvm *kvm)
        if (r < 0)
                goto out;
        data = TSS_BASE_SIZE + TSS_REDIRECTION_SIZE;
-       r = kvm_write_guest_page(kvm, fn++, &data, 0x66, sizeof(u16));
+       r = kvm_write_guest_page(kvm, fn++, &data,
+                       TSS_IOPB_BASE_OFFSET, sizeof(u16));
        if (r < 0)
                goto out;
        r = kvm_clear_guest_page(kvm, fn++, 0, PAGE_SIZE);
@@ -1749,7 +1998,7 @@ static int init_rmode_identity_map(struct kvm *kvm)
        pfn_t identity_map_pfn;
        u32 tmp;
 
-       if (!vm_need_ept())
+       if (!enable_ept)
                return 1;
        if (unlikely(!kvm->arch.ept_identity_pagetable)) {
                printk(KERN_ERR "EPT: identity-mapping pagetable "
@@ -1785,7 +2034,7 @@ static void seg_setup(int seg)
        vmcs_write16(sf->selector, 0);
        vmcs_writel(sf->base, 0);
        vmcs_write32(sf->limit, 0xffff);
-       vmcs_write32(sf->ar_bytes, 0x93);
+       vmcs_write32(sf->ar_bytes, 0xf3);
 }
 
 static int alloc_apic_access_page(struct kvm *kvm)
@@ -1804,9 +2053,7 @@ static int alloc_apic_access_page(struct kvm *kvm)
        if (r)
                goto out;
 
-       down_read(&current->mm->mmap_sem);
        kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00);
-       up_read(&current->mm->mmap_sem);
 out:
        up_write(&kvm->slots_lock);
        return r;
@@ -1828,10 +2075,8 @@ static int alloc_identity_pagetable(struct kvm *kvm)
        if (r)
                goto out;
 
-       down_read(&current->mm->mmap_sem);
        kvm->arch.ept_identity_pagetable = gfn_to_page(kvm,
                        VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT);
-       up_read(&current->mm->mmap_sem);
 out:
        up_write(&kvm->slots_lock);
        return r;
@@ -1842,7 +2087,7 @@ static void allocate_vpid(struct vcpu_vmx *vmx)
        int vpid;
 
        vmx->vpid = 0;
-       if (!enable_vpid || !cpu_has_vmx_vpid())
+       if (!enable_vpid)
                return;
        spin_lock(&vmx_vpid_lock);
        vpid = find_first_zero_bit(vmx_vpid_bitmap, VMX_NR_VPIDS);
@@ -1853,9 +2098,9 @@ static void allocate_vpid(struct vcpu_vmx *vmx)
        spin_unlock(&vmx_vpid_lock);
 }
 
-static void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
+static void __vmx_disable_intercept_for_msr(unsigned long *msr_bitmap, u32 msr)
 {
-       void *va;
+       int f = sizeof(unsigned long);
 
        if (!cpu_has_vmx_msr_bitmap())
                return;
@@ -1865,16 +2110,21 @@ static void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
         * have the write-low and read-high bitmap offsets the wrong way round.
         * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
         */
-       va = kmap(msr_bitmap);
        if (msr <= 0x1fff) {
-               __clear_bit(msr, va + 0x000); /* read-low */
-               __clear_bit(msr, va + 0x800); /* write-low */
+               __clear_bit(msr, msr_bitmap + 0x000 / f); /* read-low */
+               __clear_bit(msr, msr_bitmap + 0x800 / f); /* write-low */
        } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
                msr &= 0x1fff;
-               __clear_bit(msr, va + 0x400); /* read-high */
-               __clear_bit(msr, va + 0xc00); /* write-high */
+               __clear_bit(msr, msr_bitmap + 0x400 / f); /* read-high */
+               __clear_bit(msr, msr_bitmap + 0xc00 / f); /* write-high */
        }
-       kunmap(msr_bitmap);
+}
+
+static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only)
+{
+       if (!longmode_only)
+               __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy, msr);
+       __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode, msr);
 }
 
 /*
@@ -1882,8 +2132,9 @@ static void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
  */
 static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
 {
-       u32 host_sysenter_cs;
+       u32 host_sysenter_cs, msr_low, msr_high;
        u32 junk;
+       u64 host_pat, tsc_this, tsc_base;
        unsigned long a;
        struct descriptor_table dt;
        int i;
@@ -1891,11 +2142,11 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
        u32 exec_control;
 
        /* I/O */
-       vmcs_write64(IO_BITMAP_A, page_to_phys(vmx_io_bitmap_a));
-       vmcs_write64(IO_BITMAP_B, page_to_phys(vmx_io_bitmap_b));
+       vmcs_write64(IO_BITMAP_A, __pa(vmx_io_bitmap_a));
+       vmcs_write64(IO_BITMAP_B, __pa(vmx_io_bitmap_b));
 
        if (cpu_has_vmx_msr_bitmap())
-               vmcs_write64(MSR_BITMAP, page_to_phys(vmx_msr_bitmap));
+               vmcs_write64(MSR_BITMAP, __pa(vmx_msr_bitmap_legacy));
 
        vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
 
@@ -1911,9 +2162,10 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
                                CPU_BASED_CR8_LOAD_EXITING;
 #endif
        }
-       if (!vm_need_ept())
+       if (!enable_ept)
                exec_control |= CPU_BASED_CR3_STORE_EXITING |
-                               CPU_BASED_CR3_LOAD_EXITING;
+                               CPU_BASED_CR3_LOAD_EXITING  |
+                               CPU_BASED_INVLPG_EXITING;
        vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
 
        if (cpu_has_secondary_exec_ctrls()) {
@@ -1923,7 +2175,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
                                ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
                if (vmx->vpid == 0)
                        exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
-               if (!vm_need_ept())
+               if (!enable_ept)
                        exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
        }
@@ -1970,6 +2222,20 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
        rdmsrl(MSR_IA32_SYSENTER_EIP, a);
        vmcs_writel(HOST_IA32_SYSENTER_EIP, a);   /* 22.2.3 */
 
+       if (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PAT) {
+               rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high);
+               host_pat = msr_low | ((u64) msr_high << 32);
+               vmcs_write64(HOST_IA32_PAT, host_pat);
+       }
+       if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
+               rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high);
+               host_pat = msr_low | ((u64) msr_high << 32);
+               /* Write the default value follow host pat */
+               vmcs_write64(GUEST_IA32_PAT, host_pat);
+               /* Keep arch.pat sync with GUEST_IA32_PAT */
+               vmx->vcpu.arch.pat = host_pat;
+       }
+
        for (i = 0; i < NR_VMX_MSR; ++i) {
                u32 index = vmx_msr_index[i];
                u32 data_low, data_high;
@@ -1996,6 +2262,12 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
        vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL);
        vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK);
 
+       tsc_base = vmx->vcpu.kvm->arch.vm_init_tsc;
+       rdtscll(tsc_this);
+       if (tsc_this < vmx->vcpu.kvm->arch.vm_init_tsc)
+               tsc_base = tsc_this;
+
+       guest_write_tsc(0, tsc_base);
 
        return 0;
 }
@@ -2024,6 +2296,8 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 
        vmx->vcpu.arch.rmode.active = 0;
 
+       vmx->soft_vnmi_blocked = 0;
+
        vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
        kvm_set_cr8(&vmx->vcpu, 0);
        msr = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
@@ -2033,6 +2307,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 
        fx_init(&vmx->vcpu);
 
+       seg_setup(VCPU_SREG_CS);
        /*
         * GUEST_CS_BASE should really be 0xffff0000, but VT vm86 mode
         * insists on having GUEST_CS_BASE == GUEST_CS_SELECTOR << 4.  Sigh.
@@ -2044,8 +2319,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
                vmcs_write16(GUEST_CS_SELECTOR, vmx->vcpu.arch.sipi_vector << 8);
                vmcs_writel(GUEST_CS_BASE, vmx->vcpu.arch.sipi_vector << 12);
        }
-       vmcs_write32(GUEST_CS_LIMIT, 0xffff);
-       vmcs_write32(GUEST_CS_AR_BYTES, 0x9b);
 
        seg_setup(VCPU_SREG_DS);
        seg_setup(VCPU_SREG_ES);
@@ -2074,7 +2347,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
                kvm_rip_write(vcpu, 0);
        kvm_register_write(vcpu, VCPU_REGS_RSP, 0);
 
-       /* todo: dr0 = dr1 = dr2 = dr3 = 0; dr6 = 0xffff0ff0 */
        vmcs_writel(GUEST_DR7, 0x400);
 
        vmcs_writel(GUEST_GDTR_BASE, 0);
@@ -2087,8 +2359,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
        vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0);
        vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0);
 
-       guest_write_tsc(0);
-
        /* Special registers */
        vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
 
@@ -2122,17 +2392,50 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 
        ret = 0;
 
+       /* HACK: Don't enable emulation on guest boot/reset */
+       vmx->emulation_required = 0;
+
 out:
        up_read(&vcpu->kvm->slots_lock);
        return ret;
 }
 
+void vmx_drop_interrupt_shadow(struct kvm_vcpu *vcpu)
+{
+       vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
+                       GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS);
+}
+
+static void enable_irq_window(struct kvm_vcpu *vcpu)
+{
+       u32 cpu_based_vm_exec_control;
+
+       cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
+       cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
+       vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
+}
+
+static void enable_nmi_window(struct kvm_vcpu *vcpu)
+{
+       u32 cpu_based_vm_exec_control;
+
+       if (!cpu_has_virtual_nmis()) {
+               enable_irq_window(vcpu);
+               return;
+       }
+
+       cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
+       cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_NMI_PENDING;
+       vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
+}
+
 static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
 
        KVMTRACE_1D(INJ_VIRQ, vcpu, (u32)irq, handler);
 
+       ++vcpu->stat.irq_injections;
        if (vcpu->arch.rmode.active) {
                vmx->rmode.irq.pending = true;
                vmx->rmode.irq.vector = irq;
@@ -2149,58 +2452,59 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq)
 
 static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
 {
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+       if (!cpu_has_virtual_nmis()) {
+               /*
+                * Tracking the NMI-blocked state in software is built upon
+                * finding the next open IRQ window. This, in turn, depends on
+                * well-behaving guests: They have to keep IRQs disabled at
+                * least as long as the NMI handler runs. Otherwise we may
+                * cause NMI nesting, maybe breaking the guest. But as this is
+                * highly unlikely, we can live with the residual risk.
+                */
+               vmx->soft_vnmi_blocked = 1;
+               vmx->vnmi_blocked_time = 0;
+       }
+
+       ++vcpu->stat.nmi_injections;
+       if (vcpu->arch.rmode.active) {
+               vmx->rmode.irq.pending = true;
+               vmx->rmode.irq.vector = NMI_VECTOR;
+               vmx->rmode.irq.rip = kvm_rip_read(vcpu);
+               vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+                            NMI_VECTOR | INTR_TYPE_SOFT_INTR |
+                            INTR_INFO_VALID_MASK);
+               vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
+               kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1);
+               return;
+       }
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
                        INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
-       vcpu->arch.nmi_pending = 0;
 }
 
-static void kvm_do_inject_irq(struct kvm_vcpu *vcpu)
+static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
 {
-       int word_index = __ffs(vcpu->arch.irq_summary);
-       int bit_index = __ffs(vcpu->arch.irq_pending[word_index]);
-       int irq = word_index * BITS_PER_LONG + bit_index;
+       if (!cpu_has_virtual_nmis() && to_vmx(vcpu)->soft_vnmi_blocked)
+               return 0;
 
-       clear_bit(bit_index, &vcpu->arch.irq_pending[word_index]);
-       if (!vcpu->arch.irq_pending[word_index])
-               clear_bit(word_index, &vcpu->arch.irq_summary);
-       vmx_inject_irq(vcpu, irq);
+       return  !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
+                       (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS |
+                               GUEST_INTR_STATE_NMI));
 }
 
-
-static void do_interrupt_requests(struct kvm_vcpu *vcpu,
-                                      struct kvm_run *kvm_run)
+static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
 {
-       u32 cpu_based_vm_exec_control;
-
-       vcpu->arch.interrupt_window_open =
-               ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
-                (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0);
-
-       if (vcpu->arch.interrupt_window_open &&
-           vcpu->arch.irq_summary &&
-           !(vmcs_read32(VM_ENTRY_INTR_INFO_FIELD) & INTR_INFO_VALID_MASK))
-               /*
-                * If interrupts enabled, and not blocked by sti or mov ss. Good.
-                */
-               kvm_do_inject_irq(vcpu);
-
-       cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
-       if (!vcpu->arch.interrupt_window_open &&
-           (vcpu->arch.irq_summary || kvm_run->request_interrupt_window))
-               /*
-                * Interrupts blocked.  Wait for unblock.
-                */
-               cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
-       else
-               cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
-       vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
+       return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
+               !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
+                       (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS));
 }
 
 static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
 {
        int ret;
        struct kvm_userspace_memory_region tss_mem = {
-               .slot = 8,
+               .slot = TSS_PRIVATE_MEMSLOT,
                .guest_phys_addr = addr,
                .memory_size = PAGE_SIZE * 3,
                .flags = 0,
@@ -2213,30 +2517,9 @@ static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
        return 0;
 }
 
-static void kvm_guest_debug_pre(struct kvm_vcpu *vcpu)
-{
-       struct kvm_guest_debug *dbg = &vcpu->guest_debug;
-
-       set_debugreg(dbg->bp[0], 0);
-       set_debugreg(dbg->bp[1], 1);
-       set_debugreg(dbg->bp[2], 2);
-       set_debugreg(dbg->bp[3], 3);
-
-       if (dbg->singlestep) {
-               unsigned long flags;
-
-               flags = vmcs_readl(GUEST_RFLAGS);
-               flags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
-               vmcs_writel(GUEST_RFLAGS, flags);
-       }
-}
-
 static int handle_rmode_exception(struct kvm_vcpu *vcpu,
                                  int vec, u32 err_code)
 {
-       if (!vcpu->arch.rmode.active)
-               return 0;
-
        /*
         * Instruction with address size override prefix opcode 0x67
         * Cause the #SS fault with 0 error code in VM86 mode.
@@ -2244,14 +2527,41 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
        if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0)
                if (emulate_instruction(vcpu, NULL, 0, 0, 0) == EMULATE_DONE)
                        return 1;
+       /*
+        * Forward all other exceptions that are valid in real mode.
+        * FIXME: Breaks guest debugging in real mode, needs to be fixed with
+        *        the required debugging infrastructure rework.
+        */
+       switch (vec) {
+       case DB_VECTOR:
+               if (vcpu->guest_debug &
+                   (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
+                       return 0;
+               kvm_queue_exception(vcpu, vec);
+               return 1;
+       case BP_VECTOR:
+               if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
+                       return 0;
+               /* fall through */
+       case DE_VECTOR:
+       case OF_VECTOR:
+       case BR_VECTOR:
+       case UD_VECTOR:
+       case DF_VECTOR:
+       case SS_VECTOR:
+       case GP_VECTOR:
+       case MF_VECTOR:
+               kvm_queue_exception(vcpu, vec);
+               return 1;
+       }
        return 0;
 }
 
 static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
-       u32 intr_info, error_code;
-       unsigned long cr2, rip;
+       u32 intr_info, ex_no, error_code;
+       unsigned long cr2, rip, dr6;
        u32 vect_info;
        enum emulation_result er;
 
@@ -2263,13 +2573,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                printk(KERN_ERR "%s: unexpected, vectoring info 0x%x "
                       "intr info 0x%x\n", __func__, vect_info, intr_info);
 
-       if (!irqchip_in_kernel(vcpu->kvm) && is_external_interrupt(vect_info)) {
-               int irq = vect_info & VECTORING_INFO_VECTOR_MASK;
-               set_bit(irq, vcpu->arch.irq_pending);
-               set_bit(irq / BITS_PER_LONG, &vcpu->arch.irq_summary);
-       }
-
-       if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) /* nmi */
+       if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR)
                return 1;  /* already handled by vmx_vcpu_run() */
 
        if (is_no_device(intr_info)) {
@@ -2290,12 +2594,12 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
        if (is_page_fault(intr_info)) {
                /* EPT won't cause page fault directly */
-               if (vm_need_ept())
+               if (enable_ept)
                        BUG();
                cr2 = vmcs_readl(EXIT_QUALIFICATION);
                KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2,
                            (u32)((u64)cr2 >> 32), handler);
-               if (vect_info & VECTORING_INFO_VALID_MASK)
+               if (vcpu->arch.interrupt.pending || vcpu->arch.exception.pending)
                        kvm_mmu_unprotect_page_virt(vcpu, cr2);
                return kvm_mmu_page_fault(vcpu, cr2, error_code);
        }
@@ -2310,14 +2614,30 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                return 1;
        }
 
-       if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) ==
-           (INTR_TYPE_EXCEPTION | 1)) {
+       ex_no = intr_info & INTR_INFO_VECTOR_MASK;
+       switch (ex_no) {
+       case DB_VECTOR:
+               dr6 = vmcs_readl(EXIT_QUALIFICATION);
+               if (!(vcpu->guest_debug &
+                     (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
+                       vcpu->arch.dr6 = dr6 | DR6_FIXED_1;
+                       kvm_queue_exception(vcpu, DB_VECTOR);
+                       return 1;
+               }
+               kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1;
+               kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7);
+               /* fall through */
+       case BP_VECTOR:
                kvm_run->exit_reason = KVM_EXIT_DEBUG;
-               return 0;
+               kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip;
+               kvm_run->debug.arch.exception = ex_no;
+               break;
+       default:
+               kvm_run->exit_reason = KVM_EXIT_EXCEPTION;
+               kvm_run->ex.exception = ex_no;
+               kvm_run->ex.error_code = error_code;
+               break;
        }
-       kvm_run->exit_reason = KVM_EXIT_EXCEPTION;
-       kvm_run->ex.exception = intr_info & INTR_INFO_VECTOR_MASK;
-       kvm_run->ex.error_code = error_code;
        return 0;
 }
 
@@ -2338,7 +2658,7 @@ static int handle_triple_fault(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        unsigned long exit_qualification;
-       int size, down, in, string, rep;
+       int size, in, string;
        unsigned port;
 
        ++vcpu->stat.io_exits;
@@ -2354,10 +2674,9 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
        size = (exit_qualification & 7) + 1;
        in = (exit_qualification & 8) != 0;
-       down = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0;
-       rep = (exit_qualification & 32) != 0;
        port = exit_qualification >> 16;
 
+       skip_emulated_instruction(vcpu);
        return kvm_emulate_pio(vcpu, kvm_run, in, size, port);
 }
 
@@ -2400,13 +2719,18 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                        kvm_set_cr4(vcpu, kvm_register_read(vcpu, reg));
                        skip_emulated_instruction(vcpu);
                        return 1;
-               case 8:
-                       kvm_set_cr8(vcpu, kvm_register_read(vcpu, reg));
-                       skip_emulated_instruction(vcpu);
-                       if (irqchip_in_kernel(vcpu->kvm))
-                               return 1;
-                       kvm_run->exit_reason = KVM_EXIT_SET_TPR;
-                       return 0;
+               case 8: {
+                               u8 cr8_prev = kvm_get_cr8(vcpu);
+                               u8 cr8 = kvm_register_read(vcpu, reg);
+                               kvm_set_cr8(vcpu, cr8);
+                               skip_emulated_instruction(vcpu);
+                               if (irqchip_in_kernel(vcpu->kvm))
+                                       return 1;
+                               if (cr8_prev <= cr8)
+                                       return 1;
+                               kvm_run->exit_reason = KVM_EXIT_SET_TPR;
+                               return 0;
+                       }
                };
                break;
        case 2: /* clts */
@@ -2455,21 +2779,44 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        unsigned long val;
        int dr, reg;
 
-       /*
-        * FIXME: this code assumes the host is debugging the guest.
-        *        need to deal with guest debugging itself too.
-        */
+       dr = vmcs_readl(GUEST_DR7);
+       if (dr & DR7_GD) {
+               /*
+                * As the vm-exit takes precedence over the debug trap, we
+                * need to emulate the latter, either for the host or the
+                * guest debugging itself.
+                */
+               if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) {
+                       kvm_run->debug.arch.dr6 = vcpu->arch.dr6;
+                       kvm_run->debug.arch.dr7 = dr;
+                       kvm_run->debug.arch.pc =
+                               vmcs_readl(GUEST_CS_BASE) +
+                               vmcs_readl(GUEST_RIP);
+                       kvm_run->debug.arch.exception = DB_VECTOR;
+                       kvm_run->exit_reason = KVM_EXIT_DEBUG;
+                       return 0;
+               } else {
+                       vcpu->arch.dr7 &= ~DR7_GD;
+                       vcpu->arch.dr6 |= DR6_BD;
+                       vmcs_writel(GUEST_DR7, vcpu->arch.dr7);
+                       kvm_queue_exception(vcpu, DB_VECTOR);
+                       return 1;
+               }
+       }
+
        exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-       dr = exit_qualification & 7;
-       reg = (exit_qualification >> 8) & 15;
-       if (exit_qualification & 16) {
-               /* mov from dr */
+       dr = exit_qualification & DEBUG_REG_ACCESS_NUM;
+       reg = DEBUG_REG_ACCESS_REG(exit_qualification);
+       if (exit_qualification & TYPE_MOV_FROM_DR) {
                switch (dr) {
+               case 0 ... 3:
+                       val = vcpu->arch.db[dr];
+                       break;
                case 6:
-                       val = 0xffff0ff0;
+                       val = vcpu->arch.dr6;
                        break;
                case 7:
-                       val = 0x400;
+                       val = vcpu->arch.dr7;
                        break;
                default:
                        val = 0;
@@ -2477,7 +2824,38 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                kvm_register_write(vcpu, reg, val);
                KVMTRACE_2D(DR_READ, vcpu, (u32)dr, (u32)val, handler);
        } else {
-               /* mov to dr */
+               val = vcpu->arch.regs[reg];
+               switch (dr) {
+               case 0 ... 3:
+                       vcpu->arch.db[dr] = val;
+                       if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP))
+                               vcpu->arch.eff_db[dr] = val;
+                       break;
+               case 4 ... 5:
+                       if (vcpu->arch.cr4 & X86_CR4_DE)
+                               kvm_queue_exception(vcpu, UD_VECTOR);
+                       break;
+               case 6:
+                       if (val & 0xffffffff00000000ULL) {
+                               kvm_queue_exception(vcpu, GP_VECTOR);
+                               break;
+                       }
+                       vcpu->arch.dr6 = (val & DR6_VOLATILE) | DR6_FIXED_1;
+                       break;
+               case 7:
+                       if (val & 0xffffffff00000000ULL) {
+                               kvm_queue_exception(vcpu, GP_VECTOR);
+                               break;
+                       }
+                       vcpu->arch.dr7 = (val & DR7_VOLATILE) | DR7_FIXED_1;
+                       if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) {
+                               vmcs_writel(GUEST_DR7, vcpu->arch.dr7);
+                               vcpu->arch.switch_db_regs =
+                                       (val & DR7_BP_EN_MASK);
+                       }
+                       break;
+               }
+               KVMTRACE_2D(DR_WRITE, vcpu, (u32)dr, (u32)val, handler);
        }
        skip_emulated_instruction(vcpu);
        return 1;
@@ -2544,15 +2922,16 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu,
        vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
 
        KVMTRACE_0D(PEND_INTR, vcpu, handler);
+       ++vcpu->stat.irq_window_exits;
 
        /*
         * If the user space waits to inject interrupts, exit as soon as
         * possible
         */
-       if (kvm_run->request_interrupt_window &&
-           !vcpu->arch.irq_summary) {
+       if (!irqchip_in_kernel(vcpu->kvm) &&
+           kvm_run->request_interrupt_window &&
+           !kvm_cpu_has_interrupt(vcpu)) {
                kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
-               ++vcpu->stat.irq_window_exits;
                return 0;
        }
        return 1;
@@ -2571,6 +2950,15 @@ static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        return 1;
 }
 
+static int handle_invlpg(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+       kvm_mmu_invlpg(vcpu, exit_qualification);
+       skip_emulated_instruction(vcpu);
+       return 1;
+}
+
 static int handle_wbinvd(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        skip_emulated_instruction(vcpu);
@@ -2580,11 +2968,11 @@ static int handle_wbinvd(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
 static int handle_apic_access(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-       u64 exit_qualification;
+       unsigned long exit_qualification;
        enum emulation_result er;
        unsigned long offset;
 
-       exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
        offset = exit_qualification & 0xffful;
 
        er = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
@@ -2600,28 +2988,64 @@ static int handle_apic_access(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
 static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
        unsigned long exit_qualification;
        u16 tss_selector;
-       int reason;
+       int reason, type, idt_v;
+
+       idt_v = (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+       type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
 
        exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 
        reason = (u32)exit_qualification >> 30;
+       if (reason == TASK_SWITCH_GATE && idt_v) {
+               switch (type) {
+               case INTR_TYPE_NMI_INTR:
+                       vcpu->arch.nmi_injected = false;
+                       if (cpu_has_virtual_nmis())
+                               vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+                                             GUEST_INTR_STATE_NMI);
+                       break;
+               case INTR_TYPE_EXT_INTR:
+                       kvm_clear_interrupt_queue(vcpu);
+                       break;
+               case INTR_TYPE_HARD_EXCEPTION:
+               case INTR_TYPE_SOFT_EXCEPTION:
+                       kvm_clear_exception_queue(vcpu);
+                       break;
+               default:
+                       break;
+               }
+       }
        tss_selector = exit_qualification;
 
-       return kvm_task_switch(vcpu, tss_selector, reason);
+       if (!idt_v || (type != INTR_TYPE_HARD_EXCEPTION &&
+                      type != INTR_TYPE_EXT_INTR &&
+                      type != INTR_TYPE_NMI_INTR))
+               skip_emulated_instruction(vcpu);
+
+       if (!kvm_task_switch(vcpu, tss_selector, reason))
+               return 0;
+
+       /* clear all local breakpoint enable flags */
+       vmcs_writel(GUEST_DR7, vmcs_readl(GUEST_DR7) & ~55);
+
+       /*
+        * TODO: What about debug traps on tss switch?
+        *       Are we supposed to inject them and update dr6?
+        */
+
+       return 1;
 }
 
 static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-       u64 exit_qualification;
-       enum emulation_result er;
+       unsigned long exit_qualification;
        gpa_t gpa;
-       unsigned long hva;
        int gla_validity;
-       int r;
 
-       exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 
        if (exit_qualification & (1 << 6)) {
                printk(KERN_ERR "EPT: GPA exceeds GAW!\n");
@@ -2633,7 +3057,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                printk(KERN_ERR "EPT: Handling EPT violation failed!\n");
                printk(KERN_ERR "EPT: GPA: 0x%lx, GVA: 0x%lx\n",
                        (long unsigned int)vmcs_read64(GUEST_PHYSICAL_ADDRESS),
-                       (long unsigned int)vmcs_read64(GUEST_LINEAR_ADDRESS));
+                       vmcs_readl(GUEST_LINEAR_ADDRESS));
                printk(KERN_ERR "EPT: Exit qualification is 0x%lx\n",
                        (long unsigned int)exit_qualification);
                kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
@@ -2642,32 +3066,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        }
 
        gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
-       hva = gfn_to_hva(vcpu->kvm, gpa >> PAGE_SHIFT);
-       if (!kvm_is_error_hva(hva)) {
-               r = kvm_mmu_page_fault(vcpu, gpa & PAGE_MASK, 0);
-               if (r < 0) {
-                       printk(KERN_ERR "EPT: Not enough memory!\n");
-                       return -ENOMEM;
-               }
-               return 1;
-       } else {
-               /* must be MMIO */
-               er = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
-
-               if (er == EMULATE_FAIL) {
-                       printk(KERN_ERR
-                        "EPT: Fail to handle EPT violation vmexit!er is %d\n",
-                        er);
-                       printk(KERN_ERR "EPT: GPA: 0x%lx, GVA: 0x%lx\n",
-                        (long unsigned int)vmcs_read64(GUEST_PHYSICAL_ADDRESS),
-                        (long unsigned int)vmcs_read64(GUEST_LINEAR_ADDRESS));
-                       printk(KERN_ERR "EPT: Exit qualification is 0x%lx\n",
-                               (long unsigned int)exit_qualification);
-                       return -ENOTSUPP;
-               } else if (er == EMULATE_DO_MMIO)
-                       return 0;
-       }
-       return 1;
+       return kvm_mmu_page_fault(vcpu, gpa & PAGE_MASK, 0);
 }
 
 static int handle_nmi_window(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -2683,6 +3082,38 @@ static int handle_nmi_window(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        return 1;
 }
 
+static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
+                               struct kvm_run *kvm_run)
+{
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       enum emulation_result err = EMULATE_DONE;
+
+       preempt_enable();
+       local_irq_enable();
+
+       while (!guest_state_valid(vcpu)) {
+               err = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
+
+               if (err == EMULATE_DO_MMIO)
+                       break;
+
+               if (err != EMULATE_DONE) {
+                       kvm_report_emulation_failure(vcpu, "emulation failure");
+                       return;
+               }
+
+               if (signal_pending(current))
+                       break;
+               if (need_resched())
+                       schedule();
+       }
+
+       local_irq_disable();
+       preempt_disable();
+
+       vmx->invalid_state_emulation_result = err;
+}
+
 /*
  * The exit handlers return 1 if the exit was handled fully and guest execution
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
@@ -2702,6 +3133,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu,
        [EXIT_REASON_MSR_WRITE]               = handle_wrmsr,
        [EXIT_REASON_PENDING_INTERRUPT]       = handle_interrupt_window,
        [EXIT_REASON_HLT]                     = handle_halt,
+       [EXIT_REASON_INVLPG]                  = handle_invlpg,
        [EXIT_REASON_VMCALL]                  = handle_vmcall,
        [EXIT_REASON_TPR_BELOW_THRESHOLD]     = handle_tpr_below_threshold,
        [EXIT_REASON_APIC_ACCESS]             = handle_apic_access,
@@ -2717,7 +3149,7 @@ static const int kvm_vmx_max_exit_handlers =
  * The guest has exited.  See if we can fix it or if we need userspace
  * assistance.
  */
-static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+static int vmx_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
        u32 exit_reason = vmcs_read32(VM_EXIT_REASON);
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -2726,9 +3158,17 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        KVMTRACE_3D(VMEXIT, vcpu, exit_reason, (u32)kvm_rip_read(vcpu),
                    (u32)((u64)kvm_rip_read(vcpu) >> 32), entryexit);
 
+       /* If we need to emulate an MMIO from handle_invalid_guest_state
+        * we just return 0 */
+       if (vmx->emulation_required && emulate_invalid_guest_state) {
+               if (guest_state_valid(vcpu))
+                       vmx->emulation_required = 0;
+               return vmx->invalid_state_emulation_result != EMULATE_DO_MMIO;
+       }
+
        /* Access CR3 don't cause VMExit in paging mode, so we need
         * to sync with guest real CR3. */
-       if (vm_need_ept() && is_paging(vcpu)) {
+       if (enable_ept && is_paging(vcpu)) {
                vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
                ept_load_pdptrs(vcpu);
        }
@@ -2742,9 +3182,30 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 
        if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
                        (exit_reason != EXIT_REASON_EXCEPTION_NMI &&
-                       exit_reason != EXIT_REASON_EPT_VIOLATION))
-               printk(KERN_WARNING "%s: unexpected, valid vectoring info and "
-                      "exit reason is 0x%x\n", __func__, exit_reason);
+                       exit_reason != EXIT_REASON_EPT_VIOLATION &&
+                       exit_reason != EXIT_REASON_TASK_SWITCH))
+               printk(KERN_WARNING "%s: unexpected, valid vectoring info "
+                      "(0x%x) and exit reason is 0x%x\n",
+                      __func__, vectoring_info, exit_reason);
+
+       if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked)) {
+               if (vmx_interrupt_allowed(vcpu)) {
+                       vmx->soft_vnmi_blocked = 0;
+               } else if (vmx->vnmi_blocked_time > 1000000000LL &&
+                          vcpu->arch.nmi_pending) {
+                       /*
+                        * This CPU don't support us in finding the end of an
+                        * NMI-blocked window if the guest runs with IRQs
+                        * disabled. So we pull the trigger after 1 s of
+                        * futile waiting, but inform the user about this.
+                        */
+                       printk(KERN_WARNING "%s: Breaking out of NMI-blocked "
+                              "state on VCPU %d after 1 s timeout\n",
+                              __func__, vcpu->vcpu_id);
+                       vmx->soft_vnmi_blocked = 0;
+               }
+       }
+
        if (exit_reason < kvm_vmx_max_exit_handlers
            && kvm_vmx_exit_handlers[exit_reason])
                return kvm_vmx_exit_handlers[exit_reason](vcpu, kvm_run);
@@ -2755,160 +3216,83 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        return 0;
 }
 
-static void update_tpr_threshold(struct kvm_vcpu *vcpu)
+static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
 {
-       int max_irr, tpr;
-
-       if (!vm_need_tpr_shadow(vcpu->kvm))
-               return;
-
-       if (!kvm_lapic_enabled(vcpu) ||
-           ((max_irr = kvm_lapic_find_highest_irr(vcpu)) == -1)) {
+       if (irr == -1 || tpr < irr) {
                vmcs_write32(TPR_THRESHOLD, 0);
                return;
        }
 
-       tpr = (kvm_lapic_get_cr8(vcpu) & 0x0f) << 4;
-       vmcs_write32(TPR_THRESHOLD, (max_irr > tpr) ? tpr >> 4 : max_irr >> 4);
-}
-
-static void enable_irq_window(struct kvm_vcpu *vcpu)
-{
-       u32 cpu_based_vm_exec_control;
-
-       cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
-       cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
-       vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
-}
-
-static void enable_nmi_window(struct kvm_vcpu *vcpu)
-{
-       u32 cpu_based_vm_exec_control;
-
-       if (!cpu_has_virtual_nmis())
-               return;
-
-       cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
-       cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_NMI_PENDING;
-       vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
-}
-
-static int vmx_nmi_enabled(struct kvm_vcpu *vcpu)
-{
-       u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
-       return !(guest_intr & (GUEST_INTR_STATE_NMI |
-                              GUEST_INTR_STATE_MOV_SS |
-                              GUEST_INTR_STATE_STI));
-}
-
-static int vmx_irq_enabled(struct kvm_vcpu *vcpu)
-{
-       u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
-       return (!(guest_intr & (GUEST_INTR_STATE_MOV_SS |
-                              GUEST_INTR_STATE_STI)) &&
-               (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF));
-}
-
-static void enable_intr_window(struct kvm_vcpu *vcpu)
-{
-       if (vcpu->arch.nmi_pending)
-               enable_nmi_window(vcpu);
-       else if (kvm_cpu_has_interrupt(vcpu))
-               enable_irq_window(vcpu);
+       vmcs_write32(TPR_THRESHOLD, irr);
 }
 
 static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
 {
        u32 exit_intr_info;
+       u32 idt_vectoring_info = vmx->idt_vectoring_info;
        bool unblock_nmi;
        u8 vector;
+       int type;
+       bool idtv_info_valid;
 
+       idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
        exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
        if (cpu_has_virtual_nmis()) {
                unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
                vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
                /*
-                * SDM 3: 25.7.1.2
+                * SDM 3: 27.7.1.2 (September 2008)
                 * Re-set bit "block by NMI" before VM entry if vmexit caused by
                 * a guest IRET fault.
+                * SDM 3: 23.2.2 (September 2008)
+                * Bit 12 is undefined in any of the following cases:
+                *  If the VM exit sets the valid bit in the IDT-vectoring
+                *   information field.
+                *  If the VM exit is due to a double fault.
                 */
-               if (unblock_nmi && vector != DF_VECTOR)
+               if ((exit_intr_info & INTR_INFO_VALID_MASK) && unblock_nmi &&
+                   vector != DF_VECTOR && !idtv_info_valid)
                        vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
                                      GUEST_INTR_STATE_NMI);
-       }
-}
+       } else if (unlikely(vmx->soft_vnmi_blocked))
+               vmx->vnmi_blocked_time +=
+                       ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time));
 
-static void vmx_intr_assist(struct kvm_vcpu *vcpu)
-{
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
-       u32 idtv_info_field, intr_info_field, exit_intr_info_field;
-       int vector;
-
-       update_tpr_threshold(vcpu);
-
-       intr_info_field = vmcs_read32(VM_ENTRY_INTR_INFO_FIELD);
-       exit_intr_info_field = vmcs_read32(VM_EXIT_INTR_INFO);
-       idtv_info_field = vmx->idt_vectoring_info;
-       if (intr_info_field & INTR_INFO_VALID_MASK) {
-               if (idtv_info_field & INTR_INFO_VALID_MASK) {
-                       /* TODO: fault when IDT_Vectoring */
-                       if (printk_ratelimit())
-                               printk(KERN_ERR "Fault when IDT_Vectoring\n");
-               }
-               enable_intr_window(vcpu);
-               return;
-       }
-       if (unlikely(idtv_info_field & INTR_INFO_VALID_MASK)) {
-               if ((idtv_info_field & VECTORING_INFO_TYPE_MASK)
-                   == INTR_TYPE_EXT_INTR
-                   && vcpu->arch.rmode.active) {
-                       u8 vect = idtv_info_field & VECTORING_INFO_VECTOR_MASK;
+       vmx->vcpu.arch.nmi_injected = false;
+       kvm_clear_exception_queue(&vmx->vcpu);
+       kvm_clear_interrupt_queue(&vmx->vcpu);
 
-                       vmx_inject_irq(vcpu, vect);
-                       enable_intr_window(vcpu);
-                       return;
-               }
+       if (!idtv_info_valid)
+               return;
 
-               KVMTRACE_1D(REDELIVER_EVT, vcpu, idtv_info_field, handler);
+       vector = idt_vectoring_info & VECTORING_INFO_VECTOR_MASK;
+       type = idt_vectoring_info & VECTORING_INFO_TYPE_MASK;
 
+       switch (type) {
+       case INTR_TYPE_NMI_INTR:
+               vmx->vcpu.arch.nmi_injected = true;
                /*
-                * SDM 3: 25.7.1.2
-                * Clear bit "block by NMI" before VM entry if a NMI delivery
-                * faulted.
+                * SDM 3: 27.7.1.2 (September 2008)
+                * Clear bit "block by NMI" before VM entry if a NMI
+                * delivery faulted.
                 */
-               if ((idtv_info_field & VECTORING_INFO_TYPE_MASK)
-                   == INTR_TYPE_NMI_INTR && cpu_has_virtual_nmis())
-                       vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
-                               vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
-                               ~GUEST_INTR_STATE_NMI);
-
-               vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field
-                               & ~INTR_INFO_RESVD_BITS_MASK);
-               vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
-                               vmcs_read32(VM_EXIT_INSTRUCTION_LEN));
-
-               if (unlikely(idtv_info_field & INTR_INFO_DELIVER_CODE_MASK))
-                       vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
-                               vmcs_read32(IDT_VECTORING_ERROR_CODE));
-               enable_intr_window(vcpu);
-               return;
-       }
-       if (cpu_has_virtual_nmis()) {
-               if (vcpu->arch.nmi_pending) {
-                       if (vmx_nmi_enabled(vcpu))
-                               vmx_inject_nmi(vcpu);
-                       enable_intr_window(vcpu);
-                       return;
-               }
+               vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
+                               GUEST_INTR_STATE_NMI);
+               break;
+       case INTR_TYPE_HARD_EXCEPTION:
+       case INTR_TYPE_SOFT_EXCEPTION:
+               if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) {
+                       u32 err = vmcs_read32(IDT_VECTORING_ERROR_CODE);
+                       kvm_queue_exception_e(&vmx->vcpu, vector, err);
+               } else
+                       kvm_queue_exception(&vmx->vcpu, vector);
+               break;
+       case INTR_TYPE_EXT_INTR:
+               kvm_queue_interrupt(&vmx->vcpu, vector);
+               break;
+       default:
+               break;
        }
-       if (!kvm_cpu_has_interrupt(vcpu))
-               return;
-       if (vmx_irq_enabled(vcpu)) {
-               vector = kvm_cpu_get_interrupt(vcpu);
-               vmx_inject_irq(vcpu, vector);
-               kvm_timer_intr_post(vcpu, vector);
-       } else
-               enable_irq_window(vcpu);
 }
 
 /*
@@ -2934,11 +3318,29 @@ static void fixup_rmode_irq(struct vcpu_vmx *vmx)
                | vmx->rmode.irq.vector;
 }
 
+#ifdef CONFIG_X86_64
+#define R "r"
+#define Q "q"
+#else
+#define R "e"
+#define Q "l"
+#endif
+
 static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        u32 intr_info;
 
+       /* Record the guest's net vcpu time for enforced NMI injections. */
+       if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked))
+               vmx->entry_time = ktime_get();
+
+       /* Handle invalid guest state instead of entering VMX */
+       if (vmx->emulation_required && emulate_invalid_guest_state) {
+               handle_invalid_guest_state(vcpu, kvm_run);
+               return;
+       }
+
        if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
                vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
        if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
@@ -2949,28 +3351,29 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
         */
        vmcs_writel(HOST_CR0, read_cr0());
 
+       set_debugreg(vcpu->arch.dr6, 6);
+
        asm(
                /* Store host registers */
-#ifdef CONFIG_X86_64
-               "push %%rdx; push %%rbp;"
-               "push %%rcx \n\t"
-#else
-               "push %%edx; push %%ebp;"
-               "push %%ecx \n\t"
-#endif
+               "push %%"R"dx; push %%"R"bp;"
+               "push %%"R"cx \n\t"
+               "cmp %%"R"sp, %c[host_rsp](%0) \n\t"
+               "je 1f \n\t"
+               "mov %%"R"sp, %c[host_rsp](%0) \n\t"
                __ex(ASM_VMX_VMWRITE_RSP_RDX) "\n\t"
+               "1: \n\t"
                /* Check if vmlaunch of vmresume is needed */
                "cmpl $0, %c[launched](%0) \n\t"
                /* Load guest registers.  Don't clobber flags. */
+               "mov %c[cr2](%0), %%"R"ax \n\t"
+               "mov %%"R"ax, %%cr2 \n\t"
+               "mov %c[rax](%0), %%"R"ax \n\t"
+               "mov %c[rbx](%0), %%"R"bx \n\t"
+               "mov %c[rdx](%0), %%"R"dx \n\t"
+               "mov %c[rsi](%0), %%"R"si \n\t"
+               "mov %c[rdi](%0), %%"R"di \n\t"
+               "mov %c[rbp](%0), %%"R"bp \n\t"
 #ifdef CONFIG_X86_64
-               "mov %c[cr2](%0), %%rax \n\t"
-               "mov %%rax, %%cr2 \n\t"
-               "mov %c[rax](%0), %%rax \n\t"
-               "mov %c[rbx](%0), %%rbx \n\t"
-               "mov %c[rdx](%0), %%rdx \n\t"
-               "mov %c[rsi](%0), %%rsi \n\t"
-               "mov %c[rdi](%0), %%rdi \n\t"
-               "mov %c[rbp](%0), %%rbp \n\t"
                "mov %c[r8](%0),  %%r8  \n\t"
                "mov %c[r9](%0),  %%r9  \n\t"
                "mov %c[r10](%0), %%r10 \n\t"
@@ -2979,18 +3382,9 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                "mov %c[r13](%0), %%r13 \n\t"
                "mov %c[r14](%0), %%r14 \n\t"
                "mov %c[r15](%0), %%r15 \n\t"
-               "mov %c[rcx](%0), %%rcx \n\t" /* kills %0 (rcx) */
-#else
-               "mov %c[cr2](%0), %%eax \n\t"
-               "mov %%eax,   %%cr2 \n\t"
-               "mov %c[rax](%0), %%eax \n\t"
-               "mov %c[rbx](%0), %%ebx \n\t"
-               "mov %c[rdx](%0), %%edx \n\t"
-               "mov %c[rsi](%0), %%esi \n\t"
-               "mov %c[rdi](%0), %%edi \n\t"
-               "mov %c[rbp](%0), %%ebp \n\t"
-               "mov %c[rcx](%0), %%ecx \n\t" /* kills %0 (ecx) */
 #endif
+               "mov %c[rcx](%0), %%"R"cx \n\t" /* kills %0 (ecx) */
+
                /* Enter guest mode */
                "jne .Llaunched \n\t"
                __ex(ASM_VMX_VMLAUNCH) "\n\t"
@@ -2998,15 +3392,15 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                ".Llaunched: " __ex(ASM_VMX_VMRESUME) "\n\t"
                ".Lkvm_vmx_return: "
                /* Save guest registers, load host registers, keep flags */
+               "xchg %0,     (%%"R"sp) \n\t"
+               "mov %%"R"ax, %c[rax](%0) \n\t"
+               "mov %%"R"bx, %c[rbx](%0) \n\t"
+               "push"Q" (%%"R"sp); pop"Q" %c[rcx](%0) \n\t"
+               "mov %%"R"dx, %c[rdx](%0) \n\t"
+               "mov %%"R"si, %c[rsi](%0) \n\t"
+               "mov %%"R"di, %c[rdi](%0) \n\t"
+               "mov %%"R"bp, %c[rbp](%0) \n\t"
 #ifdef CONFIG_X86_64
-               "xchg %0,     (%%rsp) \n\t"
-               "mov %%rax, %c[rax](%0) \n\t"
-               "mov %%rbx, %c[rbx](%0) \n\t"
-               "pushq (%%rsp); popq %c[rcx](%0) \n\t"
-               "mov %%rdx, %c[rdx](%0) \n\t"
-               "mov %%rsi, %c[rsi](%0) \n\t"
-               "mov %%rdi, %c[rdi](%0) \n\t"
-               "mov %%rbp, %c[rbp](%0) \n\t"
                "mov %%r8,  %c[r8](%0) \n\t"
                "mov %%r9,  %c[r9](%0) \n\t"
                "mov %%r10, %c[r10](%0) \n\t"
@@ -3015,28 +3409,16 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                "mov %%r13, %c[r13](%0) \n\t"
                "mov %%r14, %c[r14](%0) \n\t"
                "mov %%r15, %c[r15](%0) \n\t"
-               "mov %%cr2, %%rax   \n\t"
-               "mov %%rax, %c[cr2](%0) \n\t"
-
-               "pop  %%rbp; pop  %%rbp; pop  %%rdx \n\t"
-#else
-               "xchg %0, (%%esp) \n\t"
-               "mov %%eax, %c[rax](%0) \n\t"
-               "mov %%ebx, %c[rbx](%0) \n\t"
-               "pushl (%%esp); popl %c[rcx](%0) \n\t"
-               "mov %%edx, %c[rdx](%0) \n\t"
-               "mov %%esi, %c[rsi](%0) \n\t"
-               "mov %%edi, %c[rdi](%0) \n\t"
-               "mov %%ebp, %c[rbp](%0) \n\t"
-               "mov %%cr2, %%eax  \n\t"
-               "mov %%eax, %c[cr2](%0) \n\t"
-
-               "pop %%ebp; pop %%ebp; pop %%edx \n\t"
 #endif
+               "mov %%cr2, %%"R"ax   \n\t"
+               "mov %%"R"ax, %c[cr2](%0) \n\t"
+
+               "pop  %%"R"bp; pop  %%"R"bp; pop  %%"R"dx \n\t"
                "setbe %c[fail](%0) \n\t"
              : : "c"(vmx), "d"((unsigned long)HOST_RSP),
                [launched]"i"(offsetof(struct vcpu_vmx, launched)),
                [fail]"i"(offsetof(struct vcpu_vmx, fail)),
+               [host_rsp]"i"(offsetof(struct vcpu_vmx, host_rsp)),
                [rax]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RAX])),
                [rbx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RBX])),
                [rcx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RCX])),
@@ -3056,32 +3438,28 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 #endif
                [cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2))
              : "cc", "memory"
+               , R"bx", R"di", R"si"
 #ifdef CONFIG_X86_64
-               , "rbx", "rdi", "rsi"
                , "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
-#else
-               , "ebx", "edi", "rsi"
 #endif
              );
 
        vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP));
        vcpu->arch.regs_dirty = 0;
 
+       get_debugreg(vcpu->arch.dr6, 6);
+
        vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
        if (vmx->rmode.irq.pending)
                fixup_rmode_irq(vmx);
 
-       vcpu->arch.interrupt_window_open =
-               (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
-                (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS)) == 0;
-
        asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
        vmx->launched = 1;
 
        intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
 
        /* We need to handle NMIs before interrupts are enabled */
-       if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200 &&
+       if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR &&
            (intr_info & INTR_INFO_VALID_MASK)) {
                KVMTRACE_0D(NMI, vcpu, handler);
                asm("int $2");
@@ -3090,6 +3468,9 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        vmx_complete_interrupts(vmx);
 }
 
+#undef R
+#undef Q
+
 static void vmx_free_vmcs(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -3158,7 +3539,7 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
                if (alloc_apic_access_page(kvm) != 0)
                        goto free_vmcs;
 
-       if (vm_need_ept())
+       if (enable_ept)
                if (alloc_identity_pagetable(kvm) != 0)
                        goto free_vmcs;
 
@@ -3196,6 +3577,19 @@ static int get_ept_level(void)
        return VMX_EPT_DEFAULT_GAW + 1;
 }
 
+static u64 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
+{
+       u64 ret;
+
+       if (is_mmio)
+               ret = MTRR_TYPE_UNCACHABLE << VMX_EPT_MT_EPTE_SHIFT;
+       else
+               ret = (kvm_get_guest_memory_type(vcpu, gfn) <<
+                       VMX_EPT_MT_EPTE_SHIFT) | VMX_EPT_IGMT_BIT;
+
+       return ret;
+}
+
 static struct kvm_x86_ops vmx_x86_ops = {
        .cpu_has_kvm_support = cpu_has_kvm_support,
        .disabled_by_bios = vmx_disabled_by_bios,
@@ -3204,7 +3598,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
        .check_processor_compatibility = vmx_check_processor_compat,
        .hardware_enable = hardware_enable,
        .hardware_disable = hardware_disable,
-       .cpu_has_accelerated_tpr = cpu_has_vmx_virtualize_apic_accesses,
+       .cpu_has_accelerated_tpr = report_flexpriority,
 
        .vcpu_create = vmx_create_vcpu,
        .vcpu_free = vmx_free_vcpu,
@@ -3215,7 +3609,6 @@ static struct kvm_x86_ops vmx_x86_ops = {
        .vcpu_put = vmx_vcpu_put,
 
        .set_guest_debug = set_guest_debug,
-       .guest_debug_pre = kvm_guest_debug_pre,
        .get_msr = vmx_get_msr,
        .set_msr = vmx_set_msr,
        .get_segment_base = vmx_get_segment_base,
@@ -3239,75 +3632,79 @@ static struct kvm_x86_ops vmx_x86_ops = {
        .tlb_flush = vmx_flush_tlb,
 
        .run = vmx_vcpu_run,
-       .handle_exit = kvm_handle_exit,
+       .handle_exit = vmx_handle_exit,
        .skip_emulated_instruction = skip_emulated_instruction,
        .patch_hypercall = vmx_patch_hypercall,
-       .get_irq = vmx_get_irq,
        .set_irq = vmx_inject_irq,
+       .set_nmi = vmx_inject_nmi,
        .queue_exception = vmx_queue_exception,
-       .exception_injected = vmx_exception_injected,
-       .inject_pending_irq = vmx_intr_assist,
-       .inject_pending_vectors = do_interrupt_requests,
+       .interrupt_allowed = vmx_interrupt_allowed,
+       .nmi_allowed = vmx_nmi_allowed,
+       .enable_nmi_window = enable_nmi_window,
+       .enable_irq_window = enable_irq_window,
+       .update_cr8_intercept = update_cr8_intercept,
+       .drop_interrupt_shadow = vmx_drop_interrupt_shadow,
 
        .set_tss_addr = vmx_set_tss_addr,
        .get_tdp_level = get_ept_level,
+       .get_mt_mask = vmx_get_mt_mask,
 };
 
 static int __init vmx_init(void)
 {
-       void *va;
        int r;
 
-       vmx_io_bitmap_a = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+       vmx_io_bitmap_a = (unsigned long *)__get_free_page(GFP_KERNEL);
        if (!vmx_io_bitmap_a)
                return -ENOMEM;
 
-       vmx_io_bitmap_b = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+       vmx_io_bitmap_b = (unsigned long *)__get_free_page(GFP_KERNEL);
        if (!vmx_io_bitmap_b) {
                r = -ENOMEM;
                goto out;
        }
 
-       vmx_msr_bitmap = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
-       if (!vmx_msr_bitmap) {
+       vmx_msr_bitmap_legacy = (unsigned long *)__get_free_page(GFP_KERNEL);
+       if (!vmx_msr_bitmap_legacy) {
                r = -ENOMEM;
                goto out1;
        }
 
+       vmx_msr_bitmap_longmode = (unsigned long *)__get_free_page(GFP_KERNEL);
+       if (!vmx_msr_bitmap_longmode) {
+               r = -ENOMEM;
+               goto out2;
+       }
+
        /*
         * Allow direct access to the PC debug port (it is often used for I/O
         * delays, but the vmexits simply slow things down).
         */
-       va = kmap(vmx_io_bitmap_a);
-       memset(va, 0xff, PAGE_SIZE);
-       clear_bit(0x80, va);
-       kunmap(vmx_io_bitmap_a);
+       memset(vmx_io_bitmap_a, 0xff, PAGE_SIZE);
+       clear_bit(0x80, vmx_io_bitmap_a);
 
-       va = kmap(vmx_io_bitmap_b);
-       memset(va, 0xff, PAGE_SIZE);
-       kunmap(vmx_io_bitmap_b);
+       memset(vmx_io_bitmap_b, 0xff, PAGE_SIZE);
 
-       va = kmap(vmx_msr_bitmap);
-       memset(va, 0xff, PAGE_SIZE);
-       kunmap(vmx_msr_bitmap);
+       memset(vmx_msr_bitmap_legacy, 0xff, PAGE_SIZE);
+       memset(vmx_msr_bitmap_longmode, 0xff, PAGE_SIZE);
 
        set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
 
        r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), THIS_MODULE);
        if (r)
-               goto out2;
+               goto out3;
 
-       vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_FS_BASE);
-       vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_GS_BASE);
-       vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_CS);
-       vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_ESP);
-       vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_EIP);
+       vmx_disable_intercept_for_msr(MSR_FS_BASE, false);
+       vmx_disable_intercept_for_msr(MSR_GS_BASE, false);
+       vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true);
+       vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false);
+       vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false);
+       vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false);
 
-       if (vm_need_ept()) {
+       if (enable_ept) {
                bypass_guest_pf = 0;
                kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
-                       VMX_EPT_WRITABLE_MASK |
-                       VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT);
+                       VMX_EPT_WRITABLE_MASK);
                kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull,
                                VMX_EPT_EXECUTABLE_MASK);
                kvm_enable_tdp();
@@ -3321,20 +3718,23 @@ static int __init vmx_init(void)
 
        return 0;
 
+out3:
+       free_page((unsigned long)vmx_msr_bitmap_longmode);
 out2:
-       __free_page(vmx_msr_bitmap);
+       free_page((unsigned long)vmx_msr_bitmap_legacy);
 out1:
-       __free_page(vmx_io_bitmap_b);
+       free_page((unsigned long)vmx_io_bitmap_b);
 out:
-       __free_page(vmx_io_bitmap_a);
+       free_page((unsigned long)vmx_io_bitmap_a);
        return r;
 }
 
 static void __exit vmx_exit(void)
 {
-       __free_page(vmx_msr_bitmap);
-       __free_page(vmx_io_bitmap_b);
-       __free_page(vmx_io_bitmap_a);
+       free_page((unsigned long)vmx_msr_bitmap_legacy);
+       free_page((unsigned long)vmx_msr_bitmap_longmode);
+       free_page((unsigned long)vmx_io_bitmap_b);
+       free_page((unsigned long)vmx_io_bitmap_a);
 
        kvm_exit();
 }