aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLaurent Vivier <Laurent.Vivier@bull.net>2007-09-18 05:27:19 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:52:47 -0500
commit8b4caf6650808024c37ec4b29cf81b308af998b1 (patch)
tree2179c0830c938ebfdbc3baa4b7c2eee4dc81a7ae /drivers
parente4e03deda83b1f2fc37ccbfc1eef27e86e8ed4e9 (diff)
KVM: x86 emulator: move all decoding process to function x86_decode_insn()
Split the decoding process into a new function x86_decode_insn(). Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/kvm/x86_emulate.c77
1 files changed, 53 insertions, 24 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index d7026cb8fc70..540589c5d427 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -517,20 +517,16 @@ static int test_cc(unsigned int condition, unsigned int flags)
517} 517}
518 518
519int 519int
520x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) 520x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
521{ 521{
522 struct decode_cache *c = &ctxt->decode; 522 struct decode_cache *c = &ctxt->decode;
523 u8 sib, rex_prefix = 0; 523 u8 sib, rex_prefix = 0;
524 unsigned int i; 524 unsigned int i;
525 int rc = 0; 525 int rc = 0;
526 unsigned long cr2 = ctxt->cr2;
527 int mode = ctxt->mode; 526 int mode = ctxt->mode;
528 int index_reg = 0, base_reg = 0, scale, rip_relative = 0; 527 int index_reg = 0, base_reg = 0, scale, rip_relative = 0;
529 int no_wb = 0;
530 u64 msr_data;
531 528
532 /* Shadow copy of register state. Committed on successful emulation. */ 529 /* Shadow copy of register state. Committed on successful emulation. */
533 unsigned long _eflags = ctxt->eflags;
534 530
535 memset(c, 0, sizeof(struct decode_cache)); 531 memset(c, 0, sizeof(struct decode_cache));
536 c->eip = ctxt->vcpu->rip; 532 c->eip = ctxt->vcpu->rip;
@@ -622,8 +618,10 @@ done_prefixes:
622 } 618 }
623 619
624 /* Unrecognised? */ 620 /* Unrecognised? */
625 if (c->d == 0) 621 if (c->d == 0) {
626 goto cannot_emulate; 622 DPRINTF("Cannot emulate %02x\n", c->b);
623 return -1;
624 }
627 } 625 }
628 626
629 /* ModRM and SIB bytes. */ 627 /* ModRM and SIB bytes. */
@@ -776,7 +774,6 @@ done_prefixes:
776 } 774 }
777 if (c->ad_bytes != 8) 775 if (c->ad_bytes != 8)
778 c->modrm_ea = (u32)c->modrm_ea; 776 c->modrm_ea = (u32)c->modrm_ea;
779 cr2 = c->modrm_ea;
780 modrm_done: 777 modrm_done:
781 ; 778 ;
782 } 779 }
@@ -838,13 +835,6 @@ done_prefixes:
838 break; 835 break;
839 } 836 }
840 c->src.type = OP_MEM; 837 c->src.type = OP_MEM;
841 c->src.ptr = (unsigned long *)cr2;
842 c->src.val = 0;
843 if ((rc = ops->read_emulated((unsigned long)c->src.ptr,
844 &c->src.val,
845 c->src.bytes, ctxt->vcpu)) != 0)
846 goto done;
847 c->src.orig_val = c->src.val;
848 break; 838 break;
849 case SrcImm: 839 case SrcImm:
850 c->src.type = OP_IMM; 840 c->src.type = OP_IMM;
@@ -877,7 +867,7 @@ done_prefixes:
877 switch (c->d & DstMask) { 867 switch (c->d & DstMask) {
878 case ImplicitOps: 868 case ImplicitOps:
879 /* Special instructions do their own operand decoding. */ 869 /* Special instructions do their own operand decoding. */
880 goto special_insn; 870 return 0;
881 case DstReg: 871 case DstReg:
882 c->dst.type = OP_REG; 872 c->dst.type = OP_REG;
883 if ((c->d & ByteOp) 873 if ((c->d & ByteOp)
@@ -905,14 +895,54 @@ done_prefixes:
905 } 895 }
906 break; 896 break;
907 case DstMem: 897 case DstMem:
908 c->dst.type = OP_MEM;
909 c->dst.ptr = (unsigned long *)cr2;
910 c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
911 c->dst.val = 0;
912 if ((c->d & ModRM) && c->modrm_mod == 3) { 898 if ((c->d & ModRM) && c->modrm_mod == 3) {
913 c->dst.type = OP_REG; 899 c->dst.type = OP_REG;
914 break; 900 break;
915 } 901 }
902 c->dst.type = OP_MEM;
903 break;
904 }
905
906done:
907 return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
908}
909
910int
911x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
912{
913 unsigned long cr2 = ctxt->cr2;
914 int no_wb = 0;
915 u64 msr_data;
916 unsigned long _eflags = ctxt->eflags;
917 struct decode_cache *c = &ctxt->decode;
918 int rc;
919
920 rc = x86_decode_insn(ctxt, ops);
921 if (rc)
922 return rc;
923
924 if ((c->d & ModRM) && (c->modrm_mod != 3))
925 cr2 = c->modrm_ea;
926
927 if (c->src.type == OP_MEM) {
928 c->src.ptr = (unsigned long *)cr2;
929 c->src.val = 0;
930 if ((rc = ops->read_emulated((unsigned long)c->src.ptr,
931 &c->src.val,
932 c->src.bytes,
933 ctxt->vcpu)) != 0)
934 goto done;
935 c->src.orig_val = c->src.val;
936 }
937
938 if ((c->d & DstMask) == ImplicitOps)
939 goto special_insn;
940
941
942 if (c->dst.type == OP_MEM) {
943 c->dst.ptr = (unsigned long *)cr2;
944 c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
945 c->dst.val = 0;
916 if (c->d & BitOp) { 946 if (c->d & BitOp) {
917 unsigned long mask = ~(c->dst.bytes * 8 - 1); 947 unsigned long mask = ~(c->dst.bytes * 8 - 1);
918 948
@@ -925,7 +955,6 @@ done_prefixes:
925 &c->dst.val, 955 &c->dst.val,
926 c->dst.bytes, ctxt->vcpu)) != 0)) 956 c->dst.bytes, ctxt->vcpu)) != 0))
927 goto done; 957 goto done;
928 break;
929 } 958 }
930 c->dst.orig_val = c->dst.val; 959 c->dst.orig_val = c->dst.val;
931 960
@@ -983,7 +1012,7 @@ done_prefixes:
983 emulate_2op_SrcV("cmp", c->src, c->dst, _eflags); 1012 emulate_2op_SrcV("cmp", c->src, c->dst, _eflags);
984 break; 1013 break;
985 case 0x63: /* movsxd */ 1014 case 0x63: /* movsxd */
986 if (mode != X86EMUL_MODE_PROT64) 1015 if (ctxt->mode != X86EMUL_MODE_PROT64)
987 goto cannot_emulate; 1016 goto cannot_emulate;
988 c->dst.val = (s32) c->src.val; 1017 c->dst.val = (s32) c->src.val;
989 break; 1018 break;
@@ -1041,7 +1070,7 @@ done_prefixes:
1041 break; 1070 break;
1042 case 0x8f: /* pop (sole member of Grp1a) */ 1071 case 0x8f: /* pop (sole member of Grp1a) */
1043 /* 64-bit mode: POP always pops a 64-bit operand. */ 1072 /* 64-bit mode: POP always pops a 64-bit operand. */
1044 if (mode == X86EMUL_MODE_PROT64) 1073 if (ctxt->mode == X86EMUL_MODE_PROT64)
1045 c->dst.bytes = 8; 1074 c->dst.bytes = 8;
1046 if ((rc = ops->read_std(register_address( 1075 if ((rc = ops->read_std(register_address(
1047 ctxt->ss_base, 1076 ctxt->ss_base,
@@ -1152,7 +1181,7 @@ done_prefixes:
1152 break; 1181 break;
1153 case 6: /* push */ 1182 case 6: /* push */
1154 /* 64-bit mode: PUSH always pushes a 64-bit operand. */ 1183 /* 64-bit mode: PUSH always pushes a 64-bit operand. */
1155 if (mode == X86EMUL_MODE_PROT64) { 1184 if (ctxt->mode == X86EMUL_MODE_PROT64) {
1156 c->dst.bytes = 8; 1185 c->dst.bytes = 8;
1157 if ((rc = ops->read_std( 1186 if ((rc = ops->read_std(
1158 (unsigned long)c->dst.ptr, 1187 (unsigned long)c->dst.ptr,