KVM: remove export of emulator_write_emulated()
[pandora-kernel.git] / arch / x86 / kvm / x86.c
index 05d571f..15a4b75 100644 (file)
@@ -414,57 +414,49 @@ out:
        return changed;
 }
 
-void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+static int __kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
        cr0 |= X86_CR0_ET;
 
 #ifdef CONFIG_X86_64
-       if (cr0 & 0xffffffff00000000UL) {
-               kvm_inject_gp(vcpu, 0);
-               return;
-       }
+       if (cr0 & 0xffffffff00000000UL)
+               return 1;
 #endif
 
        cr0 &= ~CR0_RESERVED_BITS;
 
-       if ((cr0 & X86_CR0_NW) && !(cr0 & X86_CR0_CD)) {
-               kvm_inject_gp(vcpu, 0);
-               return;
-       }
+       if ((cr0 & X86_CR0_NW) && !(cr0 & X86_CR0_CD))
+               return 1;
 
-       if ((cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PE)) {
-               kvm_inject_gp(vcpu, 0);
-               return;
-       }
+       if ((cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PE))
+               return 1;
 
        if (!is_paging(vcpu) && (cr0 & X86_CR0_PG)) {
 #ifdef CONFIG_X86_64
                if ((vcpu->arch.efer & EFER_LME)) {
                        int cs_db, cs_l;
 
-                       if (!is_pae(vcpu)) {
-                               kvm_inject_gp(vcpu, 0);
-                               return;
-                       }
+                       if (!is_pae(vcpu))
+                               return 1;
                        kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
-                       if (cs_l) {
-                               kvm_inject_gp(vcpu, 0);
-                               return;
-
-                       }
+                       if (cs_l)
+                               return 1;
                } else
 #endif
-               if (is_pae(vcpu) && !load_pdptrs(vcpu, vcpu->arch.cr3)) {
-                       kvm_inject_gp(vcpu, 0);
-                       return;
-               }
-
+               if (is_pae(vcpu) && !load_pdptrs(vcpu, vcpu->arch.cr3))
+                       return 1;
        }
 
        kvm_x86_ops->set_cr0(vcpu, cr0);
 
        kvm_mmu_reset_context(vcpu);
-       return;
+       return 0;
+}
+
+void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+       if (__kvm_set_cr0(vcpu, cr0))
+               kvm_inject_gp(vcpu, 0);
 }
 EXPORT_SYMBOL_GPL(kvm_set_cr0);
 
@@ -474,61 +466,56 @@ void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
 }
 EXPORT_SYMBOL_GPL(kvm_lmsw);
 
-void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+int __kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
        unsigned long old_cr4 = kvm_read_cr4(vcpu);
        unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE;
 
-       if (cr4 & CR4_RESERVED_BITS) {
-               kvm_inject_gp(vcpu, 0);
-               return;
-       }
+       if (cr4 & CR4_RESERVED_BITS)
+               return 1;
 
        if (is_long_mode(vcpu)) {
-               if (!(cr4 & X86_CR4_PAE)) {
-                       kvm_inject_gp(vcpu, 0);
-                       return;
-               }
+               if (!(cr4 & X86_CR4_PAE))
+                       return 1;
        } else if (is_paging(vcpu) && (cr4 & X86_CR4_PAE)
                   && ((cr4 ^ old_cr4) & pdptr_bits)
-                  && !load_pdptrs(vcpu, vcpu->arch.cr3)) {
-               kvm_inject_gp(vcpu, 0);
-               return;
-       }
+                  && !load_pdptrs(vcpu, vcpu->arch.cr3))
+               return 1;
+
+       if (cr4 & X86_CR4_VMXE)
+               return 1;
 
-       if (cr4 & X86_CR4_VMXE) {
-               kvm_inject_gp(vcpu, 0);
-               return;
-       }
        kvm_x86_ops->set_cr4(vcpu, cr4);
        vcpu->arch.cr4 = cr4;
        kvm_mmu_reset_context(vcpu);
+
+       return 0;
+}
+
+void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+{
+       if (__kvm_set_cr4(vcpu, cr4))
+               kvm_inject_gp(vcpu, 0);
 }
 EXPORT_SYMBOL_GPL(kvm_set_cr4);
 
-void kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
+static int __kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
        if (cr3 == vcpu->arch.cr3 && !pdptrs_changed(vcpu)) {
                kvm_mmu_sync_roots(vcpu);
                kvm_mmu_flush_tlb(vcpu);
-               return;
+               return 0;
        }
 
        if (is_long_mode(vcpu)) {
-               if (cr3 & CR3_L_MODE_RESERVED_BITS) {
-                       kvm_inject_gp(vcpu, 0);
-                       return;
-               }
+               if (cr3 & CR3_L_MODE_RESERVED_BITS)
+                       return 1;
        } else {
                if (is_pae(vcpu)) {
-                       if (cr3 & CR3_PAE_RESERVED_BITS) {
-                               kvm_inject_gp(vcpu, 0);
-                               return;
-                       }
-                       if (is_paging(vcpu) && !load_pdptrs(vcpu, cr3)) {
-                               kvm_inject_gp(vcpu, 0);
-                               return;
-                       }
+                       if (cr3 & CR3_PAE_RESERVED_BITS)
+                               return 1;
+                       if (is_paging(vcpu) && !load_pdptrs(vcpu, cr3))
+                               return 1;
                }
                /*
                 * We don't check reserved bits in nonpae mode, because
@@ -546,24 +533,34 @@ void kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
         * to debug) behavior on the guest side.
         */
        if (unlikely(!gfn_to_memslot(vcpu->kvm, cr3 >> PAGE_SHIFT)))
+               return 1;
+       vcpu->arch.cr3 = cr3;
+       vcpu->arch.mmu.new_cr3(vcpu);
+       return 0;
+}
+
+void kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
+{
+       if (__kvm_set_cr3(vcpu, cr3))
                kvm_inject_gp(vcpu, 0);
-       else {
-               vcpu->arch.cr3 = cr3;
-               vcpu->arch.mmu.new_cr3(vcpu);
-       }
 }
 EXPORT_SYMBOL_GPL(kvm_set_cr3);
 
-void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
+int __kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
-       if (cr8 & CR8_RESERVED_BITS) {
-               kvm_inject_gp(vcpu, 0);
-               return;
-       }
+       if (cr8 & CR8_RESERVED_BITS)
+               return 1;
        if (irqchip_in_kernel(vcpu->kvm))
                kvm_lapic_set_tpr(vcpu, cr8);
        else
                vcpu->arch.cr8 = cr8;
+       return 0;
+}
+
+void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
+{
+       if (__kvm_set_cr8(vcpu, cr8))
+               kvm_inject_gp(vcpu, 0);
 }
 EXPORT_SYMBOL_GPL(kvm_set_cr8);
 
@@ -576,7 +573,7 @@ unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_GPL(kvm_get_cr8);
 
-int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
+static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
 {
        switch (dr) {
        case 0 ... 3:
@@ -585,29 +582,21 @@ int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
                        vcpu->arch.eff_db[dr] = val;
                break;
        case 4:
-               if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) {
-                       kvm_queue_exception(vcpu, UD_VECTOR);
-                       return 1;
-               }
+               if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
+                       return 1; /* #UD */
                /* fall through */
        case 6:
-               if (val & 0xffffffff00000000ULL) {
-                       kvm_inject_gp(vcpu, 0);
-                       return 1;
-               }
+               if (val & 0xffffffff00000000ULL)
+                       return -1; /* #GP */
                vcpu->arch.dr6 = (val & DR6_VOLATILE) | DR6_FIXED_1;
                break;
        case 5:
-               if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) {
-                       kvm_queue_exception(vcpu, UD_VECTOR);
-                       return 1;
-               }
+               if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
+                       return 1; /* #UD */
                /* fall through */
        default: /* 7 */
-               if (val & 0xffffffff00000000ULL) {
-                       kvm_inject_gp(vcpu, 0);
-                       return 1;
-               }
+               if (val & 0xffffffff00000000ULL)
+                       return -1; /* #GP */
                vcpu->arch.dr7 = (val & DR7_VOLATILE) | DR7_FIXED_1;
                if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) {
                        kvm_x86_ops->set_dr7(vcpu, vcpu->arch.dr7);
@@ -618,28 +607,37 @@ int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
 
        return 0;
 }
+
+int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
+{
+       int res;
+
+       res = __kvm_set_dr(vcpu, dr, val);
+       if (res > 0)
+               kvm_queue_exception(vcpu, UD_VECTOR);
+       else if (res < 0)
+               kvm_inject_gp(vcpu, 0);
+
+       return res;
+}
 EXPORT_SYMBOL_GPL(kvm_set_dr);
 
-int kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val)
+static int _kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val)
 {
        switch (dr) {
        case 0 ... 3:
                *val = vcpu->arch.db[dr];
                break;
        case 4:
-               if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) {
-                       kvm_queue_exception(vcpu, UD_VECTOR);
+               if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
                        return 1;
-               }
                /* fall through */
        case 6:
                *val = vcpu->arch.dr6;
                break;
        case 5:
-               if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) {
-                       kvm_queue_exception(vcpu, UD_VECTOR);
+               if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
                        return 1;
-               }
                /* fall through */
        default: /* 7 */
                *val = vcpu->arch.dr7;
@@ -648,6 +646,15 @@ int kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val)
 
        return 0;
 }
+
+int kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val)
+{
+       if (_kvm_get_dr(vcpu, dr, val)) {
+               kvm_queue_exception(vcpu, UD_VECTOR);
+               return 1;
+       }
+       return 0;
+}
 EXPORT_SYMBOL_GPL(kvm_get_dr);
 
 static inline u32 bit(int bitno)
@@ -1562,7 +1569,7 @@ static int msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs __user *user_msrs,
 
        r = -ENOMEM;
        size = sizeof(struct kvm_msr_entry) * msrs.nmsrs;
-       entries = vmalloc(size);
+       entries = kmalloc(size, GFP_KERNEL);
        if (!entries)
                goto out;
 
@@ -1581,7 +1588,7 @@ static int msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs __user *user_msrs,
        r = n;
 
 out_free:
-       vfree(entries);
+       kfree(entries);
 out:
        return r;
 }
@@ -1731,8 +1738,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
-       kvm_put_guest_fpu(vcpu);
        kvm_x86_ops->vcpu_put(vcpu);
+       kvm_put_guest_fpu(vcpu);
 }
 
 static int is_efer_nx(void)
@@ -2797,7 +2804,6 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
        struct kvm_memory_slot *memslot;
        unsigned long n;
        unsigned long is_dirty = 0;
-       unsigned long *dirty_bitmap = NULL;
 
        mutex_lock(&kvm->slots_lock);
 
@@ -2812,27 +2818,30 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
 
        n = kvm_dirty_bitmap_bytes(memslot);
 
-       r = -ENOMEM;
-       dirty_bitmap = vmalloc(n);
-       if (!dirty_bitmap)
-               goto out;
-       memset(dirty_bitmap, 0, n);
-
        for (i = 0; !is_dirty && i < n/sizeof(long); i++)
                is_dirty = memslot->dirty_bitmap[i];
 
        /* If nothing is dirty, don't bother messing with page tables. */
        if (is_dirty) {
                struct kvm_memslots *slots, *old_slots;
+               unsigned long *dirty_bitmap;
 
                spin_lock(&kvm->mmu_lock);
                kvm_mmu_slot_remove_write_access(kvm, log->slot);
                spin_unlock(&kvm->mmu_lock);
 
-               slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
-               if (!slots)
-                       goto out_free;
+               r = -ENOMEM;
+               dirty_bitmap = vmalloc(n);
+               if (!dirty_bitmap)
+                       goto out;
+               memset(dirty_bitmap, 0, n);
 
+               r = -ENOMEM;
+               slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
+               if (!slots) {
+                       vfree(dirty_bitmap);
+                       goto out;
+               }
                memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots));
                slots->memslots[log->slot].dirty_bitmap = dirty_bitmap;
 
@@ -2841,13 +2850,20 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
                synchronize_srcu_expedited(&kvm->srcu);
                dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap;
                kfree(old_slots);
+
+               r = -EFAULT;
+               if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) {
+                       vfree(dirty_bitmap);
+                       goto out;
+               }
+               vfree(dirty_bitmap);
+       } else {
+               r = -EFAULT;
+               if (clear_user(log->dirty_bitmap, n))
+                       goto out;
        }
 
        r = 0;
-       if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n))
-               r = -EFAULT;
-out_free:
-       vfree(dirty_bitmap);
 out:
        mutex_unlock(&kvm->slots_lock);
        return r;
@@ -3259,7 +3275,7 @@ static int kvm_read_guest_virt_helper(gva_t addr, void *val, unsigned int bytes,
                }
                ret = kvm_read_guest(vcpu->kvm, gpa, data, toread);
                if (ret < 0) {
-                       r = X86EMUL_UNHANDLEABLE;
+                       r = X86EMUL_IO_NEEDED;
                        goto out;
                }
 
@@ -3315,7 +3331,7 @@ static int kvm_write_guest_virt_system(gva_t addr, void *val,
                }
                ret = kvm_write_guest(vcpu->kvm, gpa, data, towrite);
                if (ret < 0) {
-                       r = X86EMUL_UNHANDLEABLE;
+                       r = X86EMUL_IO_NEEDED;
                        goto out;
                }
 
@@ -3370,11 +3386,12 @@ mmio:
        trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0);
 
        vcpu->mmio_needed = 1;
-       vcpu->mmio_phys_addr = gpa;
-       vcpu->mmio_size = bytes;
-       vcpu->mmio_is_write = 0;
+       vcpu->run->exit_reason = KVM_EXIT_MMIO;
+       vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
+       vcpu->run->mmio.len = vcpu->mmio_size = bytes;
+       vcpu->run->mmio.is_write = vcpu->mmio_is_write = 0;
 
-       return X86EMUL_UNHANDLEABLE;
+       return X86EMUL_IO_NEEDED;
 }
 
 int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
@@ -3420,10 +3437,11 @@ mmio:
                return X86EMUL_CONTINUE;
 
        vcpu->mmio_needed = 1;
-       vcpu->mmio_phys_addr = gpa;
-       vcpu->mmio_size = bytes;
-       vcpu->mmio_is_write = 1;
-       memcpy(vcpu->mmio_data, val, bytes);
+       vcpu->run->exit_reason = KVM_EXIT_MMIO;
+       vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
+       vcpu->run->mmio.len = vcpu->mmio_size = bytes;
+       vcpu->run->mmio.is_write = vcpu->mmio_is_write = 1;
+       memcpy(vcpu->run->mmio.data, val, bytes);
 
        return X86EMUL_CONTINUE;
 }
@@ -3447,7 +3465,6 @@ int emulator_write_emulated(unsigned long addr,
        }
        return emulator_write_emulated_onepage(addr, val, bytes, vcpu);
 }
-EXPORT_SYMBOL_GPL(emulator_write_emulated);
 
 #define CMPXCHG_TYPE(t, ptr, old, new) \
        (cmpxchg((t *)(ptr), *(t *)(old), *(t *)(new)) == *(t *)(old))
@@ -3611,16 +3628,15 @@ int emulate_clts(struct kvm_vcpu *vcpu)
        return X86EMUL_CONTINUE;
 }
 
-int emulator_get_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long *dest)
+int emulator_get_dr(int dr, unsigned long *dest, struct kvm_vcpu *vcpu)
 {
-       return kvm_get_dr(ctxt->vcpu, dr, dest);
+       return _kvm_get_dr(vcpu, dr, dest);
 }
 
-int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long value)
+int emulator_set_dr(int dr, unsigned long value, struct kvm_vcpu *vcpu)
 {
-       unsigned long mask = (ctxt->mode == X86EMUL_MODE_PROT64) ? ~0ULL : ~0U;
 
-       return kvm_set_dr(ctxt->vcpu, dr, value & mask);
+       return __kvm_set_dr(vcpu, dr, value);
 }
 
 void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context)
@@ -3674,27 +3690,32 @@ static unsigned long emulator_get_cr(int cr, struct kvm_vcpu *vcpu)
        return value;
 }
 
-static void emulator_set_cr(int cr, unsigned long val, struct kvm_vcpu *vcpu)
+static int emulator_set_cr(int cr, unsigned long val, struct kvm_vcpu *vcpu)
 {
+       int res = 0;
+
        switch (cr) {
        case 0:
-               kvm_set_cr0(vcpu, mk_cr_64(kvm_read_cr0(vcpu), val));
+               res = __kvm_set_cr0(vcpu, mk_cr_64(kvm_read_cr0(vcpu), val));
                break;
        case 2:
                vcpu->arch.cr2 = val;
                break;
        case 3:
-               kvm_set_cr3(vcpu, val);
+               res = __kvm_set_cr3(vcpu, val);
                break;
        case 4:
-               kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val));
+               res = __kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val));
                break;
        case 8:
-               kvm_set_cr8(vcpu, val & 0xfUL);
+               res = __kvm_set_cr8(vcpu, val & 0xfUL);
                break;
        default:
                vcpu_printf(vcpu, "%s: unexpected cr %u\n", __func__, cr);
+               res = -1;
        }
+
+       return res;
 }
 
 static int emulator_get_cpl(struct kvm_vcpu *vcpu)
@@ -3707,6 +3728,12 @@ static void emulator_get_gdt(struct desc_ptr *dt, struct kvm_vcpu *vcpu)
        kvm_x86_ops->get_gdt(vcpu, dt);
 }
 
+static unsigned long emulator_get_cached_segment_base(int seg,
+                                                     struct kvm_vcpu *vcpu)
+{
+       return get_segment_base(vcpu, seg);
+}
+
 static bool emulator_get_cached_descriptor(struct desc_struct *desc, int seg,
                                           struct kvm_vcpu *vcpu)
 {
@@ -3797,11 +3824,16 @@ static struct x86_emulate_ops emulate_ops = {
        .set_cached_descriptor = emulator_set_cached_descriptor,
        .get_segment_selector = emulator_get_segment_selector,
        .set_segment_selector = emulator_set_segment_selector,
+       .get_cached_segment_base = emulator_get_cached_segment_base,
        .get_gdt             = emulator_get_gdt,
        .get_cr              = emulator_get_cr,
        .set_cr              = emulator_set_cr,
        .cpl                 = emulator_get_cpl,
        .set_rflags          = emulator_set_rflags,
+       .get_dr              = emulator_get_dr,
+       .set_dr              = emulator_set_dr,
+       .set_msr             = kvm_set_msr,
+       .get_msr             = kvm_get_msr,
 };
 
 static void cache_all_regs(struct kvm_vcpu *vcpu)
@@ -3819,7 +3851,6 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
 {
        int r, shadow_mask;
        struct decode_cache *c;
-       struct kvm_run *run = vcpu->run;
 
        kvm_clear_exception_queue(vcpu);
        vcpu->arch.mmio_fault_cr2 = cr2;
@@ -3831,8 +3862,6 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
         */
        cache_all_regs(vcpu);
 
-       vcpu->mmio_is_write = 0;
-
        if (!(emulation_type & EMULTYPE_NO_DECODE)) {
                int cs_db, cs_l;
                kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
@@ -3906,32 +3935,26 @@ restart:
                return EMULATE_DO_MMIO;
        }
 
-       if (r || vcpu->mmio_is_write) {
-               run->exit_reason = KVM_EXIT_MMIO;
-               run->mmio.phys_addr = vcpu->mmio_phys_addr;
-               memcpy(run->mmio.data, vcpu->mmio_data, 8);
-               run->mmio.len = vcpu->mmio_size;
-               run->mmio.is_write = vcpu->mmio_is_write;
+       if (vcpu->mmio_needed) {
+               if (vcpu->mmio_is_write)
+                       vcpu->mmio_needed = 0;
+               return EMULATE_DO_MMIO;
        }
 
-       if (r) {
+       if (r) { /* emulation failed */
+               /*
+                * if emulation was due to access to shadowed page table
+                * and it failed try to unshadow page and re-entetr the
+                * guest to let CPU execute the instruction.
+                */
                if (kvm_mmu_unprotect_page_virt(vcpu, cr2))
-                       goto done;
-               if (!vcpu->mmio_needed) {
-                       ++vcpu->stat.insn_emulation_fail;
-                       trace_kvm_emulate_insn_failed(vcpu);
-                       kvm_report_emulation_failure(vcpu, "mmio");
-                       return EMULATE_FAIL;
-               }
-               return EMULATE_DO_MMIO;
-       }
+                       return EMULATE_DONE;
 
-       if (vcpu->mmio_is_write) {
-               vcpu->mmio_needed = 0;
-               return EMULATE_DO_MMIO;
+               trace_kvm_emulate_insn_failed(vcpu);
+               kvm_report_emulation_failure(vcpu, "mmio");
+               return EMULATE_FAIL;
        }
 
-done:
        if (vcpu->arch.exception.pending)
                vcpu->arch.emulate_ctxt.restart = false;