diff options
Diffstat (limited to 'drivers/kvm')
-rw-r--r-- | drivers/kvm/x86_emulate.c | 99 |
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 | |||
1283 | pop_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; |