]> git.proxmox.com Git - qemu.git/commitdiff
mips: Correct MIPS interrupt glue logic for icount
authorEdgar E. Iglesias <edgar@axis.com>
Sat, 24 Jul 2010 11:40:05 +0000 (13:40 +0200)
committerEdgar E. Iglesias <edgar.iglesias@gmail.com>
Sat, 24 Jul 2010 11:40:05 +0000 (13:40 +0200)
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>
hw/mips_int.c
target-mips/cpu.h
target-mips/op_helper.c

index c30954caafd6b1fe846a2c05902a5d1241d6c400..80488baeba0b729a274ca0a638fbde9fa5742a8e 100644 (file)
 #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)
index 81051aa004722f5c77f75361460458997bf2db12..157885082a9031afc778625822de75e1a0c9cd6f 100644 (file)
@@ -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);
index 8ae510adc1e824d9f8a48aef0a42b53984b2872d..c9632248a083114153499ce064283021345384a6 100644 (file)
@@ -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;
 }