aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/x86_emulate.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r--drivers/kvm/x86_emulate.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 7ade09086aa5..f60012d62610 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -98,8 +98,11 @@ static u8 opcode_table[256] = {
98 0, 0, 0, 0, 98 0, 0, 0, 0,
99 /* 0x40 - 0x4F */ 99 /* 0x40 - 0x4F */
100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101 /* 0x50 - 0x5F */ 101 /* 0x50 - 0x57 */
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102 0, 0, 0, 0, 0, 0, 0, 0,
103 /* 0x58 - 0x5F */
104 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
105 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
103 /* 0x60 - 0x6F */ 106 /* 0x60 - 0x6F */
104 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ , 107 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ ,
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -128,9 +131,9 @@ static u8 opcode_table[256] = {
128 /* 0xB0 - 0xBF */ 131 /* 0xB0 - 0xBF */
129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
130 /* 0xC0 - 0xC7 */ 133 /* 0xC0 - 0xC7 */
131 ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, 0, 0, 134 ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
132 0, 0, ByteOp | DstMem | SrcImm | ModRM | Mov, 135 0, ImplicitOps, 0, 0,
133 DstMem | SrcImm | ModRM | Mov, 136 ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov,
134 /* 0xC8 - 0xCF */ 137 /* 0xC8 - 0xCF */
135 0, 0, 0, 0, 0, 0, 0, 0, 138 0, 0, 0, 0, 0, 0, 0, 0,
136 /* 0xD0 - 0xD7 */ 139 /* 0xD0 - 0xD7 */
@@ -143,7 +146,8 @@ static u8 opcode_table[256] = {
143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144 /* 0xF0 - 0xF7 */ 147 /* 0xF0 - 0xF7 */
145 0, 0, 0, 0, 148 0, 0, 0, 0,
146 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, 149 ImplicitOps, 0,
150 ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,
147 /* 0xF8 - 0xFF */ 151 /* 0xF8 - 0xFF */
148 0, 0, 0, 0, 152 0, 0, 0, 0,
149 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM 153 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM
@@ -152,7 +156,7 @@ static u8 opcode_table[256] = {
152static u16 twobyte_table[256] = { 156static u16 twobyte_table[256] = {
153 /* 0x00 - 0x0F */ 157 /* 0x00 - 0x0F */
154 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0, 158 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0,
155 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 159 0, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
156 /* 0x10 - 0x1F */ 160 /* 0x10 - 0x1F */
157 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, 161 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
158 /* 0x20 - 0x2F */ 162 /* 0x20 - 0x2F */
@@ -481,6 +485,7 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
481 int mode = ctxt->mode; 485 int mode = ctxt->mode;
482 unsigned long modrm_ea; 486 unsigned long modrm_ea;
483 int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0; 487 int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0;
488 int no_wb = 0;
484 489
485 /* Shadow copy of register state. Committed on successful emulation. */ 490 /* Shadow copy of register state. Committed on successful emulation. */
486 unsigned long _regs[NR_VCPU_REGS]; 491 unsigned long _regs[NR_VCPU_REGS];
@@ -1047,7 +1052,7 @@ done_prefixes:
1047 _regs[VCPU_REGS_RSP]), 1052 _regs[VCPU_REGS_RSP]),
1048 &dst.val, dst.bytes, ctxt)) != 0) 1053 &dst.val, dst.bytes, ctxt)) != 0)
1049 goto done; 1054 goto done;
1050 dst.val = dst.orig_val; /* skanky: disable writeback */ 1055 no_wb = 1;
1051 break; 1056 break;
1052 default: 1057 default:
1053 goto cannot_emulate; 1058 goto cannot_emulate;
@@ -1056,7 +1061,7 @@ done_prefixes:
1056 } 1061 }
1057 1062
1058writeback: 1063writeback:
1059 if ((d & Mov) || (dst.orig_val != dst.val)) { 1064 if (!no_wb) {
1060 switch (dst.type) { 1065 switch (dst.type) {
1061 case OP_REG: 1066 case OP_REG:
1062 /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */ 1067 /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
@@ -1149,6 +1154,23 @@ special_insn:
1149 case 0xae ... 0xaf: /* scas */ 1154 case 0xae ... 0xaf: /* scas */
1150 DPRINTF("Urk! I don't handle SCAS.\n"); 1155 DPRINTF("Urk! I don't handle SCAS.\n");
1151 goto cannot_emulate; 1156 goto cannot_emulate;
1157 case 0xf4: /* hlt */
1158 ctxt->vcpu->halt_request = 1;
1159 goto done;
1160 case 0xc3: /* ret */
1161 dst.ptr = &_eip;
1162 goto pop_instruction;
1163 case 0x58 ... 0x5f: /* pop reg */
1164 dst.ptr = (unsigned long *)&_regs[b & 0x7];
1165
1166pop_instruction:
1167 if ((rc = ops->read_std(register_address(ctxt->ss_base,
1168 _regs[VCPU_REGS_RSP]), dst.ptr, op_bytes, ctxt)) != 0)
1169 goto done;
1170
1171 register_address_increment(_regs[VCPU_REGS_RSP], op_bytes);
1172 no_wb = 1; /* Disable writeback. */
1173 break;
1152 } 1174 }
1153 goto writeback; 1175 goto writeback;
1154 1176
@@ -1302,8 +1324,10 @@ twobyte_insn:
1302 1324
1303twobyte_special_insn: 1325twobyte_special_insn:
1304 /* Disable writeback. */ 1326 /* Disable writeback. */
1305 dst.orig_val = dst.val; 1327 no_wb = 1;
1306 switch (b) { 1328 switch (b) {
1329 case 0x09: /* wbinvd */
1330 break;
1307 case 0x0d: /* GrpP (prefetch) */ 1331 case 0x0d: /* GrpP (prefetch) */
1308 case 0x18: /* Grp16 (prefetch/nop) */ 1332 case 0x18: /* Grp16 (prefetch/nop) */
1309 break; 1333 break;