aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/kvm')
-rw-r--r--drivers/kvm/x86_emulate.c99
1 files changed, 49 insertions, 50 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 18c2b2cea608..e4ce34c52ba1 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -978,19 +978,8 @@ push:
978 dst.val = src.val; 978 dst.val = src.val;
979 lock_prefix = 1; 979 lock_prefix = 1;
980 break; 980 break;
981 case 0xa0 ... 0xa1: /* mov */
982 dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
983 dst.val = src.val;
984 _eip += ad_bytes; /* skip src displacement */
985 break;
986 case 0xa2 ... 0xa3: /* mov */
987 dst.val = (unsigned long)_regs[VCPU_REGS_RAX];
988 _eip += ad_bytes; /* skip dst displacement */
989 break;
990 case 0x88 ... 0x8b: /* mov */ 981 case 0x88 ... 0x8b: /* mov */
991 case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ 982 goto mov;
992 dst.val = src.val;
993 break;
994 case 0x8f: /* pop (sole member of Grp1a) */ 983 case 0x8f: /* pop (sole member of Grp1a) */
995 /* 64-bit mode: POP always pops a 64-bit operand. */ 984 /* 64-bit mode: POP always pops a 64-bit operand. */
996 if (mode == X86EMUL_MODE_PROT64) 985 if (mode == X86EMUL_MODE_PROT64)
@@ -1001,6 +990,15 @@ push:
1001 goto done; 990 goto done;
1002 register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes); 991 register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes);
1003 break; 992 break;
993 case 0xa0 ... 0xa1: /* mov */
994 dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
995 dst.val = src.val;
996 _eip += ad_bytes; /* skip src displacement */
997 break;
998 case 0xa2 ... 0xa3: /* mov */
999 dst.val = (unsigned long)_regs[VCPU_REGS_RAX];
1000 _eip += ad_bytes; /* skip dst displacement */
1001 break;
1004 case 0xc0 ... 0xc1: 1002 case 0xc0 ... 0xc1:
1005 grp2: /* Grp2 */ 1003 grp2: /* Grp2 */
1006 switch (modrm_reg) { 1004 switch (modrm_reg) {
@@ -1028,6 +1026,10 @@ push:
1028 break; 1026 break;
1029 } 1027 }
1030 break; 1028 break;
1029 case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
1030 mov:
1031 dst.val = src.val;
1032 break;
1031 case 0xd0 ... 0xd1: /* Grp2 */ 1033 case 0xd0 ... 0xd1: /* Grp2 */
1032 src.val = 1; 1034 src.val = 1;
1033 goto grp2; 1035 goto grp2;
@@ -1186,6 +1188,17 @@ special_insn:
1186 dst.ptr = (void *) register_address( 1188 dst.ptr = (void *) register_address(
1187 ctxt->ss_base, _regs[VCPU_REGS_RSP]); 1189 ctxt->ss_base, _regs[VCPU_REGS_RSP]);
1188 break; 1190 break;
1191 case 0x58 ... 0x5f: /* pop reg */
1192 dst.ptr = (unsigned long *)&_regs[b & 0x7];
1193 pop_instruction:
1194 if ((rc = ops->read_std(register_address(ctxt->ss_base,
1195 _regs[VCPU_REGS_RSP]), dst.ptr, op_bytes, ctxt->vcpu))
1196 != 0)
1197 goto done;
1198
1199 register_address_increment(_regs[VCPU_REGS_RSP], op_bytes);
1200 no_wb = 1; /* Disable writeback. */
1201 break;
1189 case 0x6c: /* insb */ 1202 case 0x6c: /* insb */
1190 case 0x6d: /* insw/insd */ 1203 case 0x6d: /* insw/insd */
1191 if (kvm_emulate_pio_string(ctxt->vcpu, NULL, 1204 if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
@@ -1217,12 +1230,15 @@ special_insn:
1217 ) == 0) 1230 ) == 0)
1218 return -1; 1231 return -1;
1219 return 0; 1232 return 0;
1220
1221 case 0x9c: /* pushf */ 1233 case 0x9c: /* pushf */
1222 src.val = (unsigned long) _eflags; 1234 src.val = (unsigned long) _eflags;
1223 goto push; 1235 goto push;
1224 break; 1236 case 0xc3: /* ret */
1225 1237 dst.ptr = &_eip;
1238 goto pop_instruction;
1239 case 0xf4: /* hlt */
1240 ctxt->vcpu->halt_request = 1;
1241 goto done;
1226 } 1242 }
1227 if (rep_prefix) { 1243 if (rep_prefix) {
1228 if (_regs[VCPU_REGS_RCX] == 0) { 1244 if (_regs[VCPU_REGS_RCX] == 0) {
@@ -1271,24 +1287,7 @@ special_insn:
1271 case 0xae ... 0xaf: /* scas */ 1287 case 0xae ... 0xaf: /* scas */
1272 DPRINTF("Urk! I don't handle SCAS.\n"); 1288 DPRINTF("Urk! I don't handle SCAS.\n");
1273 goto cannot_emulate; 1289 goto cannot_emulate;
1274 case 0xf4: /* hlt */
1275 ctxt->vcpu->halt_request = 1;
1276 goto done;
1277 case 0xc3: /* ret */
1278 dst.ptr = &_eip;
1279 goto pop_instruction;
1280 case 0x58 ... 0x5f: /* pop reg */
1281 dst.ptr = (unsigned long *)&_regs[b & 0x7];
1282
1283pop_instruction:
1284 if ((rc = ops->read_std(register_address(ctxt->ss_base,
1285 _regs[VCPU_REGS_RSP]), dst.ptr, op_bytes, ctxt->vcpu))
1286 != 0)
1287 goto done;
1288 1290
1289 register_address_increment(_regs[VCPU_REGS_RSP], op_bytes);
1290 no_wb = 1; /* Disable writeback. */
1291 break;
1292 } 1291 }
1293 goto writeback; 1292 goto writeback;
1294 1293
@@ -1382,6 +1381,16 @@ twobyte_insn:
1382 /* Odd cmov opcodes (lsb == 1) have inverted sense. */ 1381 /* Odd cmov opcodes (lsb == 1) have inverted sense. */
1383 no_wb ^= b & 1; 1382 no_wb ^= b & 1;
1384 break; 1383 break;
1384 case 0xa3:
1385 bt: /* bt */
1386 src.val &= (dst.bytes << 3) - 1; /* only subword offset */
1387 emulate_2op_SrcV_nobyte("bt", src, dst, _eflags);
1388 break;
1389 case 0xab:
1390 bts: /* bts */
1391 src.val &= (dst.bytes << 3) - 1; /* only subword offset */
1392 emulate_2op_SrcV_nobyte("bts", src, dst, _eflags);
1393 break;
1385 case 0xb0 ... 0xb1: /* cmpxchg */ 1394 case 0xb0 ... 0xb1: /* cmpxchg */
1386 /* 1395 /*
1387 * Save real source value, then compare EAX against 1396 * Save real source value, then compare EAX against
@@ -1399,30 +1408,15 @@ twobyte_insn:
1399 dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX]; 1408 dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
1400 } 1409 }
1401 break; 1410 break;
1402 case 0xa3:
1403 bt: /* bt */
1404 src.val &= (dst.bytes << 3) - 1; /* only subword offset */
1405 emulate_2op_SrcV_nobyte("bt", src, dst, _eflags);
1406 break;
1407 case 0xb3: 1411 case 0xb3:
1408 btr: /* btr */ 1412 btr: /* btr */
1409 src.val &= (dst.bytes << 3) - 1; /* only subword offset */ 1413 src.val &= (dst.bytes << 3) - 1; /* only subword offset */
1410 emulate_2op_SrcV_nobyte("btr", src, dst, _eflags); 1414 emulate_2op_SrcV_nobyte("btr", src, dst, _eflags);
1411 break; 1415 break;
1412 case 0xab:
1413 bts: /* bts */
1414 src.val &= (dst.bytes << 3) - 1; /* only subword offset */
1415 emulate_2op_SrcV_nobyte("bts", src, dst, _eflags);
1416 break;
1417 case 0xb6 ... 0xb7: /* movzx */ 1416 case 0xb6 ... 0xb7: /* movzx */
1418 dst.bytes = op_bytes; 1417 dst.bytes = op_bytes;
1419 dst.val = (d & ByteOp) ? (u8) src.val : (u16) src.val; 1418 dst.val = (d & ByteOp) ? (u8) src.val : (u16) src.val;
1420 break; 1419 break;
1421 case 0xbb:
1422 btc: /* btc */
1423 src.val &= (dst.bytes << 3) - 1; /* only subword offset */
1424 emulate_2op_SrcV_nobyte("btc", src, dst, _eflags);
1425 break;
1426 case 0xba: /* Grp8 */ 1420 case 0xba: /* Grp8 */
1427 switch (modrm_reg & 3) { 1421 switch (modrm_reg & 3) {
1428 case 0: 1422 case 0:
@@ -1435,6 +1429,11 @@ twobyte_insn:
1435 goto btc; 1429 goto btc;
1436 } 1430 }
1437 break; 1431 break;
1432 case 0xbb:
1433 btc: /* btc */
1434 src.val &= (dst.bytes << 3) - 1; /* only subword offset */
1435 emulate_2op_SrcV_nobyte("btc", src, dst, _eflags);
1436 break;
1438 case 0xbe ... 0xbf: /* movsx */ 1437 case 0xbe ... 0xbf: /* movsx */
1439 dst.bytes = op_bytes; 1438 dst.bytes = op_bytes;
1440 dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val; 1439 dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val;
@@ -1446,14 +1445,14 @@ twobyte_special_insn:
1446 /* Disable writeback. */ 1445 /* Disable writeback. */
1447 no_wb = 1; 1446 no_wb = 1;
1448 switch (b) { 1447 switch (b) {
1448 case 0x06:
1449 emulate_clts(ctxt->vcpu);
1450 break;
1449 case 0x09: /* wbinvd */ 1451 case 0x09: /* wbinvd */
1450 break; 1452 break;
1451 case 0x0d: /* GrpP (prefetch) */ 1453 case 0x0d: /* GrpP (prefetch) */
1452 case 0x18: /* Grp16 (prefetch/nop) */ 1454 case 0x18: /* Grp16 (prefetch/nop) */
1453 break; 1455 break;
1454 case 0x06:
1455 emulate_clts(ctxt->vcpu);
1456 break;
1457 case 0x20: /* mov cr, reg */ 1456 case 0x20: /* mov cr, reg */
1458 if (modrm_mod != 3) 1457 if (modrm_mod != 3)
1459 goto cannot_emulate; 1458 goto cannot_emulate;