Commit 2ed51f5bfda2c5bb903a9abaa21c0e756f8486bd

Authored by aliguori
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,6 +595,21 @@ static inline unsigned int get_sp_mask(unsigned int e2)
595 return 0xffff; 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 #ifdef TARGET_X86_64 613 #ifdef TARGET_X86_64
599 #define SET_ESP(val, sp_mask)\ 614 #define SET_ESP(val, sp_mask)\
600 do {\ 615 do {\
@@ -650,19 +665,8 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, @@ -650,19 +665,8 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
650 uint32_t old_eip, sp_mask; 665 uint32_t old_eip, sp_mask;
651 666
652 has_error_code = 0; 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 if (is_int) 670 if (is_int)
667 old_eip = next_eip; 671 old_eip = next_eip;
668 else 672 else
@@ -886,19 +890,8 @@ static void do_interrupt64(int intno, int is_int, int error_code, @@ -886,19 +890,8 @@ static void do_interrupt64(int intno, int is_int, int error_code,
886 target_ulong old_eip, esp, offset; 890 target_ulong old_eip, esp, offset;
887 891
888 has_error_code = 0; 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 if (is_int) 895 if (is_int)
903 old_eip = next_eip; 896 old_eip = next_eip;
904 else 897 else
@@ -1198,6 +1191,25 @@ void do_interrupt_user(int intno, int is_int, int error_code, @@ -1198,6 +1191,25 @@ void do_interrupt_user(int intno, int is_int, int error_code,
1198 EIP = next_eip; 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 * Begin execution of an interruption. is_int is TRUE if coming from 1214 * Begin execution of an interruption. is_int is TRUE if coming from
1203 * the int instruction. next_eip is the EIP value AFTER the interrupt 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,6 +1250,8 @@ void do_interrupt(int intno, int is_int, int error_code,
1238 } 1250 }
1239 } 1251 }
1240 if (env->cr[0] & CR0_PE_MASK) { 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 #ifdef TARGET_X86_64 1255 #ifdef TARGET_X86_64
1242 if (env->hflags & HF_LMA_MASK) { 1256 if (env->hflags & HF_LMA_MASK) {
1243 do_interrupt64(intno, is_int, error_code, next_eip, is_hw); 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,8 +1261,15 @@ void do_interrupt(int intno, int is_int, int error_code,
1247 do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); 1261 do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1248 } 1262 }
1249 } else { 1263 } else {
  1264 + if (env->hflags & HF_SVMI_MASK)
  1265 + handle_even_inj(intno, is_int, error_code, is_hw, 1);
1250 do_interrupt_real(intno, is_int, error_code, next_eip); 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 /* This should come from sysemu.h - if we could include it here... */ 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,7 +5015,6 @@ void helper_vmrun(int aflag, int next_eip_addend)
4994 uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK; 5015 uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
4995 uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR; 5016 uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
4996 uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err)); 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 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err); 5019 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err);
5000 /* FIXME: need to implement valid_err */ 5020 /* FIXME: need to implement valid_err */
@@ -5332,6 +5352,11 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) @@ -5332,6 +5352,11 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
5332 stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code); 5352 stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
5333 stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1); 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 env->hflags2 &= ~HF2_GIF_MASK; 5360 env->hflags2 &= ~HF2_GIF_MASK;
5336 /* FIXME: Resets the current ASID register to zero (host ASID). */ 5361 /* FIXME: Resets the current ASID register to zero (host ASID). */
5337 5362