qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH][SVM] put valid data into exit_int_info if needed


From: Gleb Natapov
Subject: [Qemu-devel] [PATCH][SVM] put valid data into exit_int_info if needed
Date: Mon, 20 Apr 2009 16:34:39 +0300

If fault happened during event delivery exit_int_info should contain
valid info about the event on vm exit.

Signed-off-by: Gleb Natapov <address@hidden>

diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index be09263..091c724 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -595,6 +595,21 @@ static inline unsigned int get_sp_mask(unsigned int e2)
         return 0xffff;
 }
 
+static int exeption_has_error_code(int intno)
+{
+        switch(intno) {
+        case 8:
+        case 10:
+        case 11:
+        case 12:
+        case 13:
+        case 14:
+        case 17:
+            return 1;
+        }
+       return 0;
+}
+
 #ifdef TARGET_X86_64
 #define SET_ESP(val, sp_mask)\
 do {\
@@ -650,19 +665,8 @@ static void do_interrupt_protected(int intno, int is_int, 
int error_code,
     uint32_t old_eip, sp_mask;
 
     has_error_code = 0;
-    if (!is_int && !is_hw) {
-        switch(intno) {
-        case 8:
-        case 10:
-        case 11:
-        case 12:
-        case 13:
-        case 14:
-        case 17:
-            has_error_code = 1;
-            break;
-        }
-    }
+    if (!is_int && !is_hw)
+        has_error_code = exeption_has_error_code(intno);
     if (is_int)
         old_eip = next_eip;
     else
@@ -886,19 +890,8 @@ static void do_interrupt64(int intno, int is_int, int 
error_code,
     target_ulong old_eip, esp, offset;
 
     has_error_code = 0;
-    if (!is_int && !is_hw) {
-        switch(intno) {
-        case 8:
-        case 10:
-        case 11:
-        case 12:
-        case 13:
-        case 14:
-        case 17:
-            has_error_code = 1;
-            break;
-        }
-    }
+    if (!is_int && !is_hw)
+        has_error_code = exeption_has_error_code(intno);
     if (is_int)
         old_eip = next_eip;
     else
@@ -1198,6 +1191,25 @@ void do_interrupt_user(int intno, int is_int, int 
error_code,
         EIP = next_eip;
 }
 
+static void handle_even_inj(int intno, int is_int, int error_code,
+               int is_hw, int rm)
+{
+    uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.event_inj));
+    if (!(event_inj & SVM_EVTINJ_VALID)) {
+           int type;
+           if (is_int)
+                   type = SVM_EVTINJ_TYPE_SOFT;
+           else
+                   type = SVM_EVTINJ_TYPE_EXEPT;
+           event_inj = intno | type | SVM_EVTINJ_VALID;
+           if (!rm && exeption_has_error_code(intno)) {
+                   event_inj |= SVM_EVTINJ_VALID_ERR;
+                   stl_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.event_inj_err), error_code);
+           }
+           stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), 
event_inj);
+    }
+}
+
 /*
  * Begin execution of an interruption. is_int is TRUE if coming from
  * 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,
         }
     }
     if (env->cr[0] & CR0_PE_MASK) {
+        if (env->hflags & HF_SVMI_MASK)
+            handle_even_inj(intno, is_int, error_code, is_hw, 0);
 #ifdef TARGET_X86_64
         if (env->hflags & HF_LMA_MASK) {
             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,
             do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
         }
     } else {
+        if (env->hflags & HF_SVMI_MASK)
+            handle_even_inj(intno, is_int, error_code, is_hw, 1);
         do_interrupt_real(intno, is_int, error_code, next_eip);
     }
+
+    if (env->hflags & HF_SVMI_MASK) {
+           uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.event_inj));
+           stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), 
event_inj & ~SVM_EVTINJ_VALID);
+    }
 }
 
 /* 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)
         uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
         uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
         uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.event_inj_err));
-        stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), 
event_inj & ~SVM_EVTINJ_VALID);
 
         qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err);
         /* FIXME: need to implement valid_err */
@@ -5332,6 +5352,11 @@ void helper_vmexit(uint32_t exit_code, uint64_t 
exit_info_1)
     stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), 
exit_code);
     stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), 
exit_info_1);
 
+    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info),
+             ldl_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.event_inj)));
+    stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info_err),
+             ldl_phys(env->vm_vmcb + offsetof(struct vmcb, 
control.event_inj_err)));
+
     env->hflags2 &= ~HF2_GIF_MASK;
     /* FIXME: Resets the current ASID register to zero (host ASID). */
 
--
                        Gleb.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]