cpu-exec: unify do_interrupt call

Upstream e694d4e289b05d0c9b118850eff961aa9ca33183
Upstream 3c688828bcb3afa2744e1f1729a40eef4a575b56
Upstream d8108fb187bb68459cfe7dca4b5c983db33bcc7b

Change-Id: Ia492dae677ddfe052768b943f8ea275fab8a9c49
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index f3b369a..27fa615 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -21,7 +21,6 @@
 
 #define CPU_NO_GLOBAL_REGS
 #include "exec.h"
-#include "exec/exec-all.h"
 #include "qemu/host-utils.h"
 
 //#define DEBUG_PCALL
@@ -1157,9 +1156,10 @@
     env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
 }
 
+#if defined(CONFIG_USER_ONLY)
 /* fake user mode interrupt */
-void do_interrupt_user(int intno, int is_int, int error_code,
-                       target_ulong next_eip)
+static void do_interrupt_user(int intno, int is_int, int error_code,
+                              target_ulong next_eip)
 {
     SegmentCache *dt;
     target_ulong ptr;
@@ -1188,7 +1188,8 @@
         EIP = next_eip;
 }
 
-#if !defined(CONFIG_USER_ONLY)
+#else
+
 static void handle_even_inj(int intno, int is_int, int error_code,
 		int is_hw, int rm)
 {
@@ -1214,8 +1215,8 @@
  * the int instruction. next_eip is the EIP value AFTER the interrupt
  * instruction. It is only relevant if is_int is TRUE.
  */
-void do_interrupt(int intno, int is_int, int error_code,
-                  target_ulong next_eip, int is_hw)
+static void do_interrupt_all(int intno, int is_int, int error_code,
+                             target_ulong next_eip, int is_hw)
 {
     if (qemu_loglevel_mask(CPU_LOG_INT)) {
         if ((env->cr[0] & CR0_PE_MASK)) {
@@ -1271,12 +1272,52 @@
 
 #if !defined(CONFIG_USER_ONLY)
     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);
+        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);
     }
 #endif
 }
 
+void do_interrupt(CPUArchState *env1)
+{
+    CPUArchState *saved_env;
+
+    saved_env = env;
+    env = env1;
+#if defined(CONFIG_USER_ONLY)
+    /* if user mode only, we simulate a fake exception
+       which will be handled outside the cpu execution
+       loop */
+    do_interrupt_user(env->exception_index,
+                      env->exception_is_int,
+                      env->error_code,
+                      env->exception_next_eip);
+    /* successfully delivered */
+    env->old_exception = -1;
+#else
+    /* simulate a real cpu exception. On i386, it can
+       trigger new exceptions, but we do not handle
+       double or triple faults yet. */
+    do_interrupt_all(env->exception_index,
+                     env->exception_is_int,
+                     env->error_code,
+                     env->exception_next_eip, 0);
+    /* successfully delivered */
+    env->old_exception = -1;
+#endif
+    env = saved_env;
+}
+
+void do_interrupt_x86_hardirq(CPUArchState *env1, int intno, int is_hw)
+{
+    CPUArchState *saved_env;
+
+    saved_env = env;
+    env = env1;
+    do_interrupt_all(intno, 0, 0, 0, is_hw);
+    env = saved_env;
+}
+
 /* This should come from sysemu.h - if we could include it here... */
 void qemu_system_reset_request(void);
 
@@ -1361,7 +1402,7 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_smm_enter(void)
+void do_smm_enter(CPUArchState *env1)
 {
 }
 
@@ -1377,11 +1418,15 @@
 #define SMM_REVISION_ID 0x00020000
 #endif
 
-void do_smm_enter(void)
+void do_smm_enter(CPUArchState *env1)
 {
     target_ulong sm_state;
     SegmentCache *dt;
     int i, offset;
+    CPUArchState *saved_env;
+
+    saved_env = env;
+    env = env1;
 
     qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
     log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
@@ -1508,6 +1553,7 @@
     cpu_x86_update_cr4(env, 0);
     env->dr[7] = 0x00000400;
     CC_OP = CC_OP_EFLAGS;
+    env = saved_env;
 }
 
 void helper_rsm(void)
@@ -4845,6 +4891,10 @@
 {
 }
 
+void svm_check_intercept(CPUArchState *env1, uint32_t type)
+{
+}
+
 void helper_svm_check_io(uint32_t port, uint32_t param,
                          uint32_t next_eip_addend)
 {
@@ -5026,7 +5076,7 @@
                 env->exception_next_eip = -1;
                 qemu_log_mask(CPU_LOG_TB_IN_ASM, "INTR");
                 /* XXX: is it always correct ? */
-                do_interrupt(vector, 0, 0, 0, 1);
+                do_interrupt_all(vector, 0, 0, 0, 1);
                 break;
         case SVM_EVTINJ_TYPE_NMI:
                 env->exception_index = EXCP02_NMI;
@@ -5235,6 +5285,17 @@
     }
 }
 
+void svm_check_intercept(CPUArchState *env1, uint32_t type)
+{
+    CPUArchState *saved_env;
+
+    saved_env = env;
+    env = env1;
+    helper_svm_check_intercept_param(type, 0);
+    env = saved_env;
+}
+
+
 void helper_svm_check_io(uint32_t port, uint32_t param,
                          uint32_t next_eip_addend)
 {
@@ -5548,6 +5609,18 @@
     }
 }
 
+uint32_t cpu_cc_compute_all(CPUArchState *env1, int op)
+{
+    CPUArchState *saved_env;
+    uint32_t ret;
+
+    saved_env = env;
+    env = env1;
+    ret = helper_cc_compute_all(op);
+    env = saved_env;
+    return ret;
+}
+
 uint32_t helper_cc_compute_c(int op)
 {
     switch (op) {