diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-03-18 09:20:20 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-05-17 05:16:20 -0400 |
commit | 69f55cb11e8d789433d111ac3a0f60be37a1ae01 (patch) | |
tree | bdcaba6b5676dc9d6205b5d51a609e2b3b4d2aa0 /arch/x86/kvm/emulate.c | |
parent | ceffb4597253b2420d2f171d8b1cdf2cd3137989 (diff) |
KVM: x86 emulator: populate OP_MEM operand during decoding.
All struct operand fields are initialized during decoding for all
operand types except OP_MEM, but there is no reason for that. Move
OP_MEM operand initialization into decoding stage for consistency.
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.c | 66 |
1 files changed, 29 insertions, 37 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 8225ec26efed..0eed6839619f 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -1057,6 +1057,10 @@ done_prefixes: | |||
1057 | 1057 | ||
1058 | if (c->ad_bytes != 8) | 1058 | if (c->ad_bytes != 8) |
1059 | c->modrm_ea = (u32)c->modrm_ea; | 1059 | c->modrm_ea = (u32)c->modrm_ea; |
1060 | |||
1061 | if (c->rip_relative) | ||
1062 | c->modrm_ea += c->eip; | ||
1063 | |||
1060 | /* | 1064 | /* |
1061 | * Decode and fetch the source operand: register, memory | 1065 | * Decode and fetch the source operand: register, memory |
1062 | * or immediate. | 1066 | * or immediate. |
@@ -1091,6 +1095,8 @@ done_prefixes: | |||
1091 | break; | 1095 | break; |
1092 | } | 1096 | } |
1093 | c->src.type = OP_MEM; | 1097 | c->src.type = OP_MEM; |
1098 | c->src.ptr = (unsigned long *)c->modrm_ea; | ||
1099 | c->src.val = 0; | ||
1094 | break; | 1100 | break; |
1095 | case SrcImm: | 1101 | case SrcImm: |
1096 | case SrcImmU: | 1102 | case SrcImmU: |
@@ -1169,8 +1175,10 @@ done_prefixes: | |||
1169 | c->src2.val = 1; | 1175 | c->src2.val = 1; |
1170 | break; | 1176 | break; |
1171 | case Src2Mem16: | 1177 | case Src2Mem16: |
1172 | c->src2.bytes = 2; | ||
1173 | c->src2.type = OP_MEM; | 1178 | c->src2.type = OP_MEM; |
1179 | c->src2.bytes = 2; | ||
1180 | c->src2.ptr = (unsigned long *)(c->modrm_ea + c->src.bytes); | ||
1181 | c->src2.val = 0; | ||
1174 | break; | 1182 | break; |
1175 | } | 1183 | } |
1176 | 1184 | ||
@@ -1192,6 +1200,15 @@ done_prefixes: | |||
1192 | break; | 1200 | break; |
1193 | } | 1201 | } |
1194 | c->dst.type = OP_MEM; | 1202 | c->dst.type = OP_MEM; |
1203 | c->dst.ptr = (unsigned long *)c->modrm_ea; | ||
1204 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | ||
1205 | c->dst.val = 0; | ||
1206 | if (c->d & BitOp) { | ||
1207 | unsigned long mask = ~(c->dst.bytes * 8 - 1); | ||
1208 | |||
1209 | c->dst.ptr = (void *)c->dst.ptr + | ||
1210 | (c->src.val & mask) / 8; | ||
1211 | } | ||
1195 | break; | 1212 | break; |
1196 | case DstAcc: | 1213 | case DstAcc: |
1197 | c->dst.type = OP_REG; | 1214 | c->dst.type = OP_REG; |
@@ -1215,9 +1232,6 @@ done_prefixes: | |||
1215 | break; | 1232 | break; |
1216 | } | 1233 | } |
1217 | 1234 | ||
1218 | if (c->rip_relative) | ||
1219 | c->modrm_ea += c->eip; | ||
1220 | |||
1221 | done: | 1235 | done: |
1222 | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; | 1236 | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; |
1223 | } | 1237 | } |
@@ -1638,14 +1652,13 @@ static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt, | |||
1638 | } | 1652 | } |
1639 | 1653 | ||
1640 | static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, | 1654 | static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, |
1641 | struct x86_emulate_ops *ops, | 1655 | struct x86_emulate_ops *ops) |
1642 | unsigned long memop) | ||
1643 | { | 1656 | { |
1644 | struct decode_cache *c = &ctxt->decode; | 1657 | struct decode_cache *c = &ctxt->decode; |
1645 | u64 old, new; | 1658 | u64 old, new; |
1646 | int rc; | 1659 | int rc; |
1647 | 1660 | ||
1648 | rc = ops->read_emulated(memop, &old, 8, ctxt->vcpu); | 1661 | rc = ops->read_emulated(c->modrm_ea, &old, 8, ctxt->vcpu); |
1649 | if (rc != X86EMUL_CONTINUE) | 1662 | if (rc != X86EMUL_CONTINUE) |
1650 | return rc; | 1663 | return rc; |
1651 | 1664 | ||
@@ -1660,7 +1673,7 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, | |||
1660 | new = ((u64)c->regs[VCPU_REGS_RCX] << 32) | | 1673 | new = ((u64)c->regs[VCPU_REGS_RCX] << 32) | |
1661 | (u32) c->regs[VCPU_REGS_RBX]; | 1674 | (u32) c->regs[VCPU_REGS_RBX]; |
1662 | 1675 | ||
1663 | rc = ops->cmpxchg_emulated(memop, &old, &new, 8, ctxt->vcpu); | 1676 | rc = ops->cmpxchg_emulated(c->modrm_ea, &old, &new, 8, ctxt->vcpu); |
1664 | if (rc != X86EMUL_CONTINUE) | 1677 | if (rc != X86EMUL_CONTINUE) |
1665 | return rc; | 1678 | return rc; |
1666 | ctxt->eflags |= EFLG_ZF; | 1679 | ctxt->eflags |= EFLG_ZF; |
@@ -2382,7 +2395,6 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt, | |||
2382 | int | 2395 | int |
2383 | x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | 2396 | x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) |
2384 | { | 2397 | { |
2385 | unsigned long memop = 0; | ||
2386 | u64 msr_data; | 2398 | u64 msr_data; |
2387 | unsigned long saved_eip = 0; | 2399 | unsigned long saved_eip = 0; |
2388 | struct decode_cache *c = &ctxt->decode; | 2400 | struct decode_cache *c = &ctxt->decode; |
@@ -2417,9 +2429,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
2417 | goto done; | 2429 | goto done; |
2418 | } | 2430 | } |
2419 | 2431 | ||
2420 | if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs)) | ||
2421 | memop = c->modrm_ea; | ||
2422 | |||
2423 | if (c->rep_prefix && (c->d & String)) { | 2432 | if (c->rep_prefix && (c->d & String)) { |
2424 | /* All REP prefixes have the same first termination condition */ | 2433 | /* All REP prefixes have the same first termination condition */ |
2425 | if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) { | 2434 | if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) { |
@@ -2451,8 +2460,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
2451 | } | 2460 | } |
2452 | 2461 | ||
2453 | if (c->src.type == OP_MEM) { | 2462 | if (c->src.type == OP_MEM) { |
2454 | c->src.ptr = (unsigned long *)memop; | ||
2455 | c->src.val = 0; | ||
2456 | rc = ops->read_emulated((unsigned long)c->src.ptr, | 2463 | rc = ops->read_emulated((unsigned long)c->src.ptr, |
2457 | &c->src.val, | 2464 | &c->src.val, |
2458 | c->src.bytes, | 2465 | c->src.bytes, |
@@ -2463,8 +2470,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
2463 | } | 2470 | } |
2464 | 2471 | ||
2465 | if (c->src2.type == OP_MEM) { | 2472 | if (c->src2.type == OP_MEM) { |
2466 | c->src2.ptr = (unsigned long *)(memop + c->src.bytes); | ||
2467 | c->src2.val = 0; | ||
2468 | rc = ops->read_emulated((unsigned long)c->src2.ptr, | 2473 | rc = ops->read_emulated((unsigned long)c->src2.ptr, |
2469 | &c->src2.val, | 2474 | &c->src2.val, |
2470 | c->src2.bytes, | 2475 | c->src2.bytes, |
@@ -2477,25 +2482,12 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
2477 | goto special_insn; | 2482 | goto special_insn; |
2478 | 2483 | ||
2479 | 2484 | ||
2480 | if (c->dst.type == OP_MEM) { | 2485 | if ((c->dst.type == OP_MEM) && !(c->d & Mov)) { |
2481 | c->dst.ptr = (unsigned long *)memop; | 2486 | /* optimisation - avoid slow emulated read if Mov */ |
2482 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | 2487 | rc = ops->read_emulated((unsigned long)c->dst.ptr, &c->dst.val, |
2483 | c->dst.val = 0; | 2488 | c->dst.bytes, ctxt->vcpu); |
2484 | if (c->d & BitOp) { | 2489 | if (rc != X86EMUL_CONTINUE) |
2485 | unsigned long mask = ~(c->dst.bytes * 8 - 1); | 2490 | goto done; |
2486 | |||
2487 | c->dst.ptr = (void *)c->dst.ptr + | ||
2488 | (c->src.val & mask) / 8; | ||
2489 | } | ||
2490 | if (!(c->d & Mov)) { | ||
2491 | /* optimisation - avoid slow emulated read */ | ||
2492 | rc = ops->read_emulated((unsigned long)c->dst.ptr, | ||
2493 | &c->dst.val, | ||
2494 | c->dst.bytes, | ||
2495 | ctxt->vcpu); | ||
2496 | if (rc != X86EMUL_CONTINUE) | ||
2497 | goto done; | ||
2498 | } | ||
2499 | } | 2491 | } |
2500 | c->dst.orig_val = c->dst.val; | 2492 | c->dst.orig_val = c->dst.val; |
2501 | 2493 | ||
@@ -3062,7 +3054,7 @@ twobyte_insn: | |||
3062 | kvm_queue_exception(ctxt->vcpu, UD_VECTOR); | 3054 | kvm_queue_exception(ctxt->vcpu, UD_VECTOR); |
3063 | goto done; | 3055 | goto done; |
3064 | case 7: /* invlpg*/ | 3056 | case 7: /* invlpg*/ |
3065 | emulate_invlpg(ctxt->vcpu, memop); | 3057 | emulate_invlpg(ctxt->vcpu, c->modrm_ea); |
3066 | /* Disable writeback. */ | 3058 | /* Disable writeback. */ |
3067 | c->dst.type = OP_NONE; | 3059 | c->dst.type = OP_NONE; |
3068 | break; | 3060 | break; |
@@ -3263,7 +3255,7 @@ twobyte_insn: | |||
3263 | (u64) c->src.val; | 3255 | (u64) c->src.val; |
3264 | break; | 3256 | break; |
3265 | case 0xc7: /* Grp9 (cmpxchg8b) */ | 3257 | case 0xc7: /* Grp9 (cmpxchg8b) */ |
3266 | rc = emulate_grp9(ctxt, ops, memop); | 3258 | rc = emulate_grp9(ctxt, ops); |
3267 | if (rc != X86EMUL_CONTINUE) | 3259 | if (rc != X86EMUL_CONTINUE) |
3268 | goto done; | 3260 | goto done; |
3269 | c->dst.type = OP_NONE; | 3261 | c->dst.type = OP_NONE; |