diff options
author | Laurent Vivier <Laurent.Vivier@bull.net> | 2007-09-18 05:27:37 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:52:47 -0500 |
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) | |||
913 | unsigned long cr2 = ctxt->cr2; | 913 | unsigned long cr2 = ctxt->cr2; |
914 | int no_wb = 0; | 914 | int no_wb = 0; |
915 | u64 msr_data; | 915 | u64 msr_data; |
916 | unsigned long saved_eip = 0; | ||
916 | unsigned long _eflags = ctxt->eflags; | 917 | unsigned long _eflags = ctxt->eflags; |
917 | struct decode_cache *c = &ctxt->decode; | 918 | struct decode_cache *c = &ctxt->decode; |
918 | int rc = 0; | 919 | int rc = 0; |
919 | 920 | ||
921 | /* Shadow copy of register state. Committed on successful emulation. | ||
922 | * NOTE: we can copy them from vcpu as x86_decode_insn() doesn't | ||
923 | * modify them. | ||
924 | */ | ||
925 | |||
926 | memcpy(c->regs, ctxt->vcpu->regs, sizeof c->regs); | ||
927 | saved_eip = c->eip; | ||
928 | |||
920 | if ((c->d & ModRM) && (c->modrm_mod != 3)) | 929 | if ((c->d & ModRM) && (c->modrm_mod != 3)) |
921 | cr2 = c->modrm_ea; | 930 | cr2 = c->modrm_ea; |
922 | 931 | ||
@@ -1250,7 +1259,11 @@ writeback: | |||
1250 | ctxt->vcpu->rip = c->eip; | 1259 | ctxt->vcpu->rip = c->eip; |
1251 | 1260 | ||
1252 | done: | 1261 | done: |
1253 | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; | 1262 | if (rc == X86EMUL_UNHANDLEABLE) { |
1263 | c->eip = saved_eip; | ||
1264 | return -1; | ||
1265 | } | ||
1266 | return 0; | ||
1254 | 1267 | ||
1255 | special_insn: | 1268 | special_insn: |
1256 | if (c->twobyte) | 1269 | if (c->twobyte) |
@@ -1305,8 +1318,10 @@ push: | |||
1305 | register_address(ctxt->es_base, | 1318 | register_address(ctxt->es_base, |
1306 | c->regs[VCPU_REGS_RDI]), | 1319 | c->regs[VCPU_REGS_RDI]), |
1307 | c->rep_prefix, | 1320 | c->rep_prefix, |
1308 | c->regs[VCPU_REGS_RDX]) == 0) | 1321 | c->regs[VCPU_REGS_RDX]) == 0) { |
1322 | c->eip = saved_eip; | ||
1309 | return -1; | 1323 | return -1; |
1324 | } | ||
1310 | return 0; | 1325 | return 0; |
1311 | case 0x6e: /* outsb */ | 1326 | case 0x6e: /* outsb */ |
1312 | case 0x6f: /* outsw/outsd */ | 1327 | case 0x6f: /* outsw/outsd */ |
@@ -1321,8 +1336,10 @@ push: | |||
1321 | ctxt->ds_base, | 1336 | ctxt->ds_base, |
1322 | c->regs[VCPU_REGS_RSI]), | 1337 | c->regs[VCPU_REGS_RSI]), |
1323 | c->rep_prefix, | 1338 | c->rep_prefix, |
1324 | c->regs[VCPU_REGS_RDX]) == 0) | 1339 | c->regs[VCPU_REGS_RDX]) == 0) { |
1340 | c->eip = saved_eip; | ||
1325 | return -1; | 1341 | return -1; |
1342 | } | ||
1326 | return 0; | 1343 | return 0; |
1327 | case 0x70 ... 0x7f: /* jcc (short) */ { | 1344 | case 0x70 ... 0x7f: /* jcc (short) */ { |
1328 | int rel = insn_fetch(s8, 1, c->eip); | 1345 | int rel = insn_fetch(s8, 1, c->eip); |
@@ -1711,5 +1728,6 @@ twobyte_special_insn: | |||
1711 | 1728 | ||
1712 | cannot_emulate: | 1729 | cannot_emulate: |
1713 | DPRINTF("Cannot emulate %02x\n", c->b); | 1730 | DPRINTF("Cannot emulate %02x\n", c->b); |
1731 | c->eip = saved_eip; | ||
1714 | return -1; | 1732 | return -1; |
1715 | } | 1733 | } |