diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-03-18 09:20:26 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-05-17 05:16:29 -0400 |
commit | 5cd21917da245fbe98bd443de2c7f519b3df6814 (patch) | |
tree | 0bb2d4ee197011a92002a5cc32d19758a1e87ed0 /arch/x86/kvm/x86.c | |
parent | cb404fe0898779ec5fe5e06e90aaddcf40aefad8 (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/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 658e8e8155cb..c88cb8145283 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -3755,6 +3755,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu, | |||
3755 | return EMULATE_DONE; | 3755 | return EMULATE_DONE; |
3756 | } | 3756 | } |
3757 | 3757 | ||
3758 | restart: | ||
3758 | r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); | 3759 | r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); |
3759 | shadow_mask = vcpu->arch.emulate_ctxt.interruptibility; | 3760 | shadow_mask = vcpu->arch.emulate_ctxt.interruptibility; |
3760 | 3761 | ||
@@ -3777,7 +3778,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu, | |||
3777 | 3778 | ||
3778 | if (r) { | 3779 | if (r) { |
3779 | if (kvm_mmu_unprotect_page_virt(vcpu, cr2)) | 3780 | if (kvm_mmu_unprotect_page_virt(vcpu, cr2)) |
3780 | return EMULATE_DONE; | 3781 | goto done; |
3781 | if (!vcpu->mmio_needed) { | 3782 | if (!vcpu->mmio_needed) { |
3782 | kvm_report_emulation_failure(vcpu, "mmio"); | 3783 | kvm_report_emulation_failure(vcpu, "mmio"); |
3783 | return EMULATE_FAIL; | 3784 | return EMULATE_FAIL; |
@@ -3792,6 +3793,13 @@ int emulate_instruction(struct kvm_vcpu *vcpu, | |||
3792 | return EMULATE_DO_MMIO; | 3793 | return EMULATE_DO_MMIO; |
3793 | } | 3794 | } |
3794 | 3795 | ||
3796 | done: | ||
3797 | if (vcpu->arch.exception.pending) | ||
3798 | vcpu->arch.emulate_ctxt.restart = false; | ||
3799 | |||
3800 | if (vcpu->arch.emulate_ctxt.restart) | ||
3801 | goto restart; | ||
3802 | |||
3795 | return EMULATE_DONE; | 3803 | return EMULATE_DONE; |
3796 | } | 3804 | } |
3797 | EXPORT_SYMBOL_GPL(emulate_instruction); | 3805 | EXPORT_SYMBOL_GPL(emulate_instruction); |
@@ -4560,6 +4568,15 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
4560 | goto out; | 4568 | goto out; |
4561 | } | 4569 | } |
4562 | } | 4570 | } |
4571 | if (vcpu->arch.emulate_ctxt.restart) { | ||
4572 | vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
4573 | r = emulate_instruction(vcpu, 0, 0, EMULTYPE_NO_DECODE); | ||
4574 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); | ||
4575 | if (r == EMULATE_DO_MMIO) { | ||
4576 | r = 0; | ||
4577 | goto out; | ||
4578 | } | ||
4579 | } | ||
4563 | if (kvm_run->exit_reason == KVM_EXIT_HYPERCALL) | 4580 | if (kvm_run->exit_reason == KVM_EXIT_HYPERCALL) |
4564 | kvm_register_write(vcpu, VCPU_REGS_RAX, | 4581 | kvm_register_write(vcpu, VCPU_REGS_RAX, |
4565 | kvm_run->hypercall.ret); | 4582 | kvm_run->hypercall.ret); |