aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2010-03-18 09:20:26 -0400
committerAvi Kivity <avi@redhat.com>2010-05-17 05:16:29 -0400
commit5cd21917da245fbe98bd443de2c7f519b3df6814 (patch)
tree0bb2d4ee197011a92002a5cc32d19758a1e87ed0 /arch/x86/kvm/emulate.c
parentcb404fe0898779ec5fe5e06e90aaddcf40aefad8 (diff)
KVM: x86 emulator: restart string instruction without going back to a guest.
Currently when string instruction is only partially complete we go back to a guest mode, guest tries to reexecute instruction and exits again and at this point emulation continues. Avoid all of this by restarting instruction without going back to a guest mode, but return to a guest mode each 1024 iterations to allow interrupt injection. Pending exception causes immediate guest entry too. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 0579d9dd9aac..6de6ad1610d8 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -927,8 +927,11 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
927 int mode = ctxt->mode; 927 int mode = ctxt->mode;
928 int def_op_bytes, def_ad_bytes, group; 928 int def_op_bytes, def_ad_bytes, group;
929 929
930 /* Shadow copy of register state. Committed on successful emulation. */
931 930
931 /* we cannot decode insn before we complete previous rep insn */
932 WARN_ON(ctxt->restart);
933
934 /* Shadow copy of register state. Committed on successful emulation. */
932 memset(c, 0, sizeof(struct decode_cache)); 935 memset(c, 0, sizeof(struct decode_cache));
933 c->eip = ctxt->eip; 936 c->eip = ctxt->eip;
934 ctxt->cs_base = seg_base(ctxt, VCPU_SREG_CS); 937 ctxt->cs_base = seg_base(ctxt, VCPU_SREG_CS);
@@ -2426,6 +2429,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
2426 u64 msr_data; 2429 u64 msr_data;
2427 struct decode_cache *c = &ctxt->decode; 2430 struct decode_cache *c = &ctxt->decode;
2428 int rc = X86EMUL_CONTINUE; 2431 int rc = X86EMUL_CONTINUE;
2432 int saved_dst_type = c->dst.type;
2429 2433
2430 ctxt->interruptibility = 0; 2434 ctxt->interruptibility = 0;
2431 2435
@@ -2454,8 +2458,11 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
2454 } 2458 }
2455 2459
2456 if (c->rep_prefix && (c->d & String)) { 2460 if (c->rep_prefix && (c->d & String)) {
2461 ctxt->restart = true;
2457 /* All REP prefixes have the same first termination condition */ 2462 /* All REP prefixes have the same first termination condition */
2458 if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) { 2463 if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) {
2464 string_done:
2465 ctxt->restart = false;
2459 kvm_rip_write(ctxt->vcpu, c->eip); 2466 kvm_rip_write(ctxt->vcpu, c->eip);
2460 goto done; 2467 goto done;
2461 } 2468 }
@@ -2467,17 +2474,13 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
2467 * - if REPNE/REPNZ and ZF = 1 then done 2474 * - if REPNE/REPNZ and ZF = 1 then done
2468 */ 2475 */
2469 if ((c->b == 0xa6) || (c->b == 0xa7) || 2476 if ((c->b == 0xa6) || (c->b == 0xa7) ||
2470 (c->b == 0xae) || (c->b == 0xaf)) { 2477 (c->b == 0xae) || (c->b == 0xaf)) {
2471 if ((c->rep_prefix == REPE_PREFIX) && 2478 if ((c->rep_prefix == REPE_PREFIX) &&
2472 ((ctxt->eflags & EFLG_ZF) == 0)) { 2479 ((ctxt->eflags & EFLG_ZF) == 0))
2473 kvm_rip_write(ctxt->vcpu, c->eip); 2480 goto string_done;
2474 goto done;
2475 }
2476 if ((c->rep_prefix == REPNE_PREFIX) && 2481 if ((c->rep_prefix == REPNE_PREFIX) &&
2477 ((ctxt->eflags & EFLG_ZF) == EFLG_ZF)) { 2482 ((ctxt->eflags & EFLG_ZF) == EFLG_ZF))
2478 kvm_rip_write(ctxt->vcpu, c->eip); 2483 goto string_done;
2479 goto done;
2480 }
2481 } 2484 }
2482 c->eip = ctxt->eip; 2485 c->eip = ctxt->eip;
2483 } 2486 }
@@ -2911,6 +2914,12 @@ writeback:
2911 if (rc != X86EMUL_CONTINUE) 2914 if (rc != X86EMUL_CONTINUE)
2912 goto done; 2915 goto done;
2913 2916
2917 /*
2918 * restore dst type in case the decoding will be reused
2919 * (happens for string instruction )
2920 */
2921 c->dst.type = saved_dst_type;
2922
2914 if ((c->d & SrcMask) == SrcSI) 2923 if ((c->d & SrcMask) == SrcSI)
2915 string_addr_inc(ctxt, seg_override_base(ctxt, c), VCPU_REGS_RSI, 2924 string_addr_inc(ctxt, seg_override_base(ctxt, c), VCPU_REGS_RSI,
2916 &c->src); 2925 &c->src);
@@ -2918,8 +2927,11 @@ writeback:
2918 if ((c->d & DstMask) == DstDI) 2927 if ((c->d & DstMask) == DstDI)
2919 string_addr_inc(ctxt, es_base(ctxt), VCPU_REGS_RDI, &c->dst); 2928 string_addr_inc(ctxt, es_base(ctxt), VCPU_REGS_RDI, &c->dst);
2920 2929
2921 if (c->rep_prefix && (c->d & String)) 2930 if (c->rep_prefix && (c->d & String)) {
2922 register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1); 2931 register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1);
2932 if (!(c->regs[VCPU_REGS_RCX] & 0x3ff))
2933 ctxt->restart = false;
2934 }
2923 2935
2924 /* Commit shadow register state. */ 2936 /* Commit shadow register state. */
2925 memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs); 2937 memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs);