diff options
author | Laurent Vivier <Laurent.Vivier@bull.net> | 2007-09-24 05:10:54 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:52:48 -0500 |
commit | 8cdbd2c9bf3108c41563eef586f22fa8b5174de0 (patch) | |
tree | d64daf3bf5b9a85c667c016399352151726ba723 /drivers/kvm/x86_emulate.c | |
parent | 217648638ccb62dfeea5ac5fe768539cdee61ed0 (diff) |
KVM: x86 emulator: split some decoding into functions for readability
To improve readability, move push, writeback, and grp 1a/2/3/4/5/9 emulation
parts into functions.
Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r-- | drivers/kvm/x86_emulate.c | 451 |
1 files changed, 266 insertions, 185 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index dc9d2a870fbc..a15609279283 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c | |||
@@ -907,6 +907,244 @@ done: | |||
907 | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; | 907 | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; |
908 | } | 908 | } |
909 | 909 | ||
910 | static inline void emulate_push(struct x86_emulate_ctxt *ctxt) | ||
911 | { | ||
912 | struct decode_cache *c = &ctxt->decode; | ||
913 | |||
914 | c->dst.type = OP_MEM; | ||
915 | c->dst.bytes = c->op_bytes; | ||
916 | c->dst.val = c->src.val; | ||
917 | register_address_increment(c->regs[VCPU_REGS_RSP], -c->op_bytes); | ||
918 | c->dst.ptr = (void *) register_address(ctxt->ss_base, | ||
919 | c->regs[VCPU_REGS_RSP]); | ||
920 | } | ||
921 | |||
922 | static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt, | ||
923 | struct x86_emulate_ops *ops) | ||
924 | { | ||
925 | struct decode_cache *c = &ctxt->decode; | ||
926 | int rc; | ||
927 | |||
928 | /* 64-bit mode: POP always pops a 64-bit operand. */ | ||
929 | |||
930 | if (ctxt->mode == X86EMUL_MODE_PROT64) | ||
931 | c->dst.bytes = 8; | ||
932 | |||
933 | rc = ops->read_std(register_address(ctxt->ss_base, | ||
934 | c->regs[VCPU_REGS_RSP]), | ||
935 | &c->dst.val, c->dst.bytes, ctxt->vcpu); | ||
936 | if (rc != 0) | ||
937 | return rc; | ||
938 | |||
939 | register_address_increment(c->regs[VCPU_REGS_RSP], c->dst.bytes); | ||
940 | |||
941 | return 0; | ||
942 | } | ||
943 | |||
944 | static inline void emulate_grp2(struct decode_cache *c, unsigned long *_eflags) | ||
945 | { | ||
946 | switch (c->modrm_reg) { | ||
947 | case 0: /* rol */ | ||
948 | emulate_2op_SrcB("rol", c->src, c->dst, *_eflags); | ||
949 | break; | ||
950 | case 1: /* ror */ | ||
951 | emulate_2op_SrcB("ror", c->src, c->dst, *_eflags); | ||
952 | break; | ||
953 | case 2: /* rcl */ | ||
954 | emulate_2op_SrcB("rcl", c->src, c->dst, *_eflags); | ||
955 | break; | ||
956 | case 3: /* rcr */ | ||
957 | emulate_2op_SrcB("rcr", c->src, c->dst, *_eflags); | ||
958 | break; | ||
959 | case 4: /* sal/shl */ | ||
960 | case 6: /* sal/shl */ | ||
961 | emulate_2op_SrcB("sal", c->src, c->dst, *_eflags); | ||
962 | break; | ||
963 | case 5: /* shr */ | ||
964 | emulate_2op_SrcB("shr", c->src, c->dst, *_eflags); | ||
965 | break; | ||
966 | case 7: /* sar */ | ||
967 | emulate_2op_SrcB("sar", c->src, c->dst, *_eflags); | ||
968 | break; | ||
969 | } | ||
970 | } | ||
971 | |||
972 | static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt, | ||
973 | struct x86_emulate_ops *ops, | ||
974 | unsigned long *_eflags) | ||
975 | { | ||
976 | struct decode_cache *c = &ctxt->decode; | ||
977 | int rc = 0; | ||
978 | |||
979 | switch (c->modrm_reg) { | ||
980 | case 0 ... 1: /* test */ | ||
981 | /* | ||
982 | * Special case in Grp3: test has an immediate | ||
983 | * source operand. | ||
984 | */ | ||
985 | c->src.type = OP_IMM; | ||
986 | c->src.ptr = (unsigned long *)c->eip; | ||
987 | c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | ||
988 | if (c->src.bytes == 8) | ||
989 | c->src.bytes = 4; | ||
990 | switch (c->src.bytes) { | ||
991 | case 1: | ||
992 | c->src.val = insn_fetch(s8, 1, c->eip); | ||
993 | break; | ||
994 | case 2: | ||
995 | c->src.val = insn_fetch(s16, 2, c->eip); | ||
996 | break; | ||
997 | case 4: | ||
998 | c->src.val = insn_fetch(s32, 4, c->eip); | ||
999 | break; | ||
1000 | } | ||
1001 | emulate_2op_SrcV("test", c->src, c->dst, *_eflags); | ||
1002 | break; | ||
1003 | case 2: /* not */ | ||
1004 | c->dst.val = ~c->dst.val; | ||
1005 | break; | ||
1006 | case 3: /* neg */ | ||
1007 | emulate_1op("neg", c->dst, *_eflags); | ||
1008 | break; | ||
1009 | default: | ||
1010 | DPRINTF("Cannot emulate %02x\n", c->b); | ||
1011 | rc = X86EMUL_UNHANDLEABLE; | ||
1012 | break; | ||
1013 | } | ||
1014 | done: | ||
1015 | return rc; | ||
1016 | } | ||
1017 | |||
1018 | static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt, | ||
1019 | struct x86_emulate_ops *ops, | ||
1020 | unsigned long *_eflags, | ||
1021 | int *no_wb) | ||
1022 | { | ||
1023 | struct decode_cache *c = &ctxt->decode; | ||
1024 | int rc; | ||
1025 | |||
1026 | switch (c->modrm_reg) { | ||
1027 | case 0: /* inc */ | ||
1028 | emulate_1op("inc", c->dst, *_eflags); | ||
1029 | break; | ||
1030 | case 1: /* dec */ | ||
1031 | emulate_1op("dec", c->dst, *_eflags); | ||
1032 | break; | ||
1033 | case 4: /* jmp abs */ | ||
1034 | if (c->b == 0xff) | ||
1035 | c->eip = c->dst.val; | ||
1036 | else { | ||
1037 | DPRINTF("Cannot emulate %02x\n", c->b); | ||
1038 | return X86EMUL_UNHANDLEABLE; | ||
1039 | } | ||
1040 | break; | ||
1041 | case 6: /* push */ | ||
1042 | |||
1043 | /* 64-bit mode: PUSH always pushes a 64-bit operand. */ | ||
1044 | |||
1045 | if (ctxt->mode == X86EMUL_MODE_PROT64) { | ||
1046 | c->dst.bytes = 8; | ||
1047 | rc = ops->read_std((unsigned long)c->dst.ptr, | ||
1048 | &c->dst.val, 8, ctxt->vcpu); | ||
1049 | if (rc != 0) | ||
1050 | return rc; | ||
1051 | } | ||
1052 | register_address_increment(c->regs[VCPU_REGS_RSP], | ||
1053 | -c->dst.bytes); | ||
1054 | rc = ops->write_emulated(register_address(ctxt->ss_base, | ||
1055 | c->regs[VCPU_REGS_RSP]), &c->dst.val, | ||
1056 | c->dst.bytes, ctxt->vcpu); | ||
1057 | if (rc != 0) | ||
1058 | return rc; | ||
1059 | *no_wb = 1; | ||
1060 | break; | ||
1061 | default: | ||
1062 | DPRINTF("Cannot emulate %02x\n", c->b); | ||
1063 | return X86EMUL_UNHANDLEABLE; | ||
1064 | } | ||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt, | ||
1069 | struct x86_emulate_ops *ops, | ||
1070 | unsigned long *_eflags, | ||
1071 | unsigned long cr2) | ||
1072 | { | ||
1073 | struct decode_cache *c = &ctxt->decode; | ||
1074 | u64 old, new; | ||
1075 | int rc; | ||
1076 | |||
1077 | rc = ops->read_emulated(cr2, &old, 8, ctxt->vcpu); | ||
1078 | if (rc != 0) | ||
1079 | return rc; | ||
1080 | |||
1081 | if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) || | ||
1082 | ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) { | ||
1083 | |||
1084 | c->regs[VCPU_REGS_RAX] = (u32) (old >> 0); | ||
1085 | c->regs[VCPU_REGS_RDX] = (u32) (old >> 32); | ||
1086 | *_eflags &= ~EFLG_ZF; | ||
1087 | |||
1088 | } else { | ||
1089 | new = ((u64)c->regs[VCPU_REGS_RCX] << 32) | | ||
1090 | (u32) c->regs[VCPU_REGS_RBX]; | ||
1091 | |||
1092 | rc = ops->cmpxchg_emulated(cr2, &old, &new, 8, ctxt->vcpu); | ||
1093 | if (rc != 0) | ||
1094 | return rc; | ||
1095 | *_eflags |= EFLG_ZF; | ||
1096 | } | ||
1097 | return 0; | ||
1098 | } | ||
1099 | |||
1100 | static inline int writeback(struct x86_emulate_ctxt *ctxt, | ||
1101 | struct x86_emulate_ops *ops) | ||
1102 | { | ||
1103 | int rc; | ||
1104 | struct decode_cache *c = &ctxt->decode; | ||
1105 | |||
1106 | switch (c->dst.type) { | ||
1107 | case OP_REG: | ||
1108 | /* The 4-byte case *is* correct: | ||
1109 | * in 64-bit mode we zero-extend. | ||
1110 | */ | ||
1111 | switch (c->dst.bytes) { | ||
1112 | case 1: | ||
1113 | *(u8 *)c->dst.ptr = (u8)c->dst.val; | ||
1114 | break; | ||
1115 | case 2: | ||
1116 | *(u16 *)c->dst.ptr = (u16)c->dst.val; | ||
1117 | break; | ||
1118 | case 4: | ||
1119 | *c->dst.ptr = (u32)c->dst.val; | ||
1120 | break; /* 64b: zero-ext */ | ||
1121 | case 8: | ||
1122 | *c->dst.ptr = c->dst.val; | ||
1123 | break; | ||
1124 | } | ||
1125 | break; | ||
1126 | case OP_MEM: | ||
1127 | if (c->lock_prefix) | ||
1128 | rc = ops->cmpxchg_emulated( | ||
1129 | (unsigned long)c->dst.ptr, | ||
1130 | &c->dst.orig_val, | ||
1131 | &c->dst.val, | ||
1132 | c->dst.bytes, | ||
1133 | ctxt->vcpu); | ||
1134 | else | ||
1135 | rc = ops->write_emulated( | ||
1136 | (unsigned long)c->dst.ptr, | ||
1137 | &c->dst.val, | ||
1138 | c->dst.bytes, | ||
1139 | ctxt->vcpu); | ||
1140 | if (rc != 0) | ||
1141 | return rc; | ||
1142 | default: | ||
1143 | break; | ||
1144 | } | ||
1145 | return 0; | ||
1146 | } | ||
1147 | |||
910 | int | 1148 | int |
911 | x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | 1149 | x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) |
912 | { | 1150 | { |
@@ -1042,7 +1280,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
1042 | } | 1280 | } |
1043 | break; | 1281 | break; |
1044 | case 0x84 ... 0x85: | 1282 | case 0x84 ... 0x85: |
1045 | test: /* test */ | ||
1046 | emulate_2op_SrcV("test", c->src, c->dst, _eflags); | 1283 | emulate_2op_SrcV("test", c->src, c->dst, _eflags); |
1047 | break; | 1284 | break; |
1048 | case 0x86 ... 0x87: /* xchg */ | 1285 | case 0x86 ... 0x87: /* xchg */ |
@@ -1074,18 +1311,9 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
1074 | c->dst.val = c->modrm_val; | 1311 | c->dst.val = c->modrm_val; |
1075 | break; | 1312 | break; |
1076 | case 0x8f: /* pop (sole member of Grp1a) */ | 1313 | case 0x8f: /* pop (sole member of Grp1a) */ |
1077 | /* 64-bit mode: POP always pops a 64-bit operand. */ | 1314 | rc = emulate_grp1a(ctxt, ops); |
1078 | if (ctxt->mode == X86EMUL_MODE_PROT64) | 1315 | if (rc != 0) |
1079 | c->dst.bytes = 8; | ||
1080 | if ((rc = ops->read_std(register_address( | ||
1081 | ctxt->ss_base, | ||
1082 | c->regs[VCPU_REGS_RSP]), | ||
1083 | &c->dst.val, | ||
1084 | c->dst.bytes, | ||
1085 | ctxt->vcpu)) != 0) | ||
1086 | goto done; | 1316 | goto done; |
1087 | register_address_increment(c->regs[VCPU_REGS_RSP], | ||
1088 | c->dst.bytes); | ||
1089 | break; | 1317 | break; |
1090 | case 0xa0 ... 0xa1: /* mov */ | 1318 | case 0xa0 ... 0xa1: /* mov */ |
1091 | c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX]; | 1319 | c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX]; |
@@ -1099,31 +1327,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
1099 | c->eip += c->ad_bytes; | 1327 | c->eip += c->ad_bytes; |
1100 | break; | 1328 | break; |
1101 | case 0xc0 ... 0xc1: | 1329 | case 0xc0 ... 0xc1: |
1102 | grp2: /* Grp2 */ | 1330 | emulate_grp2(c, &_eflags); |
1103 | switch (c->modrm_reg) { | ||
1104 | case 0: /* rol */ | ||
1105 | emulate_2op_SrcB("rol", c->src, c->dst, _eflags); | ||
1106 | break; | ||
1107 | case 1: /* ror */ | ||
1108 | emulate_2op_SrcB("ror", c->src, c->dst, _eflags); | ||
1109 | break; | ||
1110 | case 2: /* rcl */ | ||
1111 | emulate_2op_SrcB("rcl", c->src, c->dst, _eflags); | ||
1112 | break; | ||
1113 | case 3: /* rcr */ | ||
1114 | emulate_2op_SrcB("rcr", c->src, c->dst, _eflags); | ||
1115 | break; | ||
1116 | case 4: /* sal/shl */ | ||
1117 | case 6: /* sal/shl */ | ||
1118 | emulate_2op_SrcB("sal", c->src, c->dst, _eflags); | ||
1119 | break; | ||
1120 | case 5: /* shr */ | ||
1121 | emulate_2op_SrcB("shr", c->src, c->dst, _eflags); | ||
1122 | break; | ||
1123 | case 7: /* sar */ | ||
1124 | emulate_2op_SrcB("sar", c->src, c->dst, _eflags); | ||
1125 | break; | ||
1126 | } | ||
1127 | break; | 1331 | break; |
1128 | case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ | 1332 | case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ |
1129 | mov: | 1333 | mov: |
@@ -1131,126 +1335,29 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
1131 | break; | 1335 | break; |
1132 | case 0xd0 ... 0xd1: /* Grp2 */ | 1336 | case 0xd0 ... 0xd1: /* Grp2 */ |
1133 | c->src.val = 1; | 1337 | c->src.val = 1; |
1134 | goto grp2; | 1338 | emulate_grp2(c, &_eflags); |
1339 | break; | ||
1135 | case 0xd2 ... 0xd3: /* Grp2 */ | 1340 | case 0xd2 ... 0xd3: /* Grp2 */ |
1136 | c->src.val = c->regs[VCPU_REGS_RCX]; | 1341 | c->src.val = c->regs[VCPU_REGS_RCX]; |
1137 | goto grp2; | 1342 | emulate_grp2(c, &_eflags); |
1343 | break; | ||
1138 | case 0xf6 ... 0xf7: /* Grp3 */ | 1344 | case 0xf6 ... 0xf7: /* Grp3 */ |
1139 | switch (c->modrm_reg) { | 1345 | rc = emulate_grp3(ctxt, ops, &_eflags); |
1140 | case 0 ... 1: /* test */ | 1346 | if (rc != 0) |
1141 | /* | 1347 | goto done; |
1142 | * Special case in Grp3: test has an immediate | ||
1143 | * source operand. | ||
1144 | */ | ||
1145 | c->src.type = OP_IMM; | ||
1146 | c->src.ptr = (unsigned long *)c->eip; | ||
1147 | c->src.bytes = (c->d & ByteOp) ? 1 : | ||
1148 | c->op_bytes; | ||
1149 | if (c->src.bytes == 8) | ||
1150 | c->src.bytes = 4; | ||
1151 | switch (c->src.bytes) { | ||
1152 | case 1: | ||
1153 | c->src.val = insn_fetch(s8, 1, c->eip); | ||
1154 | break; | ||
1155 | case 2: | ||
1156 | c->src.val = insn_fetch(s16, 2, c->eip); | ||
1157 | break; | ||
1158 | case 4: | ||
1159 | c->src.val = insn_fetch(s32, 4, c->eip); | ||
1160 | break; | ||
1161 | } | ||
1162 | goto test; | ||
1163 | case 2: /* not */ | ||
1164 | c->dst.val = ~c->dst.val; | ||
1165 | break; | ||
1166 | case 3: /* neg */ | ||
1167 | emulate_1op("neg", c->dst, _eflags); | ||
1168 | break; | ||
1169 | default: | ||
1170 | goto cannot_emulate; | ||
1171 | } | ||
1172 | break; | 1348 | break; |
1173 | case 0xfe ... 0xff: /* Grp4/Grp5 */ | 1349 | case 0xfe ... 0xff: /* Grp4/Grp5 */ |
1174 | switch (c->modrm_reg) { | 1350 | rc = emulate_grp45(ctxt, ops, &_eflags, &no_wb); |
1175 | case 0: /* inc */ | 1351 | if (rc != 0) |
1176 | emulate_1op("inc", c->dst, _eflags); | 1352 | goto done; |
1177 | break; | ||
1178 | case 1: /* dec */ | ||
1179 | emulate_1op("dec", c->dst, _eflags); | ||
1180 | break; | ||
1181 | case 4: /* jmp abs */ | ||
1182 | if (c->b == 0xff) | ||
1183 | c->eip = c->dst.val; | ||
1184 | else | ||
1185 | goto cannot_emulate; | ||
1186 | break; | ||
1187 | case 6: /* push */ | ||
1188 | /* 64-bit mode: PUSH always pushes a 64-bit operand. */ | ||
1189 | if (ctxt->mode == X86EMUL_MODE_PROT64) { | ||
1190 | c->dst.bytes = 8; | ||
1191 | if ((rc = ops->read_std( | ||
1192 | (unsigned long)c->dst.ptr, | ||
1193 | &c->dst.val, 8, | ||
1194 | ctxt->vcpu)) != 0) | ||
1195 | goto done; | ||
1196 | } | ||
1197 | register_address_increment(c->regs[VCPU_REGS_RSP], | ||
1198 | -c->dst.bytes); | ||
1199 | if ((rc = ops->write_emulated( | ||
1200 | register_address(ctxt->ss_base, | ||
1201 | c->regs[VCPU_REGS_RSP]), | ||
1202 | &c->dst.val, | ||
1203 | c->dst.bytes, ctxt->vcpu)) != 0) | ||
1204 | goto done; | ||
1205 | no_wb = 1; | ||
1206 | break; | ||
1207 | default: | ||
1208 | goto cannot_emulate; | ||
1209 | } | ||
1210 | break; | 1353 | break; |
1211 | } | 1354 | } |
1212 | 1355 | ||
1213 | writeback: | 1356 | writeback: |
1214 | if (!no_wb) { | 1357 | if (!no_wb) { |
1215 | switch (c->dst.type) { | 1358 | rc = writeback(ctxt, ops); |
1216 | case OP_REG: | 1359 | if (rc != 0) |
1217 | /* The 4-byte case *is* correct: | 1360 | goto done; |
1218 | * in 64-bit mode we zero-extend. | ||
1219 | */ | ||
1220 | switch (c->dst.bytes) { | ||
1221 | case 1: | ||
1222 | *(u8 *)c->dst.ptr = (u8)c->dst.val; | ||
1223 | break; | ||
1224 | case 2: | ||
1225 | *(u16 *)c->dst.ptr = (u16)c->dst.val; | ||
1226 | break; | ||
1227 | case 4: | ||
1228 | *c->dst.ptr = (u32)c->dst.val; | ||
1229 | break; /* 64b: zero-ext */ | ||
1230 | case 8: | ||
1231 | *c->dst.ptr = c->dst.val; | ||
1232 | break; | ||
1233 | } | ||
1234 | break; | ||
1235 | case OP_MEM: | ||
1236 | if (c->lock_prefix) | ||
1237 | rc = ops->cmpxchg_emulated( | ||
1238 | (unsigned long)c->dst.ptr, | ||
1239 | &c->dst.orig_val, | ||
1240 | &c->dst.val, | ||
1241 | c->dst.bytes, | ||
1242 | ctxt->vcpu); | ||
1243 | else | ||
1244 | rc = ops->write_emulated( | ||
1245 | (unsigned long)c->dst.ptr, | ||
1246 | &c->dst.val, | ||
1247 | c->dst.bytes, | ||
1248 | ctxt->vcpu); | ||
1249 | if (rc != 0) | ||
1250 | goto done; | ||
1251 | default: | ||
1252 | break; | ||
1253 | } | ||
1254 | } | 1361 | } |
1255 | 1362 | ||
1256 | /* Commit shadow register state. */ | 1363 | /* Commit shadow register state. */ |
@@ -1283,8 +1390,7 @@ special_insn: | |||
1283 | ctxt->ss_base, c->regs[VCPU_REGS_RSP]); | 1390 | ctxt->ss_base, c->regs[VCPU_REGS_RSP]); |
1284 | break; | 1391 | break; |
1285 | case 0x58 ... 0x5f: /* pop reg */ | 1392 | case 0x58 ... 0x5f: /* pop reg */ |
1286 | c->dst.ptr = | 1393 | c->dst.ptr = (unsigned long *)&c->regs[c->b & 0x7]; |
1287 | (unsigned long *)&c->regs[c->b & 0x7]; | ||
1288 | pop_instruction: | 1394 | pop_instruction: |
1289 | if ((rc = ops->read_std(register_address(ctxt->ss_base, | 1395 | if ((rc = ops->read_std(register_address(ctxt->ss_base, |
1290 | c->regs[VCPU_REGS_RSP]), c->dst.ptr, | 1396 | c->regs[VCPU_REGS_RSP]), c->dst.ptr, |
@@ -1298,14 +1404,7 @@ special_insn: | |||
1298 | case 0x6a: /* push imm8 */ | 1404 | case 0x6a: /* push imm8 */ |
1299 | c->src.val = 0L; | 1405 | c->src.val = 0L; |
1300 | c->src.val = insn_fetch(s8, 1, c->eip); | 1406 | c->src.val = insn_fetch(s8, 1, c->eip); |
1301 | push: | 1407 | emulate_push(ctxt); |
1302 | c->dst.type = OP_MEM; | ||
1303 | c->dst.bytes = c->op_bytes; | ||
1304 | c->dst.val = c->src.val; | ||
1305 | register_address_increment(c->regs[VCPU_REGS_RSP], | ||
1306 | -c->op_bytes); | ||
1307 | c->dst.ptr = (void *) register_address(ctxt->ss_base, | ||
1308 | c->regs[VCPU_REGS_RSP]); | ||
1309 | break; | 1408 | break; |
1310 | case 0x6c: /* insb */ | 1409 | case 0x6c: /* insb */ |
1311 | case 0x6d: /* insw/insd */ | 1410 | case 0x6d: /* insw/insd */ |
@@ -1350,7 +1449,8 @@ push: | |||
1350 | } | 1449 | } |
1351 | case 0x9c: /* pushf */ | 1450 | case 0x9c: /* pushf */ |
1352 | c->src.val = (unsigned long) _eflags; | 1451 | c->src.val = (unsigned long) _eflags; |
1353 | goto push; | 1452 | emulate_push(ctxt); |
1453 | break; | ||
1354 | case 0x9d: /* popf */ | 1454 | case 0x9d: /* popf */ |
1355 | c->dst.ptr = (unsigned long *) &_eflags; | 1455 | c->dst.ptr = (unsigned long *) &_eflags; |
1356 | goto pop_instruction; | 1456 | goto pop_instruction; |
@@ -1436,7 +1536,8 @@ push: | |||
1436 | c->src.val = (unsigned long) c->eip; | 1536 | c->src.val = (unsigned long) c->eip; |
1437 | JMP_REL(rel); | 1537 | JMP_REL(rel); |
1438 | c->op_bytes = c->ad_bytes; | 1538 | c->op_bytes = c->ad_bytes; |
1439 | goto push; | 1539 | emulate_push(ctxt); |
1540 | break; | ||
1440 | } | 1541 | } |
1441 | case 0xe9: /* jmp rel */ | 1542 | case 0xe9: /* jmp rel */ |
1442 | case 0xeb: /* jmp rel short */ | 1543 | case 0xeb: /* jmp rel short */ |
@@ -1511,8 +1612,7 @@ twobyte_insn: | |||
1511 | no_wb = 1; | 1612 | no_wb = 1; |
1512 | if (c->modrm_mod != 3) | 1613 | if (c->modrm_mod != 3) |
1513 | goto cannot_emulate; | 1614 | goto cannot_emulate; |
1514 | rc = emulator_get_dr(ctxt, c->modrm_reg, | 1615 | rc = emulator_get_dr(ctxt, c->modrm_reg, &c->regs[c->modrm_rm]); |
1515 | &c->regs[c->modrm_rm]); | ||
1516 | break; | 1616 | break; |
1517 | case 0x23: /* mov from reg to dr */ | 1617 | case 0x23: /* mov from reg to dr */ |
1518 | no_wb = 1; | 1618 | no_wb = 1; |
@@ -1668,8 +1768,7 @@ twobyte_special_insn: | |||
1668 | break; | 1768 | break; |
1669 | case 0x32: | 1769 | case 0x32: |
1670 | /* rdmsr */ | 1770 | /* rdmsr */ |
1671 | rc = kvm_get_msr(ctxt->vcpu, | 1771 | rc = kvm_get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data); |
1672 | c->regs[VCPU_REGS_RCX], &msr_data); | ||
1673 | if (rc) { | 1772 | if (rc) { |
1674 | kvm_x86_ops->inject_gp(ctxt->vcpu, 0); | 1773 | kvm_x86_ops->inject_gp(ctxt->vcpu, 0); |
1675 | c->eip = ctxt->vcpu->rip; | 1774 | c->eip = ctxt->vcpu->rip; |
@@ -1701,28 +1800,10 @@ twobyte_special_insn: | |||
1701 | break; | 1800 | break; |
1702 | } | 1801 | } |
1703 | case 0xc7: /* Grp9 (cmpxchg8b) */ | 1802 | case 0xc7: /* Grp9 (cmpxchg8b) */ |
1704 | { | 1803 | rc = emulate_grp9(ctxt, ops, &_eflags, cr2); |
1705 | u64 old, new; | 1804 | if (rc != 0) |
1706 | if ((rc = ops->read_emulated(cr2, &old, 8, ctxt->vcpu)) | 1805 | goto done; |
1707 | != 0) | 1806 | break; |
1708 | goto done; | ||
1709 | if (((u32) (old >> 0) != | ||
1710 | (u32) c->regs[VCPU_REGS_RAX]) || | ||
1711 | ((u32) (old >> 32) != | ||
1712 | (u32) c->regs[VCPU_REGS_RDX])) { | ||
1713 | c->regs[VCPU_REGS_RAX] = (u32) (old >> 0); | ||
1714 | c->regs[VCPU_REGS_RDX] = (u32) (old >> 32); | ||
1715 | _eflags &= ~EFLG_ZF; | ||
1716 | } else { | ||
1717 | new = ((u64)c->regs[VCPU_REGS_RCX] << 32) | ||
1718 | | (u32) c->regs[VCPU_REGS_RBX]; | ||
1719 | if ((rc = ops->cmpxchg_emulated(cr2, &old, | ||
1720 | &new, 8, ctxt->vcpu)) != 0) | ||
1721 | goto done; | ||
1722 | _eflags |= EFLG_ZF; | ||
1723 | } | ||
1724 | break; | ||
1725 | } | ||
1726 | } | 1807 | } |
1727 | goto writeback; | 1808 | goto writeback; |
1728 | 1809 | ||