int mode = ctxt->mode;
        int def_op_bytes, def_ad_bytes, group;
 
-       /* Shadow copy of register state. Committed on successful emulation. */
 
+       /* we cannot decode insn before we complete previous rep insn */
+       WARN_ON(ctxt->restart);
+
+       /* Shadow copy of register state. Committed on successful emulation. */
        memset(c, 0, sizeof(struct decode_cache));
        c->eip = ctxt->eip;
        ctxt->cs_base = seg_base(ctxt, VCPU_SREG_CS);
        u64 msr_data;
        struct decode_cache *c = &ctxt->decode;
        int rc = X86EMUL_CONTINUE;
+       int saved_dst_type = c->dst.type;
 
        ctxt->interruptibility = 0;
 
        }
 
        if (c->rep_prefix && (c->d & String)) {
+               ctxt->restart = true;
                /* All REP prefixes have the same first termination condition */
                if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) {
+               string_done:
+                       ctxt->restart = false;
                        kvm_rip_write(ctxt->vcpu, c->eip);
                        goto done;
                }
                 *      - if REPNE/REPNZ and ZF = 1 then done
                 */
                if ((c->b == 0xa6) || (c->b == 0xa7) ||
-                               (c->b == 0xae) || (c->b == 0xaf)) {
+                   (c->b == 0xae) || (c->b == 0xaf)) {
                        if ((c->rep_prefix == REPE_PREFIX) &&
-                               ((ctxt->eflags & EFLG_ZF) == 0)) {
-                                       kvm_rip_write(ctxt->vcpu, c->eip);
-                                       goto done;
-                       }
+                           ((ctxt->eflags & EFLG_ZF) == 0))
+                               goto string_done;
                        if ((c->rep_prefix == REPNE_PREFIX) &&
-                               ((ctxt->eflags & EFLG_ZF) == EFLG_ZF)) {
-                               kvm_rip_write(ctxt->vcpu, c->eip);
-                               goto done;
-                       }
+                           ((ctxt->eflags & EFLG_ZF) == EFLG_ZF))
+                               goto string_done;
                }
                c->eip = ctxt->eip;
        }
        if (rc != X86EMUL_CONTINUE)
                goto done;
 
+       /*
+        * restore dst type in case the decoding will be reused
+        * (happens for string instruction )
+        */
+       c->dst.type = saved_dst_type;
+
        if ((c->d & SrcMask) == SrcSI)
                string_addr_inc(ctxt, seg_override_base(ctxt, c), VCPU_REGS_RSI,
                                &c->src);
        if ((c->d & DstMask) == DstDI)
                string_addr_inc(ctxt, es_base(ctxt), VCPU_REGS_RDI, &c->dst);
 
-       if (c->rep_prefix && (c->d & String))
+       if (c->rep_prefix && (c->d & String)) {
                register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1);
+               if (!(c->regs[VCPU_REGS_RCX] & 0x3ff))
+                       ctxt->restart = false;
+       }
 
        /* Commit shadow register state. */
        memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs);
 
                return EMULATE_DONE;
        }
 
+restart:
        r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
        shadow_mask = vcpu->arch.emulate_ctxt.interruptibility;
 
 
        if (r) {
                if (kvm_mmu_unprotect_page_virt(vcpu, cr2))
-                       return EMULATE_DONE;
+                       goto done;
                if (!vcpu->mmio_needed) {
                        kvm_report_emulation_failure(vcpu, "mmio");
                        return EMULATE_FAIL;
                return EMULATE_DO_MMIO;
        }
 
+done:
+       if (vcpu->arch.exception.pending)
+               vcpu->arch.emulate_ctxt.restart = false;
+
+       if (vcpu->arch.emulate_ctxt.restart)
+               goto restart;
+
        return EMULATE_DONE;
 }
 EXPORT_SYMBOL_GPL(emulate_instruction);
                        goto out;
                }
        }
+       if (vcpu->arch.emulate_ctxt.restart) {
+               vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+               r = emulate_instruction(vcpu, 0, 0, EMULTYPE_NO_DECODE);
+               srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
+               if (r == EMULATE_DO_MMIO) {
+                       r = 0;
+                       goto out;
+               }
+       }
        if (kvm_run->exit_reason == KVM_EXIT_HYPERCALL)
                kvm_register_write(vcpu, VCPU_REGS_RAX,
                                     kvm_run->hypercall.ret);