repository: /home/avi/kvm/linux-2.6 branch: (no branch) commit 5d9b36eec8ca6abe03da91efdfc7b5861525bd43 Author: Laurent Vivier <[EMAIL PROTECTED]> Date: Tue Sep 18 11:27:37 2007 +0200
KVM: Call x86_decode_insn() only when needed Move emulate_ctxt to kvm_vcpu to keep emulate context when we exit from kvm module. Call x86_decode_insn() only when needed. Modify x86_emulate_insn() to not modify the context if it must be re-entered. Signed-off-by: Laurent Vivier <[EMAIL PROTECTED]> Signed-off-by: Avi Kivity <[EMAIL PROTECTED]> diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 1cde572..b7cd276 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h @@ -207,6 +207,8 @@ enum { VCPU_SREG_LDTR, }; +#include "x86_emulate.h" + struct kvm_pio_request { unsigned long count; int cur_count; @@ -380,6 +382,10 @@ struct kvm_vcpu { int cpuid_nent; struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES]; + + /* emulate context */ + + struct x86_emulate_ctxt emulate_ctxt; }; struct kvm_mem_alias { @@ -555,7 +561,7 @@ enum emulation_result { }; int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run, - unsigned long cr2, u16 error_code); + unsigned long cr2, u16 error_code, int no_decode); void kvm_report_emulation_failure(struct kvm_vcpu *cvpu, const char *context); void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address); void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address); diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index bb6004a..bc2d32d 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c @@ -1272,45 +1272,56 @@ struct x86_emulate_ops emulate_ops = { int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run, unsigned long cr2, - u16 error_code) + u16 error_code, + int no_decode) { - struct x86_emulate_ctxt emulate_ctxt; - int r; - int cs_db, cs_l; + int r = 0; vcpu->mmio_fault_cr2 = cr2; kvm_x86_ops->cache_regs(vcpu); - kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); - - emulate_ctxt.vcpu = vcpu; - emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu); - emulate_ctxt.cr2 = cr2; - emulate_ctxt.mode = (emulate_ctxt.eflags & X86_EFLAGS_VM) - ? X86EMUL_MODE_REAL : cs_l - ? X86EMUL_MODE_PROT64 : cs_db - ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; - - if (emulate_ctxt.mode == X86EMUL_MODE_PROT64) { - emulate_ctxt.cs_base = 0; - emulate_ctxt.ds_base = 0; - emulate_ctxt.es_base = 0; - emulate_ctxt.ss_base = 0; - } else { - emulate_ctxt.cs_base = get_segment_base(vcpu, VCPU_SREG_CS); - emulate_ctxt.ds_base = get_segment_base(vcpu, VCPU_SREG_DS); - emulate_ctxt.es_base = get_segment_base(vcpu, VCPU_SREG_ES); - emulate_ctxt.ss_base = get_segment_base(vcpu, VCPU_SREG_SS); - } - - emulate_ctxt.gs_base = get_segment_base(vcpu, VCPU_SREG_GS); - emulate_ctxt.fs_base = get_segment_base(vcpu, VCPU_SREG_FS); - vcpu->mmio_is_write = 0; vcpu->pio.string = 0; - r = x86_decode_insn(&emulate_ctxt, &emulate_ops); + + if (!no_decode) { + int cs_db, cs_l; + kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); + + vcpu->emulate_ctxt.vcpu = vcpu; + vcpu->emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu); + vcpu->emulate_ctxt.cr2 = cr2; + vcpu->emulate_ctxt.mode = + (vcpu->emulate_ctxt.eflags & X86_EFLAGS_VM) + ? X86EMUL_MODE_REAL : cs_l + ? X86EMUL_MODE_PROT64 : cs_db + ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; + + if (vcpu->emulate_ctxt.mode == X86EMUL_MODE_PROT64) { + vcpu->emulate_ctxt.cs_base = 0; + vcpu->emulate_ctxt.ds_base = 0; + vcpu->emulate_ctxt.es_base = 0; + vcpu->emulate_ctxt.ss_base = 0; + } else { + vcpu->emulate_ctxt.cs_base = + get_segment_base(vcpu, VCPU_SREG_CS); + vcpu->emulate_ctxt.ds_base = + get_segment_base(vcpu, VCPU_SREG_DS); + vcpu->emulate_ctxt.es_base = + get_segment_base(vcpu, VCPU_SREG_ES); + vcpu->emulate_ctxt.ss_base = + get_segment_base(vcpu, VCPU_SREG_SS); + } + + vcpu->emulate_ctxt.gs_base = + get_segment_base(vcpu, VCPU_SREG_GS); + vcpu->emulate_ctxt.fs_base = + get_segment_base(vcpu, VCPU_SREG_FS); + + r = x86_decode_insn(&vcpu->emulate_ctxt, &emulate_ops); + } + if (r == 0) - r = x86_emulate_insn(&emulate_ctxt, &emulate_ops); + r = x86_emulate_insn(&vcpu->emulate_ctxt, &emulate_ops); if (vcpu->pio.string) return EMULATE_DO_MMIO; @@ -1334,7 +1345,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu, } kvm_x86_ops->decache_regs(vcpu); - kvm_x86_ops->set_rflags(vcpu, emulate_ctxt.eflags); + kvm_x86_ops->set_rflags(vcpu, vcpu->emulate_ctxt.eflags); if (vcpu->mmio_is_write) { vcpu->mmio_needed = 0; @@ -2065,7 +2076,7 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) vcpu->mmio_read_completed = 1; vcpu->mmio_needed = 0; r = emulate_instruction(vcpu, kvm_run, - vcpu->mmio_fault_cr2, 0); + vcpu->mmio_fault_cr2, 0, 1); if (r == EMULATE_DO_MMIO) { /* * Read-modify-write. Back to userspace. diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index ecb8f06..a533088 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c @@ -951,7 +951,7 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) return 1; } er = emulate_instruction(&svm->vcpu, kvm_run, fault_address, - error_code); + error_code, 0); mutex_unlock(&kvm->lock); switch (er) { @@ -975,7 +975,7 @@ static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) { int er; - er = emulate_instruction(&svm->vcpu, kvm_run, 0, 0); + er = emulate_instruction(&svm->vcpu, kvm_run, 0, 0, 0); if (er != EMULATE_DONE) inject_ud(&svm->vcpu); @@ -1018,7 +1018,8 @@ static int io_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) string = (io_info & SVM_IOIO_STR_MASK) != 0; if (string) { - if (emulate_instruction(&svm->vcpu, kvm_run, 0, 0) == EMULATE_DO_MMIO) + if (emulate_instruction(&svm->vcpu, + kvm_run, 0, 0, 0) == EMULATE_DO_MMIO) return 0; return 1; } @@ -1077,7 +1078,7 @@ static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) static int emulate_on_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) { - if (emulate_instruction(&svm->vcpu, NULL, 0, 0) != EMULATE_DONE) + if (emulate_instruction(&svm->vcpu, NULL, 0, 0, 0) != EMULATE_DONE) pr_unimpl(&svm->vcpu, "%s: failed\n", __FUNCTION__); return 1; } diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index a71564c..2a28bc1 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c @@ -1748,7 +1748,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu, * Cause the #SS fault with 0 error code in VM86 mode. */ if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0) - if (emulate_instruction(vcpu, NULL, 0, 0) == EMULATE_DONE) + if (emulate_instruction(vcpu, NULL, 0, 0, 0) == EMULATE_DONE) return 1; return 0; } @@ -1787,7 +1787,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) } if (is_invalid_opcode(intr_info)) { - er = emulate_instruction(vcpu, kvm_run, 0, 0); + er = emulate_instruction(vcpu, kvm_run, 0, 0, 0); if (er != EMULATE_DONE) vmx_inject_ud(vcpu); @@ -1812,7 +1812,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) return 1; } - er = emulate_instruction(vcpu, kvm_run, cr2, error_code); + er = emulate_instruction(vcpu, kvm_run, cr2, error_code, 0); mutex_unlock(&vcpu->kvm->lock); switch (er) { @@ -1873,7 +1873,8 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) string = (exit_qualification & 16) != 0; if (string) { - if (emulate_instruction(vcpu, kvm_run, 0, 0) == EMULATE_DO_MMIO) + if (emulate_instruction(vcpu, + kvm_run, 0, 0, 0) == EMULATE_DO_MMIO) return 0; return 1; } diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index c5102d9..3a1c712 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c @@ -904,10 +904,14 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) unsigned long cr2 = ctxt->cr2; int no_wb = 0; u64 msr_data; + unsigned long saved_rcx = 0, saved_eip = 0; unsigned long _eflags = ctxt->eflags; struct decode_cache *c = &ctxt->decode; int rc = 0; + if ((c->d & ModRM) && (c->modrm_mod != 3)) + ctxt->cr2 = c->modrm_ea; + if (c->src.type == OP_MEM) { c->src.ptr = (unsigned long *)ctxt->cr2; c->src.val = 0; @@ -1300,8 +1304,13 @@ special_insn: pop_instruction: if ((rc = ops->read_std(register_address(ctxt->ss_base, c->regs[VCPU_REGS_RSP]), c->dst.ptr, - c->op_bytes, ctxt->vcpu)) != 0) + c->op_bytes, ctxt->vcpu)) != 0) { + if (c->rep_prefix) { + c->regs[VCPU_REGS_RCX] = saved_rcx; + c->eip = saved_eip; + } goto done; + } register_address_increment(c->regs[VCPU_REGS_RSP], c->op_bytes); @@ -1362,6 +1371,8 @@ special_insn: ctxt->vcpu->rip = c->eip; goto done; } + saved_rcx = c->regs[VCPU_REGS_RCX]; + saved_eip = c->eip; c->regs[VCPU_REGS_RCX]--; c->eip = ctxt->vcpu->rip; } @@ -1377,8 +1388,13 @@ special_insn: ctxt->ds_base, c->regs[VCPU_REGS_RSI]), &c->dst.val, - c->dst.bytes, ctxt->vcpu)) != 0) + c->dst.bytes, ctxt->vcpu)) != 0) { + if (c->rep_prefix) { + c->regs[VCPU_REGS_RCX] = saved_rcx; + c->eip = saved_eip; + } goto done; + } register_address_increment(c->regs[VCPU_REGS_RSI], (_eflags & EFLG_DF) ? -c->dst.bytes : c->dst.bytes); @@ -1404,8 +1420,13 @@ special_insn: c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX]; if ((rc = ops->read_emulated(cr2, &c->dst.val, c->dst.bytes, - ctxt->vcpu)) != 0) + ctxt->vcpu)) != 0) { + if (c->rep_prefix) { + c->regs[VCPU_REGS_RCX] = saved_rcx; + c->eip = saved_eip; + } goto done; + } register_address_increment(c->regs[VCPU_REGS_RSI], (_eflags & EFLG_DF) ? -c->dst.bytes : c->dst.bytes); ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ kvm-commits mailing list kvm-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-commits