diff options
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r-- | drivers/kvm/x86_emulate.c | 98 |
1 files changed, 52 insertions, 46 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index be70795b4822..7513cddb929f 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #define ModRM (1<<6) | 61 | #define ModRM (1<<6) |
62 | /* Destination is only written; never read. */ | 62 | /* Destination is only written; never read. */ |
63 | #define Mov (1<<7) | 63 | #define Mov (1<<7) |
64 | #define BitOp (1<<8) | ||
64 | 65 | ||
65 | static u8 opcode_table[256] = { | 66 | static u8 opcode_table[256] = { |
66 | /* 0x00 - 0x07 */ | 67 | /* 0x00 - 0x07 */ |
@@ -148,7 +149,7 @@ static u8 opcode_table[256] = { | |||
148 | 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM | 149 | 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM |
149 | }; | 150 | }; |
150 | 151 | ||
151 | static u8 twobyte_table[256] = { | 152 | static u16 twobyte_table[256] = { |
152 | /* 0x00 - 0x0F */ | 153 | /* 0x00 - 0x0F */ |
153 | 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0, | 154 | 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0, |
154 | 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, | 155 | 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, |
@@ -180,16 +181,16 @@ static u8 twobyte_table[256] = { | |||
180 | /* 0x90 - 0x9F */ | 181 | /* 0x90 - 0x9F */ |
181 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 182 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
182 | /* 0xA0 - 0xA7 */ | 183 | /* 0xA0 - 0xA7 */ |
183 | 0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0, | 184 | 0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0, |
184 | /* 0xA8 - 0xAF */ | 185 | /* 0xA8 - 0xAF */ |
185 | 0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0, | 186 | 0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0, |
186 | /* 0xB0 - 0xB7 */ | 187 | /* 0xB0 - 0xB7 */ |
187 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0, | 188 | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0, |
188 | DstMem | SrcReg | ModRM, | 189 | DstMem | SrcReg | ModRM | BitOp, |
189 | 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, | 190 | 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, |
190 | DstReg | SrcMem16 | ModRM | Mov, | 191 | DstReg | SrcMem16 | ModRM | Mov, |
191 | /* 0xB8 - 0xBF */ | 192 | /* 0xB8 - 0xBF */ |
192 | 0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM, | 193 | 0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM | BitOp, |
193 | 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, | 194 | 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, |
194 | DstReg | SrcMem16 | ModRM | Mov, | 195 | DstReg | SrcMem16 | ModRM | Mov, |
195 | /* 0xC0 - 0xCF */ | 196 | /* 0xC0 - 0xCF */ |
@@ -469,7 +470,8 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt, | |||
469 | int | 470 | int |
470 | x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | 471 | x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) |
471 | { | 472 | { |
472 | u8 b, d, sib, twobyte = 0, rex_prefix = 0; | 473 | unsigned d; |
474 | u8 b, sib, twobyte = 0, rex_prefix = 0; | ||
473 | u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; | 475 | u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; |
474 | unsigned long *override_base = NULL; | 476 | unsigned long *override_base = NULL; |
475 | unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i; | 477 | unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i; |
@@ -726,46 +728,6 @@ done_prefixes: | |||
726 | ; | 728 | ; |
727 | } | 729 | } |
728 | 730 | ||
729 | /* Decode and fetch the destination operand: register or memory. */ | ||
730 | switch (d & DstMask) { | ||
731 | case ImplicitOps: | ||
732 | /* Special instructions do their own operand decoding. */ | ||
733 | goto special_insn; | ||
734 | case DstReg: | ||
735 | dst.type = OP_REG; | ||
736 | if ((d & ByteOp) | ||
737 | && !(twobyte_table && (b == 0xb6 || b == 0xb7))) { | ||
738 | dst.ptr = decode_register(modrm_reg, _regs, | ||
739 | (rex_prefix == 0)); | ||
740 | dst.val = *(u8 *) dst.ptr; | ||
741 | dst.bytes = 1; | ||
742 | } else { | ||
743 | dst.ptr = decode_register(modrm_reg, _regs, 0); | ||
744 | switch ((dst.bytes = op_bytes)) { | ||
745 | case 2: | ||
746 | dst.val = *(u16 *)dst.ptr; | ||
747 | break; | ||
748 | case 4: | ||
749 | dst.val = *(u32 *)dst.ptr; | ||
750 | break; | ||
751 | case 8: | ||
752 | dst.val = *(u64 *)dst.ptr; | ||
753 | break; | ||
754 | } | ||
755 | } | ||
756 | break; | ||
757 | case DstMem: | ||
758 | dst.type = OP_MEM; | ||
759 | dst.ptr = (unsigned long *)cr2; | ||
760 | dst.bytes = (d & ByteOp) ? 1 : op_bytes; | ||
761 | if (!(d & Mov) && /* optimisation - avoid slow emulated read */ | ||
762 | ((rc = ops->read_emulated((unsigned long)dst.ptr, | ||
763 | &dst.val, dst.bytes, ctxt)) != 0)) | ||
764 | goto done; | ||
765 | break; | ||
766 | } | ||
767 | dst.orig_val = dst.val; | ||
768 | |||
769 | /* | 731 | /* |
770 | * Decode and fetch the source operand: register, memory | 732 | * Decode and fetch the source operand: register, memory |
771 | * or immediate. | 733 | * or immediate. |
@@ -838,6 +800,50 @@ done_prefixes: | |||
838 | break; | 800 | break; |
839 | } | 801 | } |
840 | 802 | ||
803 | /* Decode and fetch the destination operand: register or memory. */ | ||
804 | switch (d & DstMask) { | ||
805 | case ImplicitOps: | ||
806 | /* Special instructions do their own operand decoding. */ | ||
807 | goto special_insn; | ||
808 | case DstReg: | ||
809 | dst.type = OP_REG; | ||
810 | if ((d & ByteOp) | ||
811 | && !(twobyte_table && (b == 0xb6 || b == 0xb7))) { | ||
812 | dst.ptr = decode_register(modrm_reg, _regs, | ||
813 | (rex_prefix == 0)); | ||
814 | dst.val = *(u8 *) dst.ptr; | ||
815 | dst.bytes = 1; | ||
816 | } else { | ||
817 | dst.ptr = decode_register(modrm_reg, _regs, 0); | ||
818 | switch ((dst.bytes = op_bytes)) { | ||
819 | case 2: | ||
820 | dst.val = *(u16 *)dst.ptr; | ||
821 | break; | ||
822 | case 4: | ||
823 | dst.val = *(u32 *)dst.ptr; | ||
824 | break; | ||
825 | case 8: | ||
826 | dst.val = *(u64 *)dst.ptr; | ||
827 | break; | ||
828 | } | ||
829 | } | ||
830 | break; | ||
831 | case DstMem: | ||
832 | dst.type = OP_MEM; | ||
833 | dst.ptr = (unsigned long *)cr2; | ||
834 | dst.bytes = (d & ByteOp) ? 1 : op_bytes; | ||
835 | if (d & BitOp) { | ||
836 | dst.ptr += src.val / BITS_PER_LONG; | ||
837 | dst.bytes = sizeof(long); | ||
838 | } | ||
839 | if (!(d & Mov) && /* optimisation - avoid slow emulated read */ | ||
840 | ((rc = ops->read_emulated((unsigned long)dst.ptr, | ||
841 | &dst.val, dst.bytes, ctxt)) != 0)) | ||
842 | goto done; | ||
843 | break; | ||
844 | } | ||
845 | dst.orig_val = dst.val; | ||
846 | |||
841 | if (twobyte) | 847 | if (twobyte) |
842 | goto twobyte_insn; | 848 | goto twobyte_insn; |
843 | 849 | ||