qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Glauber Costa <gcosta@redhat.com>
To: qemu-devel@nongnu.org
Cc: kvm@vger.kernel.org
Subject: [Qemu-devel] [PATCH 4/6] simply cpu_exec further
Date: Tue, 27 May 2008 12:18:23 -0300	[thread overview]
Message-ID: <1211901505-30519-5-git-send-email-gcosta@redhat.com> (raw)
In-Reply-To: <1211901505-30519-4-git-send-email-gcosta@redhat.com>

We change interrupt functions so they have the same
signature, getting only an env parameter. When necessary,
some more attributed were added to the relevant CPUState to
make it possible.

Signed-off-by: Glauber Costa <gcosta@redhat.com>
---
 cpu-defs.h               |    1 +
 cpu-exec.c               |  197 +++++-----------------------------------------
 exec-all.h               |    7 ++
 target-alpha/helper.c    |    9 ++
 target-arm/helper.c      |   27 ++++++
 target-cris/helper.c     |    9 ++
 target-i386/exec.h       |    5 +-
 target-i386/helper.c     |   69 ++++++++++++++++-
 target-m68k/cpu.h        |    2 +-
 target-m68k/helper.c     |   16 ++++
 target-m68k/op_helper.c  |    8 +-
 target-mips/helper.c     |   17 ++++
 target-ppc/helper.c      |   16 ++++
 target-sh4/helper.c      |    8 ++
 target-sparc/exec.h      |    3 +-
 target-sparc/helper.c    |    1 +
 target-sparc/op_helper.c |   29 ++++++-
 17 files changed, 232 insertions(+), 192 deletions(-)

diff --git a/cpu-defs.h b/cpu-defs.h
index 5bcd1ee..5f3f9df 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -162,6 +162,7 @@ typedef struct CPUTLBEntry {
     /* Core interrupt code */                                           \
     jmp_buf jmp_env;                                                    \
     int exception_index;                                                \
+    int exception_is_hw;                                                \
     int error_code;                                                     \
                                                                         \
     int halted;                                                         \
diff --git a/cpu-exec.c b/cpu-exec.c
index a829b7b..e798b03 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -241,6 +241,21 @@ static inline TranslationBlock *tb_find_fast(void)
     return tb;
 }
 
+void handle_interrupt_common(CPUState *env)
+{
+    if (env->interrupt_request & CPU_INTERRUPT_HALT) {
+        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
+        env->halted = 1;
+        env->exception_index = EXCP_HLT;
+        cpu_loop_exit();
+    }
+}
+
+void reset_tb(void)
+{
+    next_tb = 0;
+}
+
 /* main execution loop */
 
 int cpu_exec(CPUState *env1)
@@ -281,43 +296,16 @@ int cpu_exec(CPUState *env1)
                        which will be handled 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);
-                    /* successfully delivered */
-                    env->old_exception = -1;
+                    do_interrupt(env);
 #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. */
-                    do_interrupt(env->exception_index,
-                                 env->exception_is_int,
-                                 env->error_code,
-                                 env->exception_next_eip, 0);
-                    /* successfully delivered */
-                    env->old_exception = -1;
-#elif defined(TARGET_PPC)
-                    do_interrupt(env);
-#elif defined(TARGET_MIPS)
-                    do_interrupt(env);
-#elif defined(TARGET_SPARC)
-                    do_interrupt(env->exception_index);
-#elif defined(TARGET_ARM)
+                    env->exception_is_hw = 0;
                     do_interrupt(env);
-#elif defined(TARGET_SH4)
-		    do_interrupt(env);
-#elif defined(TARGET_ALPHA)
-                    do_interrupt(env);
-#elif defined(TARGET_CRIS)
-                    do_interrupt(env);
-#elif defined(TARGET_M68K)
-                    do_interrupt(0);
-#endif
                 }
                 env->exception_index = -1;
             }
@@ -360,156 +348,9 @@ int cpu_exec(CPUState *env1)
                         env->exception_index = EXCP_DEBUG;
                         cpu_loop_exit();
                     }
-#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
-    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
-                    if (interrupt_request & CPU_INTERRUPT_HALT) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
-                        env->halted = 1;
-                        env->exception_index = EXCP_HLT;
-                        cpu_loop_exit();
-                    }
-#endif
-#if defined(TARGET_I386)
-                    if ((interrupt_request & CPU_INTERRUPT_SMI) &&
-                        !(env->hflags & HF_SMM_MASK)) {
-                        svm_check_intercept(SVM_EXIT_SMI);
-                        env->interrupt_request &= ~CPU_INTERRUPT_SMI;
-                        do_smm_enter();
-                        next_tb = 0;
-                    } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
-                        !(env->hflags & HF_NMI_MASK)) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_NMI;
-                        env->hflags |= HF_NMI_MASK;
-                        do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
-                        next_tb = 0;
-                    } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
-                        (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
-                        !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
-                        int intno;
-                        svm_check_intercept(SVM_EXIT_INTR);
-                        env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
-                        intno = cpu_get_pic_interrupt(env);
-                        if (loglevel & CPU_LOG_TB_IN_ASM) {
-                            fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
-                        }
-                        do_interrupt(intno, 0, 0, 0, 1);
-                        /* ensure that no TB jump will be modified as
-                           the program flow was changed */
-                        next_tb = 0;
-#if !defined(CONFIG_USER_ONLY)
-                    } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
-                        (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
-                         int intno;
-                         /* FIXME: this should respect TPR */
-                         env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
-                         svm_check_intercept(SVM_EXIT_VINTR);
-                         intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
-                         if (loglevel & CPU_LOG_TB_IN_ASM)
-                             fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
-	                 do_interrupt(intno, 0, 0, -1, 1);
-                         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
-                                  ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
-                        next_tb = 0;
-#endif
-                    }
-#elif defined(TARGET_PPC)
-#if 0
-                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
-                        cpu_ppc_reset(env);
-                    }
-#endif
-                    if (interrupt_request & CPU_INTERRUPT_HARD) {
-                        ppc_hw_interrupt(env);
-                        if (env->pending_interrupts == 0)
-                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-                        next_tb = 0;
-                    }
-#elif defined(TARGET_MIPS)
-                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
-                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
-                        (env->CP0_Status & (1 << CP0St_IE)) &&
-                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
-                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
-                        !(env->hflags & MIPS_HFLAG_DM)) {
-                        /* Raise it */
-                        env->exception_index = EXCP_EXT_INTERRUPT;
-                        env->error_code = 0;
-                        do_interrupt(env);
-                        next_tb = 0;
-                    }
-#elif defined(TARGET_SPARC)
-                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
-			(env->psret != 0)) {
-			int pil = env->interrupt_index & 15;
-			int type = env->interrupt_index & 0xf0;
-
-			if (((type == TT_EXTINT) &&
-			     (pil == 15 || pil > env->psrpil)) ||
-			    type != TT_EXTINT) {
-			    env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-			    do_interrupt(env->interrupt_index);
-			    env->interrupt_index = 0;
-#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
-                            cpu_check_irqs(env);
-#endif
-                        next_tb = 0;
-			}
-		    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
-			//do_interrupt(0, 0, 0, 0, 0);
-			env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
-		    }
-#elif defined(TARGET_ARM)
-                    if (interrupt_request & CPU_INTERRUPT_FIQ
-                        && !(env->uncached_cpsr & CPSR_F)) {
-                        env->exception_index = EXCP_FIQ;
-                        do_interrupt(env);
-                        next_tb = 0;
-                    }
-                    /* ARMv7-M interrupt return works by loading a magic value
-                       into the PC.  On real hardware the load causes the
-                       return to occur.  The qemu implementation performs the
-                       jump normally, then does the exception return when the
-                       CPU tries to execute code at the magic address.
-                       This will cause the magic PC value to be pushed to
-                       the stack if an interrupt occured at the wrong time.
-                       We avoid this by disabling interrupts when
-                       pc contains a magic address.  */
-                    if (interrupt_request & CPU_INTERRUPT_HARD
-                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
-                            || !(env->uncached_cpsr & CPSR_I))) {
-                        env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
-                        next_tb = 0;
-                    }
-#elif defined(TARGET_SH4)
-                    if (interrupt_request & CPU_INTERRUPT_HARD) {
-                        do_interrupt(env);
-                        next_tb = 0;
-                    }
-#elif defined(TARGET_ALPHA)
-                    if (interrupt_request & CPU_INTERRUPT_HARD) {
-                        do_interrupt(env);
-                        next_tb = 0;
-                    }
-#elif defined(TARGET_CRIS)
-                    if (interrupt_request & CPU_INTERRUPT_HARD) {
-                        do_interrupt(env);
-                        next_tb = 0;
-                    }
-#elif defined(TARGET_M68K)
-                    if (interrupt_request & CPU_INTERRUPT_HARD
-                        && ((env->sr & SR_I) >> SR_I_SHIFT)
-                            < env->pending_level) {
-                        /* Real hardware gets the interrupt vector via an
-                           IACK cycle at this point.  Current emulated
-                           hardware doesn't rely on this, so we
-                           provide/save the vector when the interrupt is
-                           first signalled.  */
-                        env->exception_index = env->pending_vector;
-                        do_interrupt(1);
-                        next_tb = 0;
-                    }
-#endif
+
+                    arch_handle_interrupt_request(env);
+
                    /* Don't use the cached interupt_request value,
                       do_interrupt may have updated the EXITTB flag. */
                     if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
diff --git a/exec-all.h b/exec-all.h
index fd1ea6a..b43526c 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -84,6 +84,13 @@ void cpu_resume_from_signal(CPUState *env1, void *puc);
 void cpu_exec_init(CPUState *env);
 
 extern int  cpu_info_ip(CPUState *env, char *buf);
+
+/* implemented by the targets */
+void arch_handle_interrupt_request(CPUState *env);
+/* implemented by cpu-exec.c */
+void handle_interrupt_common(CPUState *env);
+void reset_tb(void);
+
 void cpu_load_flags(CPUState *env);
 void cpu_put_flags(CPUState *env);
 
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 6056d6c..003601a 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -456,3 +456,12 @@ void cpu_dump_EA (target_ulong EA)
 int cpu_info_ip(CPUState *env, char *buf) { return 0; }
 void cpu_load_flags(CPUState *env) {}
 void cpu_put_flags(CPUState *env) {}
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+    handle_interrupt_common(env);
+    if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        do_interrupt(env);
+        reset_tb();
+    }
+}
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 6724909..c0b3e84 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2527,3 +2527,30 @@ int cpu_info_ip(CPUState *env, char *buf) { return 0; }
 void cpu_load_flags(CPUState *env) { }
 /* XXX: Save/restore host fpu exception state?.  */
 void cpu_put_flags(CPUState *env) { }
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+    handle_interrupt_common(env);
+    if (env->interrupt_request & CPU_INTERRUPT_FIQ
+        && !(env->uncached_cpsr & CPSR_F)) {
+        env->exception_index = EXCP_FIQ;
+        do_interrupt(env);
+        reset_tb();
+    }
+    /* ARMv7-M interrupt return works by loading a magic value
+       into the PC.  On real hardware the load causes the
+       return to occur.  The qemu implementation performs the
+       jump normally, then does the exception return when the
+       CPU tries to execute code at the magic address.
+       This will cause the magic PC value to be pushed to
+       the stack if an interrupt occured at the wrong time.
+       We avoid this by disabling interrupts when
+       pc contains a magic address.  */
+    if (env->interrupt_request & CPU_INTERRUPT_HARD
+        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
+            || !(env->uncached_cpsr & CPSR_I))) {
+        env->exception_index = EXCP_IRQ;
+        do_interrupt(env);
+        reset_tb();
+    }
+}
diff --git a/target-cris/helper.c b/target-cris/helper.c
index 0ed169c..7acba95 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -187,3 +187,12 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
 int  cpu_info_ip(CPUState *env, char *buf) { return 0; }
 void cpu_load_flags(CPUState *env) {}
 void cpu_put_flags(CPUState *env) {}
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+    handle_interrupt_common(env);
+    if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        do_interrupt(env);
+        reset_tb();
+    }
+}
diff --git a/target-i386/exec.h b/target-i386/exec.h
index f6517ce..b4adabf 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -108,10 +108,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx,
               void *retaddr);
 void __hidden cpu_lock(void);
 void __hidden cpu_unlock(void);
-void do_interrupt(int intno, int is_int, int error_code,
-                  target_ulong next_eip, int is_hw);
-void do_interrupt_user(int intno, int is_int, int error_code,
-                       target_ulong next_eip);
+void do_interrupt(CPUState *env);
 void raise_interrupt(int intno, int is_int, int error_code,
                      int next_eip_addend);
 void raise_exception_err(int exception_index, int error_code);
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 7e690de..7682d8e 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1199,8 +1199,8 @@ void do_interrupt_user(int intno, int is_int, int error_code,
  * 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)
+void do_interrupt_system(int intno, int is_int, int error_code,
+                         target_ulong next_eip, int is_hw)
 {
     if (loglevel & CPU_LOG_INT) {
         if ((env->cr[0] & CR0_PE_MASK)) {
@@ -1247,6 +1247,71 @@ void do_interrupt(int intno, int is_int, int error_code,
     }
 }
 
+void do_interrupt(CPUState *env)
+{
+    if (env->user_mode_only)
+        do_interrupt_user(env->exception_index,
+                          env->exception_is_int,
+                          env->error_code,
+                          env->exception_next_eip);
+    else
+        do_interrupt_system(env->exception_index,
+                            env->exception_is_int,
+                            env->error_code,
+                            env->exception_next_eip,
+                            env->exception_is_hw);
+
+    env->old_exception = -1;
+}
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+    int interrupt_request = env->interrupt_request;
+    int intno;
+
+    if ((interrupt_request & CPU_INTERRUPT_SMI) &&
+        !(env->hflags & HF_SMM_MASK)) {
+        svm_check_intercept(SVM_EXIT_SMI);
+        env->interrupt_request &= ~CPU_INTERRUPT_SMI;
+        do_smm_enter();
+        reset_tb();
+    } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
+        !(env->hflags & HF_NMI_MASK)) {
+        env->interrupt_request &= ~CPU_INTERRUPT_NMI;
+        env->hflags |= HF_NMI_MASK;
+        do_interrupt_system(EXCP02_NMI, 0, 0, 0, 1);
+        reset_tb();
+    } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+        (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
+        !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
+        svm_check_intercept(SVM_EXIT_INTR);
+        env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
+        intno = cpu_get_pic_interrupt(env);
+        if (loglevel & CPU_LOG_TB_IN_ASM) {
+            fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
+        }
+
+        do_interrupt_system(intno, 0, 0, 0, 1);
+        /* ensure that no TB jump will be modified as
+           the program flow was changed */
+        reset_tb();
+#if !defined(CONFIG_USER_ONLY)
+    } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
+        (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
+         /* FIXME: this should respect TPR */
+         env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+         svm_check_intercept(SVM_EXIT_VINTR);
+         intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
+         if (loglevel & CPU_LOG_TB_IN_ASM)
+             fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
+
+         do_interrupt_system(intno, 0, 0, -1, 1);
+         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
+                  ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
+         reset_tb();
+#endif
+    }
+}
 /*
  * Check nested exceptions and change to double or triple fault if
  * needed. It should only be called, if this is not an interrupt.
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index e8c1dfc..1acb4a3 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -120,7 +120,7 @@ typedef struct CPUM68KState {
 CPUM68KState *cpu_m68k_init(const char *cpu_model);
 int cpu_m68k_exec(CPUM68KState *s);
 void cpu_m68k_close(CPUM68KState *s);
-void do_interrupt(int is_hw);
+void do_interrupt(CPUM68KState *s);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 82b5576..65d68c9 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -355,6 +355,22 @@ void cpu_put_flags(CPUState *env)
               | env->cc_dest | (env->cc_x << 4);
 }
 
+void arch_handle_interrupt_request(CPUState *env)
+{
+    if (env->interrupt_request & CPU_INTERRUPT_HARD
+        && ((env->sr & SR_I) >> SR_I_SHIFT)
+            < env->pending_level) {
+        /* Real hardware gets the interrupt vector via an
+           IACK cycle at this point.  Current emulated
+           hardware doesn't rely on this, so we
+           provide/save the vector when the interrupt is
+           signalled.  */
+        env->exception_index = env->pending_vector;
+        env->exception_is_hw = 1;
+        do_interrupt(env);
+        reset_tb();
+    }
+}
 #if defined(CONFIG_USER_ONLY)
 
 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 547f13d..2b0fc1c 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -21,7 +21,7 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt(int is_hw)
+void do_interrupt(CPUState *env)
 {
     env->exception_index = -1;
 }
@@ -95,7 +95,7 @@ static void do_rte(void)
     env->aregs[7] = sp + 8;
 }
 
-void do_interrupt(int is_hw)
+void do_interrupt(CPUState *env)
 {
     uint32_t sp;
     uint32_t fmt;
@@ -105,7 +105,7 @@ void do_interrupt(int is_hw)
     fmt = 0;
     retaddr = env->pc;
 
-    if (!is_hw) {
+    if (!env->exception_is_hw) {
         switch (env->exception_index) {
         case EXCP_RTE:
             /* Return from an exception.  */
@@ -143,7 +143,7 @@ void do_interrupt(int is_hw)
     fmt |= env->sr;
 
     env->sr |= SR_S;
-    if (is_hw) {
+    if (env->exception_is_hw) {
         env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT);
         env->sr &= ~SR_M;
     }
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 81a1a6b..f10930a 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -645,3 +645,20 @@ int cpu_info_ip(CPUState *env, char *buf)
 
 void cpu_put_flags(CPUState *env) { }
 void cpu_load_flags(CPUState *env) { }
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+    handle_interrupt_common(env);
+    if ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
+        (env->CP0_Status & (1 << CP0St_IE)) &&
+        !(env->CP0_Status & (1 << CP0St_EXL)) &&
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM)) {
+        /* Raise it */
+        env->exception_index = EXCP_EXT_INTERRUPT;
+        env->error_code = 0;
+        do_interrupt(env);
+        reset_tb();
+    }
+}
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 2858780..ff8398f 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -2997,3 +2997,19 @@ int cpu_info_ip(CPUState *env, char *buf)
 
 void cpu_load_flags(CPUState *env) { }
 void cpu_put_flags(CPUState *env) { }
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+#if 0
+    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
+        cpu_ppc_reset(env);
+    }
+#endif
+    if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        ppc_hw_interrupt(env);
+        if (env->pending_interrupts == 0)
+            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+        reset_tb();
+    }
+}
+
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index df64d28..9d475ba 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -538,3 +538,11 @@ void cpu_load_tlb(CPUState * env)
 int  cpu_info_ip(CPUState *env, char *buf) { return 0; }
 void cpu_load_flags(CPUState *env) {}
 void cpu_put_flags(CPUState *env) {}
+
+void arch_handle_interrupt_request(CPUState *env)
+{
+    if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        do_interrupt(env);
+        reset_tb();
+    }
+}
diff --git a/target-sparc/exec.h b/target-sparc/exec.h
index 19d1732..33c5267 100644
--- a/target-sparc/exec.h
+++ b/target-sparc/exec.h
@@ -30,7 +30,8 @@ static inline void regs_to_env(void)
 
 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
                                int mmu_idx, int is_softmmu);
-void do_interrupt(int intno);
+
+void do_interrupt(CPUState *env);
 
 static inline int cpu_halted(CPUState *env1) {
     if (!env1->halted)
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 0a300fc..d63a91d 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -1339,6 +1339,7 @@ void cpu_put_flags(CPUState *env)
     REGWPTR = saved_regwptr;
 #endif
 }
+
 #ifdef TARGET_SPARC64
 #if !defined(CONFIG_USER_ONLY)
 #include "qemu-common.h"
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 2d85560..a22e752 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -2689,8 +2689,9 @@ static const char * const excp_names[0x50] = {
 };
 #endif
 
-void do_interrupt(int intno)
+void do_interrupt(CPUState *cpu)
 {
+    int intno = cpu->exception_index;
 #ifdef DEBUG_PCALL
     if (loglevel & CPU_LOG_INT) {
         static int count;
@@ -2803,9 +2804,10 @@ static const char * const excp_names[0x80] = {
 };
 #endif
 
-void do_interrupt(int intno)
+void do_interrupt(CPUState *env)
 {
     int cwp;
+    int intno = env->exception_index;
 
 #ifdef DEBUG_PCALL
     if (loglevel & CPU_LOG_INT) {
@@ -2864,6 +2866,29 @@ void do_interrupt(int intno)
 }
 #endif
 
+void arch_handle_interrupt_request(CPUState *env)
+{
+    handle_interrupt_common(env);
+    if ((env->interrupt_request & CPU_INTERRUPT_HARD) && (env->psret != 0)) {
+        int pil = env->interrupt_index & 15;
+        int type = env->interrupt_index & 0xf0;
+
+        if (((type == TT_EXTINT) &&
+            (pil == 15 || pil > env->psrpil)) || type != TT_EXTINT) {
+            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+            do_interrupt(env);
+            env->interrupt_index = 0;
+#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
+            cpu_check_irqs(env);
+#endif
+            reset_tb();
+        }
+    } else if (env->interrupt_request & CPU_INTERRUPT_TIMER) {
+        //do_interrupt(0, 0, 0, 0, 0);
+        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+    }
+}
+
 #if !defined(CONFIG_USER_ONLY)
 
 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
-- 
1.5.4.5

  reply	other threads:[~2008-05-27 15:19 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-27 15:18 [Qemu-devel] [PATCH 0/6] simplify cpu-exec new spin Glauber Costa
2008-05-27 15:18 ` [Qemu-devel] [PATCH 1/6] simplify cpu_exec Glauber Costa
2008-05-27 15:18   ` [Qemu-devel] [PATCH 2/6] Push common interrupt variables to cpu-defs.h Glauber Costa
2008-05-27 15:18     ` [Qemu-devel] [PATCH 3/6] use halted attribute for i386 too Glauber Costa
2008-05-27 15:18       ` Glauber Costa [this message]
2008-05-27 15:18         ` [Qemu-devel] [PATCH 5/6] isolate mmu code in arch-specific function Glauber Costa
2008-05-27 15:18           ` [Qemu-devel] [PATCH 6/6] cpu-exec-dump Glauber Costa
2008-05-27 15:38             ` Paul Brook
2008-05-27 15:30           ` [Qemu-devel] [PATCH 5/6] isolate mmu code in arch-specific function Fabrice Bellard
2008-05-27 15:42             ` Glauber Costa
2008-05-27 15:36           ` Paul Brook
2008-05-27 16:18         ` [Qemu-devel] [PATCH 4/6] simply cpu_exec further Blue Swirl
2008-05-27 16:27           ` Glauber Costa
2008-05-27 15:34       ` [Qemu-devel] [PATCH 3/6] use halted attribute for i386 too Fabrice Bellard
2008-05-27 16:10         ` Blue Swirl
2008-05-27 21:49           ` Glauber Costa
2008-05-27 16:25         ` Glauber Costa
2008-05-27 21:21           ` Fabrice Bellard
2008-05-27 15:39     ` [Qemu-devel] [PATCH 2/6] Push common interrupt variables to cpu-defs.h Fabrice Bellard
2008-05-27 15:33   ` [Qemu-devel] [PATCH 1/6] simplify cpu_exec Paul Brook
2008-05-27 16:05     ` Blue Swirl
2008-05-27 15:37   ` Fabrice Bellard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1211901505-30519-5-git-send-email-gcosta@redhat.com \
    --to=gcosta@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).