qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] MIPS interrupts and -icount
@ 2010-07-22 11:32 Edgar E. Iglesias
  2010-07-24 22:55 ` Aurelien Jarno
  0 siblings, 1 reply; 14+ messages in thread
From: Edgar E. Iglesias @ 2010-07-22 11:32 UTC (permalink / raw)
  To: qemu-devel

Hi,

I'm seeing an error when emulating MIPS guests with -icount.
In cpu_interrupt:
  cpu_abort(env, "Raised interrupt while not in I/O function");

It seems to me like the MIPS interrupt glue logic between interrupt
controllers and the MIPS core is not modeled correctly.

When hw interrupt pending bits in CP0_Cause are set, the CPU should
see the hw interrupt line as active. The CPU may or may not take the
interrupt based on internal state (global irq mask etc) but the glue
logic shouldn't care about that. Am I missing something here?

The following patch fixes the problem. Tested by booting the mips and mipsel
images from http://wiki.qemu.org/Download. Also tested more with an
experimental out-of-tree qemu machine I've got here running a linux-2.6.33
kernel.

I'd appreciate comments.

Thanks,
Edgar


commit c9af70e4587e1464b8019a059845492225733584
Author: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Date:   Thu Jul 22 13:14:52 2010 +0200

    mips: Correct MIPS interrupt glue logic for icount
    
    When hw interrupt pending bits in CP0_Cause are set, the CPU should
    see the hw interrupt line as active. The CPU may or may not take the
    interrupt based on internal state (global irq mask etc) but the glue
    logic shouldn't care.
    
    This fixes MIPS external hw interrupts in combination with -icount.
    
    Signed-off-by: Edgar E. Iglesias <edgar@axis.com>

diff --git a/hw/mips_int.c b/hw/mips_int.c
index c30954c..80488ba 100644
--- a/hw/mips_int.c
+++ b/hw/mips_int.c
@@ -24,22 +24,6 @@
 #include "mips_cpudevs.h"
 #include "cpu.h"
 
-/* Raise IRQ to CPU if necessary. It must be called every time the active
-   IRQ may change */
-void cpu_mips_update_irq(CPUState *env)
-{
-    if ((env->CP0_Status & (1 << CP0St_IE)) &&
-        !(env->CP0_Status & (1 << CP0St_EXL)) &&
-        !(env->CP0_Status & (1 << CP0St_ERL)) &&
-        !(env->hflags & MIPS_HFLAG_DM)) {
-        if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
-            !(env->interrupt_request & CPU_INTERRUPT_HARD)) {
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
-	}
-    } else
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-}
-
 static void cpu_mips_irq_request(void *opaque, int irq, int level)
 {
     CPUState *env = (CPUState *)opaque;
@@ -52,7 +36,12 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
     } else {
         env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
     }
-    cpu_mips_update_irq(env);
+
+    if (env->CP0_Cause & CP0Ca_IP_mask) {
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
 }
 
 void cpu_mips_irq_init_cpu(CPUState *env)
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 81051aa..1578850 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -597,9 +597,6 @@ void cpu_mips_store_compare (CPUState *env, uint32_t value);
 void cpu_mips_start_count(CPUState *env);
 void cpu_mips_stop_count(CPUState *env);
 
-/* mips_int.c */
-void cpu_mips_update_irq (CPUState *env);
-
 /* helper.c */
 int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                                int mmu_idx, int is_softmmu);
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 8ae510a..c963224 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1313,7 +1313,6 @@ void helper_mtc0_status (target_ulong arg1)
         default: cpu_abort(env, "Invalid MMU mode!\n"); break;
         }
     }
-    cpu_mips_update_irq(env);
 }
 
 void helper_mttc0_status(target_ulong arg1)
@@ -1359,12 +1358,6 @@ void helper_mtc0_cause (target_ulong arg1)
         else
             cpu_mips_start_count(env);
     }
-
-    /* Handle the software interrupt as an hardware one, as they
-       are very similar */
-    if (arg1 & CP0Ca_IP_mask) {
-        cpu_mips_update_irq(env);
-    }
 }
 
 void helper_mtc0_ebase (target_ulong arg1)
@@ -1793,8 +1786,6 @@ target_ulong helper_di (void)
     target_ulong t0 = env->CP0_Status;
 
     env->CP0_Status = t0 & ~(1 << CP0St_IE);
-    cpu_mips_update_irq(env);
-
     return t0;
 }
 
@@ -1803,8 +1794,6 @@ target_ulong helper_ei (void)
     target_ulong t0 = env->CP0_Status;
 
     env->CP0_Status = t0 | (1 << CP0St_IE);
-    cpu_mips_update_irq(env);
-
     return t0;
 }
 

^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2010-12-26 20:29 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-22 11:32 [Qemu-devel] [PATCH] MIPS interrupts and -icount Edgar E. Iglesias
2010-07-24 22:55 ` Aurelien Jarno
2010-07-25  0:07   ` Edgar E. Iglesias
2010-07-25  3:08     ` Aurelien Jarno
2010-07-25  4:44       ` Aurelien Jarno
2010-07-25  5:52         ` Edgar E. Iglesias
2010-07-25  7:21           ` Edgar E. Iglesias
2010-07-25 14:58             ` Aurelien Jarno
2010-07-25  5:46       ` Edgar E. Iglesias
2010-12-21 22:28         ` Aurelien Jarno
2010-12-22 16:12           ` Edgar E. Iglesias
2010-12-25 22:22             ` Aurelien Jarno
2010-12-26  8:34               ` Edgar E. Iglesias
2010-12-26 20:29                 ` Aurelien Jarno

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