diff options
Diffstat (limited to 'arch/x86/kvm/x86_emulate.c')
-rw-r--r-- | arch/x86/kvm/x86_emulate.c | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index d174db7a3370..ca91749d2083 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c | |||
@@ -178,7 +178,7 @@ static u32 opcode_table[256] = { | |||
178 | 0, ImplicitOps | Stack, 0, 0, | 178 | 0, ImplicitOps | Stack, 0, 0, |
179 | ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov, | 179 | ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov, |
180 | /* 0xC8 - 0xCF */ | 180 | /* 0xC8 - 0xCF */ |
181 | 0, 0, 0, 0, 0, 0, 0, 0, | 181 | 0, 0, 0, ImplicitOps | Stack, 0, 0, 0, 0, |
182 | /* 0xD0 - 0xD7 */ | 182 | /* 0xD0 - 0xD7 */ |
183 | ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM, | 183 | ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM, |
184 | ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM, | 184 | ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM, |
@@ -1136,18 +1136,19 @@ static inline void emulate_push(struct x86_emulate_ctxt *ctxt) | |||
1136 | } | 1136 | } |
1137 | 1137 | ||
1138 | static int emulate_pop(struct x86_emulate_ctxt *ctxt, | 1138 | static int emulate_pop(struct x86_emulate_ctxt *ctxt, |
1139 | struct x86_emulate_ops *ops) | 1139 | struct x86_emulate_ops *ops, |
1140 | void *dest, int len) | ||
1140 | { | 1141 | { |
1141 | struct decode_cache *c = &ctxt->decode; | 1142 | struct decode_cache *c = &ctxt->decode; |
1142 | int rc; | 1143 | int rc; |
1143 | 1144 | ||
1144 | rc = ops->read_emulated(register_address(c, ss_base(ctxt), | 1145 | rc = ops->read_emulated(register_address(c, ss_base(ctxt), |
1145 | c->regs[VCPU_REGS_RSP]), | 1146 | c->regs[VCPU_REGS_RSP]), |
1146 | &c->src.val, c->src.bytes, ctxt->vcpu); | 1147 | dest, len, ctxt->vcpu); |
1147 | if (rc != 0) | 1148 | if (rc != 0) |
1148 | return rc; | 1149 | return rc; |
1149 | 1150 | ||
1150 | register_address_increment(c, &c->regs[VCPU_REGS_RSP], c->src.bytes); | 1151 | register_address_increment(c, &c->regs[VCPU_REGS_RSP], len); |
1151 | return rc; | 1152 | return rc; |
1152 | } | 1153 | } |
1153 | 1154 | ||
@@ -1157,11 +1158,9 @@ static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt, | |||
1157 | struct decode_cache *c = &ctxt->decode; | 1158 | struct decode_cache *c = &ctxt->decode; |
1158 | int rc; | 1159 | int rc; |
1159 | 1160 | ||
1160 | c->src.bytes = c->dst.bytes; | 1161 | rc = emulate_pop(ctxt, ops, &c->dst.val, c->dst.bytes); |
1161 | rc = emulate_pop(ctxt, ops); | ||
1162 | if (rc != 0) | 1162 | if (rc != 0) |
1163 | return rc; | 1163 | return rc; |
1164 | c->dst.val = c->src.val; | ||
1165 | return 0; | 1164 | return 0; |
1166 | } | 1165 | } |
1167 | 1166 | ||
@@ -1279,6 +1278,25 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, | |||
1279 | return 0; | 1278 | return 0; |
1280 | } | 1279 | } |
1281 | 1280 | ||
1281 | static int emulate_ret_far(struct x86_emulate_ctxt *ctxt, | ||
1282 | struct x86_emulate_ops *ops) | ||
1283 | { | ||
1284 | struct decode_cache *c = &ctxt->decode; | ||
1285 | int rc; | ||
1286 | unsigned long cs; | ||
1287 | |||
1288 | rc = emulate_pop(ctxt, ops, &c->eip, c->op_bytes); | ||
1289 | if (rc) | ||
1290 | return rc; | ||
1291 | if (c->op_bytes == 4) | ||
1292 | c->eip = (u32)c->eip; | ||
1293 | rc = emulate_pop(ctxt, ops, &cs, c->op_bytes); | ||
1294 | if (rc) | ||
1295 | return rc; | ||
1296 | rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)cs, 1, VCPU_SREG_CS); | ||
1297 | return rc; | ||
1298 | } | ||
1299 | |||
1282 | static inline int writeback(struct x86_emulate_ctxt *ctxt, | 1300 | static inline int writeback(struct x86_emulate_ctxt *ctxt, |
1283 | struct x86_emulate_ops *ops) | 1301 | struct x86_emulate_ops *ops) |
1284 | { | 1302 | { |
@@ -1467,11 +1485,9 @@ special_insn: | |||
1467 | break; | 1485 | break; |
1468 | case 0x58 ... 0x5f: /* pop reg */ | 1486 | case 0x58 ... 0x5f: /* pop reg */ |
1469 | pop_instruction: | 1487 | pop_instruction: |
1470 | c->src.bytes = c->op_bytes; | 1488 | rc = emulate_pop(ctxt, ops, &c->dst.val, c->op_bytes); |
1471 | rc = emulate_pop(ctxt, ops); | ||
1472 | if (rc != 0) | 1489 | if (rc != 0) |
1473 | goto done; | 1490 | goto done; |
1474 | c->dst.val = c->src.val; | ||
1475 | break; | 1491 | break; |
1476 | case 0x63: /* movsxd */ | 1492 | case 0x63: /* movsxd */ |
1477 | if (ctxt->mode != X86EMUL_MODE_PROT64) | 1493 | if (ctxt->mode != X86EMUL_MODE_PROT64) |
@@ -1738,6 +1754,11 @@ special_insn: | |||
1738 | mov: | 1754 | mov: |
1739 | c->dst.val = c->src.val; | 1755 | c->dst.val = c->src.val; |
1740 | break; | 1756 | break; |
1757 | case 0xcb: /* ret far */ | ||
1758 | rc = emulate_ret_far(ctxt, ops); | ||
1759 | if (rc) | ||
1760 | goto done; | ||
1761 | break; | ||
1741 | case 0xd0 ... 0xd1: /* Grp2 */ | 1762 | case 0xd0 ... 0xd1: /* Grp2 */ |
1742 | c->src.val = 1; | 1763 | c->src.val = 1; |
1743 | emulate_grp2(ctxt); | 1764 | emulate_grp2(ctxt); |
@@ -1908,11 +1929,16 @@ twobyte_insn: | |||
1908 | c->dst.type = OP_NONE; | 1929 | c->dst.type = OP_NONE; |
1909 | break; | 1930 | break; |
1910 | case 3: /* lidt/vmmcall */ | 1931 | case 3: /* lidt/vmmcall */ |
1911 | if (c->modrm_mod == 3 && c->modrm_rm == 1) { | 1932 | if (c->modrm_mod == 3) { |
1912 | rc = kvm_fix_hypercall(ctxt->vcpu); | 1933 | switch (c->modrm_rm) { |
1913 | if (rc) | 1934 | case 1: |
1914 | goto done; | 1935 | rc = kvm_fix_hypercall(ctxt->vcpu); |
1915 | kvm_emulate_hypercall(ctxt->vcpu); | 1936 | if (rc) |
1937 | goto done; | ||
1938 | break; | ||
1939 | default: | ||
1940 | goto cannot_emulate; | ||
1941 | } | ||
1916 | } else { | 1942 | } else { |
1917 | rc = read_descriptor(ctxt, ops, c->src.ptr, | 1943 | rc = read_descriptor(ctxt, ops, c->src.ptr, |
1918 | &size, &address, | 1944 | &size, &address, |