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 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  
... ...