diff options
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r-- | drivers/kvm/x86_emulate.c | 44 |
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] = { | |||
152 | static u16 twobyte_table[256] = { | 156 | static 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 | ||
1058 | writeback: | 1063 | writeback: |
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 | |||
1166 | pop_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 | ||
1303 | twobyte_special_insn: | 1325 | twobyte_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; |