diff options
author | Laurent Vivier <Laurent.Vivier@bull.net> | 2007-09-18 11:27:37 +0200 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 17:52:47 +0200 |
commit | 3427318fd2244737a466a06a93c5fe579852f871 (patch) | |
tree | 7c6760dbbdd067498c470e6e4f711e5baeef491c /drivers/kvm/x86_emulate.c | |
parent | 1be3aa47182e94944e57b176a5c4ee4e74f1ce33 (diff) |
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 <Laurent.Vivier@bull.net>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r-- | drivers/kvm/x86_emulate.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index c191093982d..dc9d2a870fb 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c @@ -913,10 +913,19 @@ 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_eip = 0; unsigned long _eflags = ctxt->eflags; struct decode_cache *c = &ctxt->decode; int rc = 0; + /* Shadow copy of register state. Committed on successful emulation. + * NOTE: we can copy them from vcpu as x86_decode_insn() doesn't + * modify them. + */ + + memcpy(c->regs, ctxt->vcpu->regs, sizeof c->regs); + saved_eip = c->eip; + if ((c->d & ModRM) && (c->modrm_mod != 3)) cr2 = c->modrm_ea; @@ -1250,7 +1259,11 @@ writeback: ctxt->vcpu->rip = c->eip; done: - return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; + if (rc == X86EMUL_UNHANDLEABLE) { + c->eip = saved_eip; + return -1; + } + return 0; special_insn: if (c->twobyte) @@ -1305,8 +1318,10 @@ push: register_address(ctxt->es_base, c->regs[VCPU_REGS_RDI]), c->rep_prefix, - c->regs[VCPU_REGS_RDX]) == 0) + c->regs[VCPU_REGS_RDX]) == 0) { + c->eip = saved_eip; return -1; + } return 0; case 0x6e: /* outsb */ case 0x6f: /* outsw/outsd */ @@ -1321,8 +1336,10 @@ push: ctxt->ds_base, c->regs[VCPU_REGS_RSI]), c->rep_prefix, - c->regs[VCPU_REGS_RDX]) == 0) + c->regs[VCPU_REGS_RDX]) == 0) { + c->eip = saved_eip; return -1; + } return 0; case 0x70 ... 0x7f: /* jcc (short) */ { int rel = insn_fetch(s8, 1, c->eip); @@ -1711,5 +1728,6 @@ twobyte_special_insn: cannot_emulate: DPRINTF("Cannot emulate %02x\n", c->b); + c->eip = saved_eip; return -1; } |