static int bypass_guest_pf = 1;
 module_param(bypass_guest_pf, bool, 0);
 
+static int enable_vpid = 1;
+module_param(enable_vpid, bool, 0);
+
 struct vmcs {
        u32 revision_id;
        u32 abort;
                        unsigned rip;
                } irq;
        } rmode;
+       int vpid;
 };
 
 static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
 static struct page *vmx_io_bitmap_a;
 static struct page *vmx_io_bitmap_b;
 
+static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
+static DEFINE_SPINLOCK(vmx_vpid_lock);
+
 static struct vmcs_config {
        int size;
        int order;
                (irqchip_in_kernel(kvm)));
 }
 
+static inline int cpu_has_vmx_vpid(void)
+{
+       return (vmcs_config.cpu_based_2nd_exec_ctrl &
+               SECONDARY_EXEC_ENABLE_VPID);
+}
+
 static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
 {
        int i;
        return -1;
 }
 
+static inline void __invvpid(int ext, u16 vpid, gva_t gva)
+{
+    struct {
+       u64 vpid : 16;
+       u64 rsvd : 48;
+       u64 gva;
+    } operand = { vpid, 0, gva };
+
+    asm volatile (ASM_VMX_INVVPID
+                 /* CF==1 or ZF==1 --> rc = -1 */
+                 "; ja 1f ; ud2 ; 1:"
+                 : : "a"(&operand), "c"(ext) : "cc", "memory");
+}
+
 static struct kvm_msr_entry *find_msr_entry(struct vcpu_vmx *vmx, u32 msr)
 {
        int i;
        vmx->launched = 0;
 }
 
+static inline void vpid_sync_vcpu_all(struct vcpu_vmx *vmx)
+{
+       if (vmx->vpid == 0)
+               return;
+
+       __invvpid(VMX_VPID_EXTENT_SINGLE_CONTEXT, vmx->vpid, 0);
+}
+
 static unsigned long vmcs_readl(unsigned long field)
 {
        unsigned long value;
        if (vcpu->cpu != cpu) {
                vcpu_clear(vmx);
                kvm_migrate_apic_timer(vcpu);
+               vpid_sync_vcpu_all(vmx);
        }
 
        if (per_cpu(current_vmcs, cpu) != vmx->vmcs) {
        if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) {
                min = 0;
                opt = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
-                       SECONDARY_EXEC_WBINVD_EXITING;
+                       SECONDARY_EXEC_WBINVD_EXITING |
+                       SECONDARY_EXEC_ENABLE_VPID;
                if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS2,
                                        &_cpu_based_2nd_exec_control) < 0)
                        return -EIO;
 
 #endif
 
+static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
+{
+       vpid_sync_vcpu_all(to_vmx(vcpu));
+}
+
 static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
 {
        vcpu->arch.cr4 &= KVM_GUEST_CR4_MASK;
 
 static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
+       vmx_flush_tlb(vcpu);
        vmcs_writel(GUEST_CR3, cr3);
        if (vcpu->arch.cr0 & X86_CR0_PE)
                vmx_fpu_deactivate(vcpu);
        return r;
 }
 
+static void allocate_vpid(struct vcpu_vmx *vmx)
+{
+       int vpid;
+
+       vmx->vpid = 0;
+       if (!enable_vpid || !cpu_has_vmx_vpid())
+               return;
+       spin_lock(&vmx_vpid_lock);
+       vpid = find_first_zero_bit(vmx_vpid_bitmap, VMX_NR_VPIDS);
+       if (vpid < VMX_NR_VPIDS) {
+               vmx->vpid = vpid;
+               __set_bit(vpid, vmx_vpid_bitmap);
+       }
+       spin_unlock(&vmx_vpid_lock);
+}
+
 /*
  * Sets up the vmcs for emulated real mode.
  */
                if (!vm_need_virtualize_apic_accesses(vmx->vcpu.kvm))
                        exec_control &=
                                ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+               if (vmx->vpid == 0)
+                       exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
        }
 
                vmcs_write64(APIC_ACCESS_ADDR,
                             page_to_phys(vmx->vcpu.kvm->arch.apic_access_page));
 
+       if (vmx->vpid != 0)
+               vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
+
        vmx->vcpu.arch.cr0 = 0x60000010;
        vmx_set_cr0(&vmx->vcpu, vmx->vcpu.arch.cr0); /* enter rmode */
        vmx_set_cr4(&vmx->vcpu, 0);
        vmx_fpu_activate(&vmx->vcpu);
        update_exception_bitmap(&vmx->vcpu);
 
+       vpid_sync_vcpu_all(vmx);
+
        return 0;
 
 out:
        return 0;
 }
 
-static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
-{
-}
-
 static void update_tpr_threshold(struct kvm_vcpu *vcpu)
 {
        int max_irr, tpr;
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
 
+       spin_lock(&vmx_vpid_lock);
+       if (vmx->vpid != 0)
+               __clear_bit(vmx->vpid, vmx_vpid_bitmap);
+       spin_unlock(&vmx_vpid_lock);
        vmx_free_vmcs(vcpu);
        kfree(vmx->host_msrs);
        kfree(vmx->guest_msrs);
        if (!vmx)
                return ERR_PTR(-ENOMEM);
 
+       allocate_vpid(vmx);
+
        err = kvm_vcpu_init(&vmx->vcpu, kvm, id);
        if (err)
                goto free_vcpu;
        memset(iova, 0xff, PAGE_SIZE);
        kunmap(vmx_io_bitmap_b);
 
+       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 out1;