diff options
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r-- | drivers/kvm/x86_emulate.c | 77 |
1 files changed, 49 insertions, 28 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index 9737c3b2f48c..a6ace302e0cd 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c | |||
@@ -212,7 +212,8 @@ static u16 twobyte_table[256] = { | |||
212 | 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, | 212 | 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, |
213 | DstReg | SrcMem16 | ModRM | Mov, | 213 | DstReg | SrcMem16 | ModRM | Mov, |
214 | /* 0xC0 - 0xCF */ | 214 | /* 0xC0 - 0xCF */ |
215 | 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, 0, | 215 | 0, 0, 0, DstMem | SrcReg | ModRM | Mov, 0, 0, 0, ImplicitOps | ModRM, |
216 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
216 | /* 0xD0 - 0xDF */ | 217 | /* 0xD0 - 0xDF */ |
217 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 218 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
218 | /* 0xE0 - 0xEF */ | 219 | /* 0xE0 - 0xEF */ |
@@ -596,11 +597,10 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
596 | case 0xf0: /* LOCK */ | 597 | case 0xf0: /* LOCK */ |
597 | lock_prefix = 1; | 598 | lock_prefix = 1; |
598 | break; | 599 | break; |
600 | case 0xf2: /* REPNE/REPNZ */ | ||
599 | case 0xf3: /* REP/REPE/REPZ */ | 601 | case 0xf3: /* REP/REPE/REPZ */ |
600 | rep_prefix = 1; | 602 | rep_prefix = 1; |
601 | break; | 603 | break; |
602 | case 0xf2: /* REPNE/REPNZ */ | ||
603 | break; | ||
604 | default: | 604 | default: |
605 | goto done_prefixes; | 605 | goto done_prefixes; |
606 | } | 606 | } |
@@ -825,6 +825,14 @@ done_prefixes: | |||
825 | if (twobyte && b == 0x01 && modrm_reg == 7) | 825 | if (twobyte && b == 0x01 && modrm_reg == 7) |
826 | break; | 826 | break; |
827 | srcmem_common: | 827 | srcmem_common: |
828 | /* | ||
829 | * For instructions with a ModR/M byte, switch to register | ||
830 | * access if Mod = 3. | ||
831 | */ | ||
832 | if ((d & ModRM) && modrm_mod == 3) { | ||
833 | src.type = OP_REG; | ||
834 | break; | ||
835 | } | ||
828 | src.type = OP_MEM; | 836 | src.type = OP_MEM; |
829 | src.ptr = (unsigned long *)cr2; | 837 | src.ptr = (unsigned long *)cr2; |
830 | src.val = 0; | 838 | src.val = 0; |
@@ -893,6 +901,14 @@ done_prefixes: | |||
893 | dst.ptr = (unsigned long *)cr2; | 901 | dst.ptr = (unsigned long *)cr2; |
894 | dst.bytes = (d & ByteOp) ? 1 : op_bytes; | 902 | dst.bytes = (d & ByteOp) ? 1 : op_bytes; |
895 | dst.val = 0; | 903 | dst.val = 0; |
904 | /* | ||
905 | * For instructions with a ModR/M byte, switch to register | ||
906 | * access if Mod = 3. | ||
907 | */ | ||
908 | if ((d & ModRM) && modrm_mod == 3) { | ||
909 | dst.type = OP_REG; | ||
910 | break; | ||
911 | } | ||
896 | if (d & BitOp) { | 912 | if (d & BitOp) { |
897 | unsigned long mask = ~(dst.bytes * 8 - 1); | 913 | unsigned long mask = ~(dst.bytes * 8 - 1); |
898 | 914 | ||
@@ -1083,31 +1099,6 @@ push: | |||
1083 | case 0xd2 ... 0xd3: /* Grp2 */ | 1099 | case 0xd2 ... 0xd3: /* Grp2 */ |
1084 | src.val = _regs[VCPU_REGS_RCX]; | 1100 | src.val = _regs[VCPU_REGS_RCX]; |
1085 | goto grp2; | 1101 | goto grp2; |
1086 | case 0xe8: /* call (near) */ { | ||
1087 | long int rel; | ||
1088 | switch (op_bytes) { | ||
1089 | case 2: | ||
1090 | rel = insn_fetch(s16, 2, _eip); | ||
1091 | break; | ||
1092 | case 4: | ||
1093 | rel = insn_fetch(s32, 4, _eip); | ||
1094 | break; | ||
1095 | case 8: | ||
1096 | rel = insn_fetch(s64, 8, _eip); | ||
1097 | break; | ||
1098 | default: | ||
1099 | DPRINTF("Call: Invalid op_bytes\n"); | ||
1100 | goto cannot_emulate; | ||
1101 | } | ||
1102 | src.val = (unsigned long) _eip; | ||
1103 | JMP_REL(rel); | ||
1104 | goto push; | ||
1105 | } | ||
1106 | case 0xe9: /* jmp rel */ | ||
1107 | case 0xeb: /* jmp rel short */ | ||
1108 | JMP_REL(src.val); | ||
1109 | no_wb = 1; /* Disable writeback. */ | ||
1110 | break; | ||
1111 | case 0xf6 ... 0xf7: /* Grp3 */ | 1102 | case 0xf6 ... 0xf7: /* Grp3 */ |
1112 | switch (modrm_reg) { | 1103 | switch (modrm_reg) { |
1113 | case 0 ... 1: /* test */ | 1104 | case 0 ... 1: /* test */ |
@@ -1350,6 +1341,32 @@ special_insn: | |||
1350 | case 0xae ... 0xaf: /* scas */ | 1341 | case 0xae ... 0xaf: /* scas */ |
1351 | DPRINTF("Urk! I don't handle SCAS.\n"); | 1342 | DPRINTF("Urk! I don't handle SCAS.\n"); |
1352 | goto cannot_emulate; | 1343 | goto cannot_emulate; |
1344 | case 0xe8: /* call (near) */ { | ||
1345 | long int rel; | ||
1346 | switch (op_bytes) { | ||
1347 | case 2: | ||
1348 | rel = insn_fetch(s16, 2, _eip); | ||
1349 | break; | ||
1350 | case 4: | ||
1351 | rel = insn_fetch(s32, 4, _eip); | ||
1352 | break; | ||
1353 | case 8: | ||
1354 | rel = insn_fetch(s64, 8, _eip); | ||
1355 | break; | ||
1356 | default: | ||
1357 | DPRINTF("Call: Invalid op_bytes\n"); | ||
1358 | goto cannot_emulate; | ||
1359 | } | ||
1360 | src.val = (unsigned long) _eip; | ||
1361 | JMP_REL(rel); | ||
1362 | goto push; | ||
1363 | } | ||
1364 | case 0xe9: /* jmp rel */ | ||
1365 | case 0xeb: /* jmp rel short */ | ||
1366 | JMP_REL(src.val); | ||
1367 | no_wb = 1; /* Disable writeback. */ | ||
1368 | break; | ||
1369 | |||
1353 | 1370 | ||
1354 | } | 1371 | } |
1355 | goto writeback; | 1372 | goto writeback; |
@@ -1501,6 +1518,10 @@ twobyte_insn: | |||
1501 | dst.bytes = op_bytes; | 1518 | dst.bytes = op_bytes; |
1502 | dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val; | 1519 | dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val; |
1503 | break; | 1520 | break; |
1521 | case 0xc3: /* movnti */ | ||
1522 | dst.bytes = op_bytes; | ||
1523 | dst.val = (op_bytes == 4) ? (u32) src.val : (u64) src.val; | ||
1524 | break; | ||
1504 | } | 1525 | } |
1505 | goto writeback; | 1526 | goto writeback; |
1506 | 1527 | ||