Commit 2ed51f5bfda2c5bb903a9abaa21c0e756f8486bd
1 parent
e268ca52
put valid data into exit_int_info if needed (Gleb Natapov)
If fault happened during event delivery exit_int_info should contain valid info about the event on vm exit. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7230 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
52 additions
and
27 deletions
target-i386/op_helper.c
... | ... | @@ -595,6 +595,21 @@ static inline unsigned int get_sp_mask(unsigned int e2) |
595 | 595 | return 0xffff; |
596 | 596 | } |
597 | 597 | |
598 | +static int exeption_has_error_code(int intno) | |
599 | +{ | |
600 | + switch(intno) { | |
601 | + case 8: | |
602 | + case 10: | |
603 | + case 11: | |
604 | + case 12: | |
605 | + case 13: | |
606 | + case 14: | |
607 | + case 17: | |
608 | + return 1; | |
609 | + } | |
610 | + return 0; | |
611 | +} | |
612 | + | |
598 | 613 | #ifdef TARGET_X86_64 |
599 | 614 | #define SET_ESP(val, sp_mask)\ |
600 | 615 | do {\ |
... | ... | @@ -650,19 +665,8 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
650 | 665 | uint32_t old_eip, sp_mask; |
651 | 666 | |
652 | 667 | has_error_code = 0; |
653 | - if (!is_int && !is_hw) { | |
654 | - switch(intno) { | |
655 | - case 8: | |
656 | - case 10: | |
657 | - case 11: | |
658 | - case 12: | |
659 | - case 13: | |
660 | - case 14: | |
661 | - case 17: | |
662 | - has_error_code = 1; | |
663 | - break; | |
664 | - } | |
665 | - } | |
668 | + if (!is_int && !is_hw) | |
669 | + has_error_code = exeption_has_error_code(intno); | |
666 | 670 | if (is_int) |
667 | 671 | old_eip = next_eip; |
668 | 672 | else |
... | ... | @@ -886,19 +890,8 @@ static void do_interrupt64(int intno, int is_int, int error_code, |
886 | 890 | target_ulong old_eip, esp, offset; |
887 | 891 | |
888 | 892 | has_error_code = 0; |
889 | - if (!is_int && !is_hw) { | |
890 | - switch(intno) { | |
891 | - case 8: | |
892 | - case 10: | |
893 | - case 11: | |
894 | - case 12: | |
895 | - case 13: | |
896 | - case 14: | |
897 | - case 17: | |
898 | - has_error_code = 1; | |
899 | - break; | |
900 | - } | |
901 | - } | |
893 | + if (!is_int && !is_hw) | |
894 | + has_error_code = exeption_has_error_code(intno); | |
902 | 895 | if (is_int) |
903 | 896 | old_eip = next_eip; |
904 | 897 | else |
... | ... | @@ -1198,6 +1191,25 @@ void do_interrupt_user(int intno, int is_int, int error_code, |
1198 | 1191 | EIP = next_eip; |
1199 | 1192 | } |
1200 | 1193 | |
1194 | +static void handle_even_inj(int intno, int is_int, int error_code, | |
1195 | + int is_hw, int rm) | |
1196 | +{ | |
1197 | + uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)); | |
1198 | + if (!(event_inj & SVM_EVTINJ_VALID)) { | |
1199 | + int type; | |
1200 | + if (is_int) | |
1201 | + type = SVM_EVTINJ_TYPE_SOFT; | |
1202 | + else | |
1203 | + type = SVM_EVTINJ_TYPE_EXEPT; | |
1204 | + event_inj = intno | type | SVM_EVTINJ_VALID; | |
1205 | + if (!rm && exeption_has_error_code(intno)) { | |
1206 | + event_inj |= SVM_EVTINJ_VALID_ERR; | |
1207 | + stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err), error_code); | |
1208 | + } | |
1209 | + stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj); | |
1210 | + } | |
1211 | +} | |
1212 | + | |
1201 | 1213 | /* |
1202 | 1214 | * Begin execution of an interruption. is_int is TRUE if coming from |
1203 | 1215 | * the int instruction. next_eip is the EIP value AFTER the interrupt |
... | ... | @@ -1238,6 +1250,8 @@ void do_interrupt(int intno, int is_int, int error_code, |
1238 | 1250 | } |
1239 | 1251 | } |
1240 | 1252 | if (env->cr[0] & CR0_PE_MASK) { |
1253 | + if (env->hflags & HF_SVMI_MASK) | |
1254 | + handle_even_inj(intno, is_int, error_code, is_hw, 0); | |
1241 | 1255 | #ifdef TARGET_X86_64 |
1242 | 1256 | if (env->hflags & HF_LMA_MASK) { |
1243 | 1257 | do_interrupt64(intno, is_int, error_code, next_eip, is_hw); |
... | ... | @@ -1247,8 +1261,15 @@ void do_interrupt(int intno, int is_int, int error_code, |
1247 | 1261 | do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); |
1248 | 1262 | } |
1249 | 1263 | } else { |
1264 | + if (env->hflags & HF_SVMI_MASK) | |
1265 | + handle_even_inj(intno, is_int, error_code, is_hw, 1); | |
1250 | 1266 | do_interrupt_real(intno, is_int, error_code, next_eip); |
1251 | 1267 | } |
1268 | + | |
1269 | + if (env->hflags & HF_SVMI_MASK) { | |
1270 | + uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)); | |
1271 | + stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID); | |
1272 | + } | |
1252 | 1273 | } |
1253 | 1274 | |
1254 | 1275 | /* This should come from sysemu.h - if we could include it here... */ |
... | ... | @@ -4994,7 +5015,6 @@ void helper_vmrun(int aflag, int next_eip_addend) |
4994 | 5015 | uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK; |
4995 | 5016 | uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR; |
4996 | 5017 | uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err)); |
4997 | - stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID); | |
4998 | 5018 | |
4999 | 5019 | qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err); |
5000 | 5020 | /* FIXME: need to implement valid_err */ |
... | ... | @@ -5332,6 +5352,11 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) |
5332 | 5352 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code); |
5333 | 5353 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1); |
5334 | 5354 | |
5355 | + stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info), | |
5356 | + ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj))); | |
5357 | + stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info_err), | |
5358 | + ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err))); | |
5359 | + | |
5335 | 5360 | env->hflags2 &= ~HF2_GIF_MASK; |
5336 | 5361 | /* FIXME: Resets the current ASID register to zero (host ASID). */ |
5337 | 5362 | ... | ... |