aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-11-27 12:05:37 -0500
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:53:15 -0500
commitb9fa9d6bc6ac617170c4cf21ca764eb187618c0d (patch)
tree291927725c16a16f743f75e84b742f61d8378b07
parent51e296258cba41759ff0de5da110d8d52675ee67 (diff)
KVM: x86 emulator: Move rep processing before instruction execution
Currently rep processing is handled somewhere in the middle of instruction processing. Move it to a sensible place. Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--drivers/kvm/x86_emulate.c70
1 files changed, 36 insertions, 34 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 84e536603f5a..53377f0b202e 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -64,6 +64,7 @@
64#define Mov (1<<7) 64#define Mov (1<<7)
65#define BitOp (1<<8) 65#define BitOp (1<<8)
66#define MemAbs (1<<9) /* Memory operand is absolute displacement */ 66#define MemAbs (1<<9) /* Memory operand is absolute displacement */
67#define String (1<<10) /* String instruction (rep capable) */
67 68
68static u16 opcode_table[256] = { 69static u16 opcode_table[256] = {
69 /* 0x00 - 0x07 */ 70 /* 0x00 - 0x07 */
@@ -133,12 +134,12 @@ static u16 opcode_table[256] = {
133 /* 0xA0 - 0xA7 */ 134 /* 0xA0 - 0xA7 */
134 ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs, 135 ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs,
135 ByteOp | DstMem | SrcReg | Mov | MemAbs, DstMem | SrcReg | Mov | MemAbs, 136 ByteOp | DstMem | SrcReg | Mov | MemAbs, DstMem | SrcReg | Mov | MemAbs,
136 ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, 137 ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String,
137 ByteOp | ImplicitOps, ImplicitOps, 138 ByteOp | ImplicitOps | String, ImplicitOps | String,
138 /* 0xA8 - 0xAF */ 139 /* 0xA8 - 0xAF */
139 0, 0, ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, 140 0, 0, ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String,
140 ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, 141 ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String,
141 ByteOp | ImplicitOps, ImplicitOps, 142 ByteOp | ImplicitOps | String, ImplicitOps | String,
142 /* 0xB0 - 0xBF */ 143 /* 0xB0 - 0xBF */
143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144 /* 0xC0 - 0xC7 */ 145 /* 0xC0 - 0xC7 */
@@ -1228,6 +1229,36 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1228 if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs)) 1229 if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs))
1229 memop = c->modrm_ea; 1230 memop = c->modrm_ea;
1230 1231
1232 if (c->rep_prefix && (c->d & String)) {
1233 /* All REP prefixes have the same first termination condition */
1234 if (c->regs[VCPU_REGS_RCX] == 0) {
1235 ctxt->vcpu->rip = c->eip;
1236 goto done;
1237 }
1238 /* The second termination condition only applies for REPE
1239 * and REPNE. Test if the repeat string operation prefix is
1240 * REPE/REPZ or REPNE/REPNZ and if it's the case it tests the
1241 * corresponding termination condition according to:
1242 * - if REPE/REPZ and ZF = 0 then done
1243 * - if REPNE/REPNZ and ZF = 1 then done
1244 */
1245 if ((c->b == 0xa6) || (c->b == 0xa7) ||
1246 (c->b == 0xae) || (c->b == 0xaf)) {
1247 if ((c->rep_prefix == REPE_PREFIX) &&
1248 ((ctxt->eflags & EFLG_ZF) == 0)) {
1249 ctxt->vcpu->rip = c->eip;
1250 goto done;
1251 }
1252 if ((c->rep_prefix == REPNE_PREFIX) &&
1253 ((ctxt->eflags & EFLG_ZF) == EFLG_ZF)) {
1254 ctxt->vcpu->rip = c->eip;
1255 goto done;
1256 }
1257 }
1258 c->regs[VCPU_REGS_RCX]--;
1259 c->eip = ctxt->vcpu->rip;
1260 }
1261
1231 if (c->src.type == OP_MEM) { 1262 if (c->src.type == OP_MEM) {
1232 c->src.ptr = (unsigned long *)memop; 1263 c->src.ptr = (unsigned long *)memop;
1233 c->src.val = 0; 1264 c->src.val = 0;
@@ -1534,35 +1565,6 @@ special_insn:
1534 c->dst.type = OP_NONE; /* Disable writeback. */ 1565 c->dst.type = OP_NONE; /* Disable writeback. */
1535 break; 1566 break;
1536 } 1567 }
1537 if (c->rep_prefix) {
1538 /* All REP prefixes have the same first termination condition */
1539 if (c->regs[VCPU_REGS_RCX] == 0) {
1540 ctxt->vcpu->rip = c->eip;
1541 goto done;
1542 }
1543 /* The second termination condition only applies for REPE
1544 * and REPNE. Test if the repeat string operation prefix is
1545 * REPE/REPZ or REPNE/REPNZ and if it's the case it tests the
1546 * corresponding termination condition according to:
1547 * - if REPE/REPZ and ZF = 0 then done
1548 * - if REPNE/REPNZ and ZF = 1 then done
1549 */
1550 if ((c->b == 0xa6) || (c->b == 0xa7) ||
1551 (c->b == 0xae) || (c->b == 0xaf)) {
1552 if ((c->rep_prefix == REPE_PREFIX) &&
1553 ((ctxt->eflags & EFLG_ZF) == 0)) {
1554 ctxt->vcpu->rip = c->eip;
1555 goto done;
1556 }
1557 if ((c->rep_prefix == REPNE_PREFIX) &&
1558 ((ctxt->eflags & EFLG_ZF) == EFLG_ZF)) {
1559 ctxt->vcpu->rip = c->eip;
1560 goto done;
1561 }
1562 }
1563 c->regs[VCPU_REGS_RCX]--;
1564 c->eip = ctxt->vcpu->rip;
1565 }
1566 switch (c->b) { 1568 switch (c->b) {
1567 case 0xa4 ... 0xa5: /* movs */ 1569 case 0xa4 ... 0xa5: /* movs */
1568 c->dst.type = OP_MEM; 1570 c->dst.type = OP_MEM;