diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/emulate.c | 107 |
1 files changed, 101 insertions, 6 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 1be5cd640e93..1cdfec5231d0 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -92,19 +92,22 @@ static u32 opcode_table[256] = { | |||
92 | /* 0x00 - 0x07 */ | 92 | /* 0x00 - 0x07 */ |
93 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 93 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, |
94 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 94 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, |
95 | ByteOp | DstAcc | SrcImm, DstAcc | SrcImm, 0, 0, | 95 | ByteOp | DstAcc | SrcImm, DstAcc | SrcImm, |
96 | ImplicitOps | Stack, ImplicitOps | Stack, | ||
96 | /* 0x08 - 0x0F */ | 97 | /* 0x08 - 0x0F */ |
97 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 98 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, |
98 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 99 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, |
99 | 0, 0, 0, 0, | 100 | 0, 0, ImplicitOps | Stack, 0, |
100 | /* 0x10 - 0x17 */ | 101 | /* 0x10 - 0x17 */ |
101 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 102 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, |
102 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 103 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, |
103 | ByteOp | DstAcc | SrcImm, DstAcc | SrcImm, 0, 0, | 104 | ByteOp | DstAcc | SrcImm, DstAcc | SrcImm, |
105 | ImplicitOps | Stack, ImplicitOps | Stack, | ||
104 | /* 0x18 - 0x1F */ | 106 | /* 0x18 - 0x1F */ |
105 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 107 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, |
106 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 108 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, |
107 | ByteOp | DstAcc | SrcImm, DstAcc | SrcImm, 0, 0, | 109 | ByteOp | DstAcc | SrcImm, DstAcc | SrcImm, |
110 | ImplicitOps | Stack, ImplicitOps | Stack, | ||
108 | /* 0x20 - 0x27 */ | 111 | /* 0x20 - 0x27 */ |
109 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 112 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, |
110 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 113 | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, |
@@ -244,11 +247,13 @@ static u32 twobyte_table[256] = { | |||
244 | /* 0x90 - 0x9F */ | 247 | /* 0x90 - 0x9F */ |
245 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 248 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
246 | /* 0xA0 - 0xA7 */ | 249 | /* 0xA0 - 0xA7 */ |
247 | 0, 0, 0, DstMem | SrcReg | ModRM | BitOp, | 250 | ImplicitOps | Stack, ImplicitOps | Stack, |
251 | 0, DstMem | SrcReg | ModRM | BitOp, | ||
248 | DstMem | SrcReg | Src2ImmByte | ModRM, | 252 | DstMem | SrcReg | Src2ImmByte | ModRM, |
249 | DstMem | SrcReg | Src2CL | ModRM, 0, 0, | 253 | DstMem | SrcReg | Src2CL | ModRM, 0, 0, |
250 | /* 0xA8 - 0xAF */ | 254 | /* 0xA8 - 0xAF */ |
251 | 0, 0, 0, DstMem | SrcReg | ModRM | BitOp, | 255 | ImplicitOps | Stack, ImplicitOps | Stack, |
256 | 0, DstMem | SrcReg | ModRM | BitOp, | ||
252 | DstMem | SrcReg | Src2ImmByte | ModRM, | 257 | DstMem | SrcReg | Src2ImmByte | ModRM, |
253 | DstMem | SrcReg | Src2CL | ModRM, | 258 | DstMem | SrcReg | Src2CL | ModRM, |
254 | ModRM, 0, | 259 | ModRM, 0, |
@@ -1186,6 +1191,32 @@ static int emulate_pop(struct x86_emulate_ctxt *ctxt, | |||
1186 | return rc; | 1191 | return rc; |
1187 | } | 1192 | } |
1188 | 1193 | ||
1194 | static void emulate_push_sreg(struct x86_emulate_ctxt *ctxt, int seg) | ||
1195 | { | ||
1196 | struct decode_cache *c = &ctxt->decode; | ||
1197 | struct kvm_segment segment; | ||
1198 | |||
1199 | kvm_x86_ops->get_segment(ctxt->vcpu, &segment, seg); | ||
1200 | |||
1201 | c->src.val = segment.selector; | ||
1202 | emulate_push(ctxt); | ||
1203 | } | ||
1204 | |||
1205 | static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt, | ||
1206 | struct x86_emulate_ops *ops, int seg) | ||
1207 | { | ||
1208 | struct decode_cache *c = &ctxt->decode; | ||
1209 | unsigned long selector; | ||
1210 | int rc; | ||
1211 | |||
1212 | rc = emulate_pop(ctxt, ops, &selector, c->op_bytes); | ||
1213 | if (rc != 0) | ||
1214 | return rc; | ||
1215 | |||
1216 | rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)selector, 1, seg); | ||
1217 | return rc; | ||
1218 | } | ||
1219 | |||
1189 | static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt, | 1220 | static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt, |
1190 | struct x86_emulate_ops *ops) | 1221 | struct x86_emulate_ops *ops) |
1191 | { | 1222 | { |
@@ -1707,18 +1738,66 @@ special_insn: | |||
1707 | add: /* add */ | 1738 | add: /* add */ |
1708 | emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags); | 1739 | emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags); |
1709 | break; | 1740 | break; |
1741 | case 0x06: /* push es */ | ||
1742 | if (ctxt->mode == X86EMUL_MODE_PROT64) | ||
1743 | goto cannot_emulate; | ||
1744 | |||
1745 | emulate_push_sreg(ctxt, VCPU_SREG_ES); | ||
1746 | break; | ||
1747 | case 0x07: /* pop es */ | ||
1748 | if (ctxt->mode == X86EMUL_MODE_PROT64) | ||
1749 | goto cannot_emulate; | ||
1750 | |||
1751 | rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_ES); | ||
1752 | if (rc != 0) | ||
1753 | goto done; | ||
1754 | break; | ||
1710 | case 0x08 ... 0x0d: | 1755 | case 0x08 ... 0x0d: |
1711 | or: /* or */ | 1756 | or: /* or */ |
1712 | emulate_2op_SrcV("or", c->src, c->dst, ctxt->eflags); | 1757 | emulate_2op_SrcV("or", c->src, c->dst, ctxt->eflags); |
1713 | break; | 1758 | break; |
1759 | case 0x0e: /* push cs */ | ||
1760 | if (ctxt->mode == X86EMUL_MODE_PROT64) | ||
1761 | goto cannot_emulate; | ||
1762 | |||
1763 | emulate_push_sreg(ctxt, VCPU_SREG_CS); | ||
1764 | break; | ||
1714 | case 0x10 ... 0x15: | 1765 | case 0x10 ... 0x15: |
1715 | adc: /* adc */ | 1766 | adc: /* adc */ |
1716 | emulate_2op_SrcV("adc", c->src, c->dst, ctxt->eflags); | 1767 | emulate_2op_SrcV("adc", c->src, c->dst, ctxt->eflags); |
1717 | break; | 1768 | break; |
1769 | case 0x16: /* push ss */ | ||
1770 | if (ctxt->mode == X86EMUL_MODE_PROT64) | ||
1771 | goto cannot_emulate; | ||
1772 | |||
1773 | emulate_push_sreg(ctxt, VCPU_SREG_SS); | ||
1774 | break; | ||
1775 | case 0x17: /* pop ss */ | ||
1776 | if (ctxt->mode == X86EMUL_MODE_PROT64) | ||
1777 | goto cannot_emulate; | ||
1778 | |||
1779 | rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_SS); | ||
1780 | if (rc != 0) | ||
1781 | goto done; | ||
1782 | break; | ||
1718 | case 0x18 ... 0x1d: | 1783 | case 0x18 ... 0x1d: |
1719 | sbb: /* sbb */ | 1784 | sbb: /* sbb */ |
1720 | emulate_2op_SrcV("sbb", c->src, c->dst, ctxt->eflags); | 1785 | emulate_2op_SrcV("sbb", c->src, c->dst, ctxt->eflags); |
1721 | break; | 1786 | break; |
1787 | case 0x1e: /* push ds */ | ||
1788 | if (ctxt->mode == X86EMUL_MODE_PROT64) | ||
1789 | goto cannot_emulate; | ||
1790 | |||
1791 | emulate_push_sreg(ctxt, VCPU_SREG_DS); | ||
1792 | break; | ||
1793 | case 0x1f: /* pop ds */ | ||
1794 | if (ctxt->mode == X86EMUL_MODE_PROT64) | ||
1795 | goto cannot_emulate; | ||
1796 | |||
1797 | rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_DS); | ||
1798 | if (rc != 0) | ||
1799 | goto done; | ||
1800 | break; | ||
1722 | case 0x20 ... 0x25: | 1801 | case 0x20 ... 0x25: |
1723 | and: /* and */ | 1802 | and: /* and */ |
1724 | emulate_2op_SrcV("and", c->src, c->dst, ctxt->eflags); | 1803 | emulate_2op_SrcV("and", c->src, c->dst, ctxt->eflags); |
@@ -2297,6 +2376,14 @@ twobyte_insn: | |||
2297 | jmp_rel(c, c->src.val); | 2376 | jmp_rel(c, c->src.val); |
2298 | c->dst.type = OP_NONE; | 2377 | c->dst.type = OP_NONE; |
2299 | break; | 2378 | break; |
2379 | case 0xa0: /* push fs */ | ||
2380 | emulate_push_sreg(ctxt, VCPU_SREG_FS); | ||
2381 | break; | ||
2382 | case 0xa1: /* pop fs */ | ||
2383 | rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_FS); | ||
2384 | if (rc != 0) | ||
2385 | goto done; | ||
2386 | break; | ||
2300 | case 0xa3: | 2387 | case 0xa3: |
2301 | bt: /* bt */ | 2388 | bt: /* bt */ |
2302 | c->dst.type = OP_NONE; | 2389 | c->dst.type = OP_NONE; |
@@ -2308,6 +2395,14 @@ twobyte_insn: | |||
2308 | case 0xa5: /* shld cl, r, r/m */ | 2395 | case 0xa5: /* shld cl, r, r/m */ |
2309 | emulate_2op_cl("shld", c->src2, c->src, c->dst, ctxt->eflags); | 2396 | emulate_2op_cl("shld", c->src2, c->src, c->dst, ctxt->eflags); |
2310 | break; | 2397 | break; |
2398 | case 0xa8: /* push gs */ | ||
2399 | emulate_push_sreg(ctxt, VCPU_SREG_GS); | ||
2400 | break; | ||
2401 | case 0xa9: /* pop gs */ | ||
2402 | rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_GS); | ||
2403 | if (rc != 0) | ||
2404 | goto done; | ||
2405 | break; | ||
2311 | case 0xab: | 2406 | case 0xab: |
2312 | bts: /* bts */ | 2407 | bts: /* bts */ |
2313 | /* only subword offset */ | 2408 | /* only subword offset */ |