diff options
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r-- | drivers/kvm/x86_emulate.c | 70 |
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 | ||
68 | static u16 opcode_table[256] = { | 69 | static 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; |