update
[qemu] / cpu-exec.c
index 615915c..ddbeb2c 100644 (file)
@@ -29,8 +29,6 @@
 
 //#define DEBUG_EXEC
 //#define DEBUG_SIGNAL
-/* enable it to have a fully working x86 emulator for ring 0 */
-//#define RING0_HACKS
 
 #if defined(TARGET_ARM)
 /* XXX: unify with i386 target */
@@ -73,7 +71,7 @@ int cpu_exec(CPUState *env1)
 #ifdef __sparc__
     int saved_i7, tmp_T0;
 #endif
-    int code_gen_size, ret;
+    int code_gen_size, ret, interrupt_request;
     void (*gen_func)(void);
     TranslationBlock *tb, **ptb;
     uint8_t *tc_ptr, *cs_base, *pc;
@@ -141,7 +139,6 @@ int cpu_exec(CPUState *env1)
 #else
 #error unsupported target CPU
 #endif
-    env->interrupt_request = 0;
     env->exception_index = -1;
 
     /* prepare setjmp context for exception handling */
@@ -157,13 +154,16 @@ int cpu_exec(CPUState *env1)
                     /* if user mode only, we simulate a fake exception
                        which will be hanlded outside the cpu execution
                        loop */
+#if defined(TARGET_I386)
                     do_interrupt_user(env->exception_index, 
                                       env->exception_is_int, 
                                       env->error_code, 
                                       env->exception_next_eip);
+#endif
                     ret = env->exception_index;
                     break;
                 } else {
+#if defined(TARGET_I386)
                     /* simulate a real cpu exception. On i386, it can
                        trigger new exceptions, but we do not handle
                        double or triple faults yet. */
@@ -171,31 +171,43 @@ int cpu_exec(CPUState *env1)
                                  env->exception_is_int, 
                                  env->error_code, 
                                  env->exception_next_eip);
+#endif
                 }
                 env->exception_index = -1;
             }
-#if defined(TARGET_I386)
-            /* if hardware interrupt pending, we execute it */
-            if (env->hard_interrupt_request &&
-                (env->eflags & IF_MASK)) {
-                int intno;
-                intno = cpu_x86_get_pic_interrupt(env);
-                if (loglevel) {
-                    fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
-                }
-                do_interrupt(intno, 0, 0, 0);
-                env->hard_interrupt_request = 0;
-            }
-#endif
             T0 = 0; /* force lookup of first TB */
             for(;;) {
 #ifdef __sparc__
                 /* g1 can be modified by some libc? functions */ 
                 tmp_T0 = T0;
 #endif     
-                if (env->interrupt_request) {
-                    env->exception_index = EXCP_INTERRUPT;
-                    cpu_loop_exit();
+                interrupt_request = env->interrupt_request;
+                if (interrupt_request) {
+#if defined(TARGET_I386)
+                    /* if hardware interrupt pending, we execute it */
+                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+                        (env->eflags & IF_MASK)) {
+                        int intno;
+                        intno = cpu_x86_get_pic_interrupt(env);
+                        if (loglevel) {
+                            fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
+                        }
+                        do_interrupt(intno, 0, 0, 0);
+                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+                        /* ensure that no TB jump will be modified as
+                           the program flow was changed */
+#ifdef __sparc__
+                        tmp_T0 = 0;
+#else
+                        T0 = 0;
+#endif
+                    }
+#endif
+                    if (interrupt_request & CPU_INTERRUPT_EXIT) {
+                        env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
+                        env->exception_index = EXCP_INTERRUPT;
+                        cpu_loop_exit();
+                    }
                 }
 #ifdef DEBUG_EXEC
                 if (loglevel) {
@@ -210,7 +222,7 @@ int cpu_exec(CPUState *env1)
                     env->regs[R_EBP] = EBP;
                     env->regs[R_ESP] = ESP;
                     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
-                    cpu_x86_dump_state(env, logfile, 0);
+                    cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
                     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
 #elif defined(TARGET_ARM)
                     cpu_arm_dump_state(env, logfile, 0);
@@ -294,8 +306,6 @@ int cpu_exec(CPUState *env1)
                 T0 = tmp_T0;
 #endif     
                 /* see if we can patch the calling TB. XXX: remove TF test */
-#ifndef RING0_HACKS
-
                 if (T0 != 0 
 #if defined(TARGET_I386)
                     && !(env->eflags & TF_MASK)
@@ -305,9 +315,8 @@ int cpu_exec(CPUState *env1)
                     tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb);
                     spin_unlock(&tb_lock);
                 }
-#endif
                 tc_ptr = tb->tc_ptr;
-                
+                env->current_tb = tb;
                 /* execute the generated code */
                 gen_func = (void *)tc_ptr;
 #if defined(__sparc__)
@@ -326,6 +335,7 @@ int cpu_exec(CPUState *env1)
 #else
                 gen_func();
 #endif
+                env->current_tb = NULL;
             }
         } else {
         }
@@ -381,12 +391,6 @@ int cpu_exec(CPUState *env1)
     return ret;
 }
 
-void cpu_interrupt(CPUState *s)
-{
-    s->interrupt_request = 1;
-}
-
-
 #if defined(TARGET_I386)
 
 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
@@ -460,10 +464,9 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
 {
     TranslationBlock *tb;
     int ret;
-    
-#ifdef RING0_HACKS
-    env = global_env; /* XXX: find a better solution */
-#endif
+
+    if (cpu_single_env)
+        env = cpu_single_env; /* XXX: find a correct solution for multithread */
 #if defined(DEBUG_SIGNAL)
     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
            pc, address, is_write, *(unsigned long *)old_set);