aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2010-03-18 09:20:20 -0400
committerAvi Kivity <avi@redhat.com>2010-05-17 05:16:20 -0400
commit69f55cb11e8d789433d111ac3a0f60be37a1ae01 (patch)
treebdcaba6b5676dc9d6205b5d51a609e2b3b4d2aa0 /arch/x86/kvm/emulate.c
parentceffb4597253b2420d2f171d8b1cdf2cd3137989 (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.c66
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
1221done: 1235done:
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
1640static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, 1654static 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,
2382int 2395int
2383x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) 2396x86_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;