qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] Reworking MIPS interrupts handling
@ 2007-01-23 18:42 Aurelien Jarno
  2007-01-23 20:00 ` Aurelien Jarno
  0 siblings, 1 reply; 3+ messages in thread
From: Aurelien Jarno @ 2007-01-23 18:42 UTC (permalink / raw)
  To: qemu-devel

Hi all,

Please find below a patch to fix the IRQ issue on the MIPS platform. I
have tested it on both 2.4 and 2.6 kernel and it works fine.

Here are a few comments on the patch to understand how it works.

- The CPU hardware interrupt (CPU_INTERRUPT_HARD) is not deasserted by
  the CPU anymore, but rather by the interrupt controller. I think it
  should be the case for other targets too, but I don't want to change
  the code of other targets without some more tests, that's why I use a
  condition in the i8259.c file.

- The gt64120 now uses pic_read_irq() instead of pic_intack_read() so
  that the interrupt state of the i8259 is recomputed and propagated if
  needed.

- I changed the way the CPU hardware interrupt (CPU_INTERRUPT_HARD) is
  asserted. It appears that the MIPS CPU can have more than one
  interrupt, 6 hardware and 2 software interrupt. The
  cpu_mips_update_irq() subroutine computes the state of the hardware
  interrupt and issue and harware interrupt, deassert it or do nothing
  in function of the mode of the CPU, the CP0 cause register (status
  of the interrupt lines) and the CP0 status register (interrupt masks).

- The software interrupt are now handled using... a hardware interrupt.
  From our point of view, hardware and software interrupts are actually
  the same, they use the same vector, they use the same registers, the
  only difference is that the bit in the CP0 cause register is set to
  one by software instead of hardware.

Bye,
Aurelien

--- hw/mips_int.c	2007-01-18 20:37:29.623079789 +0100
+++ hw/mips_int.c	2007-01-23 18:47:42.000000000 +0100
@@ -0,0 +1,31 @@
+#include "vl.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 & env->CP0_Cause & 0x0000ff00) &&
+        (env->CP0_Status & 0x00000001) &&
+        !(env->hflags & MIPS_HFLAG_EXL) &&
+        !(env->hflags & MIPS_HFLAG_ERL) &&
+        !(env->hflags & MIPS_HFLAG_DM)) {
+        if (! (env->interrupt_request & CPU_INTERRUPT_HARD)) {
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        }
+    } else {
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+void cpu_mips_irq_request(void *opaque, int irq, int level)
+{
+    CPUState *env = first_cpu;
+    
+    if (level) {
+        env->CP0_Cause |= (irq & 0x0000ff00);
+    } else {
+        env->CP0_Cause &= ~(irq & 0x0000ff00);
+    }
+    cpu_mips_update_irq(env);
+}
+
Index: Makefile.target
===================================================================
RCS file: /sources/qemu/qemu/Makefile.target,v
retrieving revision 1.140
diff -u -d -p -r1.140 Makefile.target
--- Makefile.target	21 Jan 2007 22:40:04 -0000	1.140
+++ Makefile.target	23 Jan 2007 18:14:39 -0000
@@ -376,7 +376,7 @@ VL_OBJS+= grackle_pci.o prep_pci.o unin_
 CPPFLAGS += -DHAS_AUDIO
 endif
 ifeq ($(TARGET_ARCH), mips)
-VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o dma.o vga.o serial.o i8254.o i8259.o
+VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
 VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o
 VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
 DEFINES += -DHAS_AUDIO
Index: cpu-exec.c
===================================================================
RCS file: /sources/qemu/qemu/cpu-exec.c,v
retrieving revision 1.88
diff -u -d -p -r1.88 cpu-exec.c
--- cpu-exec.c	7 Dec 2006 18:28:42 -0000	1.88
+++ cpu-exec.c	23 Jan 2007 18:14:40 -0000
@@ -535,7 +535,6 @@ int cpu_exec(CPUState *env1)
                         env->exception_index = EXCP_EXT_INTERRUPT;
                         env->error_code = 0;
                         do_interrupt(env);
-                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
                         tmp_T0 = 0;
 #else
Index: vl.h
===================================================================
RCS file: /sources/qemu/qemu/vl.h,v
retrieving revision 1.175
diff -u -d -p -r1.175 vl.h
--- vl.h	21 Jan 2007 16:47:01 -0000	1.175
+++ vl.h	23 Jan 2007 18:14:44 -0000
@@ -1067,6 +1067,9 @@ extern QEMUMachine mips_machine;
 /* mips_malta.c */
 extern QEMUMachine mips_malta_machine;
 
+/* mips_int */
+extern void cpu_mips_irq_request(void *opaque, int irq, int level);
+
 /* mips_timer.c */
 extern void cpu_mips_clock_init(CPUState *);
 extern void cpu_mips_irqctrl_init (void);
Index: hw/gt64xxx.c
===================================================================
RCS file: /sources/qemu/qemu/hw/gt64xxx.c,v
retrieving revision 1.2
diff -u -d -p -r1.2 gt64xxx.c
--- hw/gt64xxx.c	17 Jan 2007 23:35:01 -0000	1.2
+++ hw/gt64xxx.c	23 Jan 2007 18:14:45 -0000
@@ -1,7 +1,7 @@
 /*
  * QEMU GT64120 PCI host
  *
- * Copyright (c) 2006 Aurelien Jarno
+ * Copyright (c) 2006, 2007 Aurelien Jarno
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -433,7 +436,8 @@ static uint32_t gt64120_readl (void *opa
         val = s->regs[saddr];
         break;
     case GT_PCI0_IACK:
- 	val = pic_intack_read(isa_pic);
+        /* Read the IRQ number */ 
+        val = pic_read_irq(isa_pic);
         break;
 
     /* SDRAM Parameters */
Index: hw/i8259.c
===================================================================
RCS file: /sources/qemu/qemu/hw/i8259.c,v
retrieving revision 1.19
diff -u -d -p -r1.19 i8259.c
--- hw/i8259.c	25 Jun 2006 18:15:31 -0000	1.19
+++ hw/i8259.c	23 Jan 2007 18:14:45 -0000
@@ -161,6 +161,10 @@ void pic_update_irq(PicState2 *s)
 #endif
         s->irq_request(s->irq_request_opaque, 1);
     }
+#if defined(TARGET_MIPS)
+    else
+        s->irq_request(s->irq_request_opaque, 0);
+#endif
 }
 
 #ifdef DEBUG_IRQ_LATENCY
Index: hw/mips_malta.c
===================================================================
RCS file: /sources/qemu/qemu/hw/mips_malta.c,v
retrieving revision 1.4
diff -u -d -p -r1.4 mips_malta.c
--- hw/mips_malta.c	20 Jan 2007 00:29:01 -0000	1.4
+++ hw/mips_malta.c	23 Jan 2007 18:14:45 -0000
@@ -56,14 +56,7 @@ static PITState *pit;
 
 static void pic_irq_request(void *opaque, int level)
 {
-    CPUState *env = first_cpu;
-    if (level) {
-        env->CP0_Cause |= 0x00000400;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-	env->CP0_Cause &= ~0x00000400;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
+    cpu_mips_irq_request(opaque, 0x00000400, level);
 }
 
 /* Malta FPGA */
Index: hw/mips_r4k.c
===================================================================
RCS file: /sources/qemu/qemu/hw/mips_r4k.c,v
retrieving revision 1.31
diff -u -d -p -r1.31 mips_r4k.c
--- hw/mips_r4k.c	6 Jan 2007 02:24:15 -0000	1.31
+++ hw/mips_r4k.c	23 Jan 2007 18:14:45 -0000
@@ -38,14 +38,7 @@ static PITState *pit; /* PIT i8254 */
 /*The PIC is attached to the MIPS CPU INT0 pin */
 static void pic_irq_request(void *opaque, int level)
 {
-    CPUState *env = first_cpu;
-    if (level) {
-        env->CP0_Cause |= 0x00000400;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-	env->CP0_Cause &= ~0x00000400;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
+    cpu_mips_irq_request(opaque, 0x00000400, level);
 }
 
 static void mips_qemu_writel (void *opaque, target_phys_addr_t addr,
Index: hw/mips_timer.c
===================================================================
RCS file: /sources/qemu/qemu/hw/mips_timer.c,v
retrieving revision 1.1
diff -u -d -p -r1.1 mips_timer.c
--- hw/mips_timer.c	6 Dec 2006 21:38:37 -0000	1.1
+++ hw/mips_timer.c	23 Jan 2007 18:14:45 -0000
@@ -57,8 +57,7 @@ void cpu_mips_store_count (CPUState *env
 void cpu_mips_store_compare (CPUState *env, uint32_t value)
 {
     cpu_mips_update_count(env, cpu_mips_get_count(env), value);
-    env->CP0_Cause &= ~0x00008000;
-    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_mips_irq_request(env, 0x00008000, 0);
 }
 
 static void mips_timer_cb (void *opaque)
@@ -73,7 +72,7 @@ static void mips_timer_cb (void *opaque)
 #endif
     cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
     env->CP0_Cause |= 0x00008000;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_mips_irq_request(opaque, 0x00008000, 1);
 }
 
 void cpu_mips_clock_init (CPUState *env)
Index: target-mips/exec.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/exec.h,v
retrieving revision 1.15
diff -u -d -p -r1.15 exec.h
--- target-mips/exec.h	3 Jan 2007 15:18:08 -0000	1.15
+++ target-mips/exec.h	23 Jan 2007 18:14:45 -0000
@@ -164,6 +164,7 @@ uint32_t cpu_mips_get_random (CPUState *
 uint32_t cpu_mips_get_count (CPUState *env);
 void cpu_mips_store_count (CPUState *env, uint32_t value);
 void cpu_mips_store_compare (CPUState *env, uint32_t value);
+void cpu_mips_update_irq(CPUState *env);
 void cpu_mips_clock_init (CPUState *env);
 void cpu_mips_tlb_flush (CPUState *env, int flush_global);
 
Index: target-mips/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op.c,v
retrieving revision 1.19
diff -u -d -p -r1.19 op.c
--- target-mips/op.c	1 Jan 2007 20:35:21 -0000	1.19
+++ target-mips/op.c	23 Jan 2007 18:14:45 -0000
@@ -1368,21 +1368,9 @@ void op_mtc0_status (void)
     else
         env->hflags &= ~MIPS_HFLAG_EXL;
     env->CP0_Status = val;
-    /* If we unmasked an asserted IRQ, raise it */
-    mask = 0x0000FF00;
     if (loglevel & CPU_LOG_TB_IN_ASM)
        CALL_FROM_TB2(do_mtc0_status_debug, old, val);
-    if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
-        !(env->hflags & MIPS_HFLAG_EXL) &&
-        !(env->hflags & MIPS_HFLAG_ERL) &&
-        !(env->hflags & MIPS_HFLAG_DM) &&
-        (env->CP0_Status & env->CP0_Cause & mask)) {
-        env->interrupt_request |= CPU_INTERRUPT_HARD;
-       if (logfile)
-           CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
-    } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) {
-        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-    }
+    CALL_FROM_TB1(cpu_mips_update_irq, env);
     RETURN();
 }
 
@@ -1402,22 +1390,13 @@ void op_mtc0_srsctl (void)
 
 void op_mtc0_cause (void)
 {
-    uint32_t val, old;
+    env->CP0_Cause = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300);
 
-    val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300);
-    old = env->CP0_Cause;
-    env->CP0_Cause = val;
-#if 0
-    {
-        int i, mask;
-       /* Check if we ever asserted a software IRQ */
-        for (i = 0; i < 2; i++) {
-            mask = 0x100 << i;
-            if ((val & mask) & !(old & mask))
-                CALL_FROM_TB1(mips_set_irq, i);
-        }
+    /* Handle the software interrupt as an hardware one, as they
+       are very similar */
+    if (T0 & 0x0000ff00) {
+        CALL_FROM_TB1(cpu_mips_update_irq, env);
     }
-#endif
     RETURN();
 }
 
@@ -1928,36 +1907,17 @@ void op_pmon (void)
 
 void op_di (void)
 {
-    uint32_t val;
-
     T0 = env->CP0_Status;
-    val = T0 & ~(1 << CP0St_IE);
-    if (val != T0) {
-        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-        env->CP0_Status = val;
-    }
+    env->CP0_Status = T0 & ~(1 << CP0St_IE);
+    CALL_FROM_TB1(cpu_mips_update_irq, env);
     RETURN();
 }
 
 void op_ei (void)
 {
-    uint32_t val;
-
     T0 = env->CP0_Status;
-    val = T0 | (1 << CP0St_IE);
-    if (val != T0) {
-       const uint32_t mask = 0x0000FF00;
-
-       env->CP0_Status = val;
-       if (!(env->hflags & MIPS_HFLAG_EXL) &&
-           !(env->hflags & MIPS_HFLAG_ERL) &&
-           !(env->hflags & MIPS_HFLAG_DM) &&
-           (env->CP0_Status & env->CP0_Cause & mask)) {
-               env->interrupt_request |= CPU_INTERRUPT_HARD;
-               if (logfile)
-                   CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
-       }
-    }
+    env->CP0_Status = T0 | (1 << CP0St_IE);
+    CALL_FROM_TB1(cpu_mips_update_irq, env);
     RETURN();
 }
 
Index: target-mips/op_helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op_helper.c,v
retrieving revision 1.26
diff -u -d -p -r1.26 op_helper.c
--- target-mips/op_helper.c	22 Jan 2007 20:50:42 -0000	1.26
+++ target-mips/op_helper.c	23 Jan 2007 18:14:46 -0000
@@ -265,6 +265,11 @@ void cpu_mips_store_compare(CPUState *en
     cpu_abort(env, "mtc0 compare\n");
 }
 
+void cpu_mips_update_irq(CPUState *env)
+{
+    cpu_abort(env, "mtc0 status / mtc0 cause\n");
+}
+
 void do_mtc0_status_debug(uint32_t old, uint32_t val)
 {
     cpu_abort(env, "mtc0 status debug\n");

-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

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

* Re: [Qemu-devel] [PATCH] Reworking MIPS interrupts handling
  2007-01-23 18:42 [Qemu-devel] [PATCH] Reworking MIPS interrupts handling Aurelien Jarno
@ 2007-01-23 20:00 ` Aurelien Jarno
  2007-01-23 20:19   ` Fabrice Bellard
  0 siblings, 1 reply; 3+ messages in thread
From: Aurelien Jarno @ 2007-01-23 20:00 UTC (permalink / raw)
  To: qemu-devel

On Tue, Jan 23, 2007 at 07:42:20PM +0100, Aurelien Jarno wrote:
> Hi all,
> 
> Please find below a patch to fix the IRQ issue on the MIPS platform. I
> have tested it on both 2.4 and 2.6 kernel and it works fine.
> 

Here is an updated patch including the comments from Paul Brook via IRC.
Thanks Paul for the review.


--- hw/mips_int.c	2007-01-18 20:37:29.623079789 +0100
+++ hw/mips_int.c	2007-01-23 20:55:13.000000000 +0100
@@ -0,0 +1,39 @@
+#include "vl.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 & env->CP0_Cause & CP0Ca_IP_mask) &&
+        (env->CP0_Status & (1 << CP0St_IE)) &&
+        !(env->hflags & MIPS_HFLAG_EXL) &&
+	!(env->hflags & MIPS_HFLAG_ERL) &&
+	!(env->hflags & MIPS_HFLAG_DM)) {
+        if (! (env->interrupt_request & CPU_INTERRUPT_HARD)) {
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+	}
+    } else {
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+void cpu_mips_irq_request(void *opaque, int irq, int level)
+{
+    CPUState *env = first_cpu;
+   
+    uint32_t mask;
+
+    if (irq >= 16)
+        return;
+
+    mask = 1 << (irq + CP0Ca_IP);
+
+    if (level) {
+        env->CP0_Cause |= mask;
+    } else {
+        env->CP0_Cause &= ~mask;
+    }
+    cpu_mips_update_irq(env);
+}
+
? hw/mips_int.c
Index: Makefile.target
===================================================================
RCS file: /sources/qemu/qemu/Makefile.target,v
retrieving revision 1.140
diff -u -d -p -r1.140 Makefile.target
--- Makefile.target	21 Jan 2007 22:40:04 -0000	1.140
+++ Makefile.target	23 Jan 2007 19:57:09 -0000
@@ -376,7 +376,7 @@ VL_OBJS+= grackle_pci.o prep_pci.o unin_
 CPPFLAGS += -DHAS_AUDIO
 endif
 ifeq ($(TARGET_ARCH), mips)
-VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o dma.o vga.o serial.o i8254.o i8259.o
+VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
 VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o
 VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
 DEFINES += -DHAS_AUDIO
Index: cpu-exec.c
===================================================================
RCS file: /sources/qemu/qemu/cpu-exec.c,v
retrieving revision 1.88
diff -u -d -p -r1.88 cpu-exec.c
--- cpu-exec.c	7 Dec 2006 18:28:42 -0000	1.88
+++ cpu-exec.c	23 Jan 2007 19:57:10 -0000
@@ -535,7 +535,6 @@ int cpu_exec(CPUState *env1)
                         env->exception_index = EXCP_EXT_INTERRUPT;
                         env->error_code = 0;
                         do_interrupt(env);
-                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
                         tmp_T0 = 0;
 #else
Index: vl.h
===================================================================
RCS file: /sources/qemu/qemu/vl.h,v
retrieving revision 1.175
diff -u -d -p -r1.175 vl.h
--- vl.h	21 Jan 2007 16:47:01 -0000	1.175
+++ vl.h	23 Jan 2007 19:57:10 -0000
@@ -1067,6 +1067,9 @@ extern QEMUMachine mips_machine;
 /* mips_malta.c */
 extern QEMUMachine mips_malta_machine;
 
+/* mips_int */
+extern void cpu_mips_irq_request(void *opaque, int irq, int level);
+
 /* mips_timer.c */
 extern void cpu_mips_clock_init(CPUState *);
 extern void cpu_mips_irqctrl_init (void);
Index: hw/gt64xxx.c
===================================================================
RCS file: /sources/qemu/qemu/hw/gt64xxx.c,v
retrieving revision 1.2
diff -u -d -p -r1.2 gt64xxx.c
--- hw/gt64xxx.c	17 Jan 2007 23:35:01 -0000	1.2
+++ hw/gt64xxx.c	23 Jan 2007 19:57:10 -0000
@@ -1,7 +1,7 @@
 /*
  * QEMU GT64120 PCI host
  *
- * Copyright (c) 2006 Aurelien Jarno
+ * Copyright (c) 2006,2007 Aurelien Jarno
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -433,7 +436,8 @@ static uint32_t gt64120_readl (void *opa
         val = s->regs[saddr];
         break;
     case GT_PCI0_IACK:
- 	val = pic_intack_read(isa_pic);
+        /* Read the IRQ number */ 
+        val = pic_read_irq(isa_pic);
         break;
 
     /* SDRAM Parameters */
Index: hw/i8259.c
===================================================================
RCS file: /sources/qemu/qemu/hw/i8259.c,v
retrieving revision 1.19
diff -u -d -p -r1.19 i8259.c
--- hw/i8259.c	25 Jun 2006 18:15:31 -0000	1.19
+++ hw/i8259.c	23 Jan 2007 19:57:10 -0000
@@ -161,6 +161,13 @@ void pic_update_irq(PicState2 *s)
 #endif
         s->irq_request(s->irq_request_opaque, 1);
     }
+
+/* all targets should do this rather than acking the IRQ in the cpu */
+#if defined(TARGET_MIPS)
+    else {
+        s->irq_request(s->irq_request_opaque, 0);
+    }
+#endif
 }
 
 #ifdef DEBUG_IRQ_LATENCY
Index: hw/mips_malta.c
===================================================================
RCS file: /sources/qemu/qemu/hw/mips_malta.c,v
retrieving revision 1.4
diff -u -d -p -r1.4 mips_malta.c
--- hw/mips_malta.c	20 Jan 2007 00:29:01 -0000	1.4
+++ hw/mips_malta.c	23 Jan 2007 19:57:10 -0000
@@ -54,16 +54,10 @@ typedef struct {
 
 static PITState *pit;
 
+/* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
 static void pic_irq_request(void *opaque, int level)
 {
-    CPUState *env = first_cpu;
-    if (level) {
-        env->CP0_Cause |= 0x00000400;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-	env->CP0_Cause &= ~0x00000400;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
+    cpu_mips_irq_request(opaque, 2, level);
 }
 
 /* Malta FPGA */
Index: hw/mips_r4k.c
===================================================================
RCS file: /sources/qemu/qemu/hw/mips_r4k.c,v
retrieving revision 1.31
diff -u -d -p -r1.31 mips_r4k.c
--- hw/mips_r4k.c	6 Jan 2007 02:24:15 -0000	1.31
+++ hw/mips_r4k.c	23 Jan 2007 19:57:10 -0000
@@ -38,14 +38,7 @@ static PITState *pit; /* PIT i8254 */
 /*The PIC is attached to the MIPS CPU INT0 pin */
 static void pic_irq_request(void *opaque, int level)
 {
-    CPUState *env = first_cpu;
-    if (level) {
-        env->CP0_Cause |= 0x00000400;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-	env->CP0_Cause &= ~0x00000400;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
+    cpu_mips_irq_request(opaque, 2, level);
 }
 
 static void mips_qemu_writel (void *opaque, target_phys_addr_t addr,
Index: hw/mips_timer.c
===================================================================
RCS file: /sources/qemu/qemu/hw/mips_timer.c,v
retrieving revision 1.1
diff -u -d -p -r1.1 mips_timer.c
--- hw/mips_timer.c	6 Dec 2006 21:38:37 -0000	1.1
+++ hw/mips_timer.c	23 Jan 2007 19:57:10 -0000
@@ -57,8 +57,7 @@ void cpu_mips_store_count (CPUState *env
 void cpu_mips_store_compare (CPUState *env, uint32_t value)
 {
     cpu_mips_update_count(env, cpu_mips_get_count(env), value);
-    env->CP0_Cause &= ~0x00008000;
-    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_mips_irq_request(env, 7, 0);
 }
 
 static void mips_timer_cb (void *opaque)
@@ -72,8 +71,7 @@ static void mips_timer_cb (void *opaque)
     }
 #endif
     cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
-    env->CP0_Cause |= 0x00008000;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_mips_irq_request(env, 7, 1);
 }
 
 void cpu_mips_clock_init (CPUState *env)
Index: target-mips/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/cpu.h,v
retrieving revision 1.17
diff -u -d -p -r1.17 cpu.h
--- target-mips/cpu.h	22 Jan 2007 20:50:42 -0000	1.17
+++ target-mips/cpu.h	23 Jan 2007 19:57:10 -0000
@@ -157,6 +157,7 @@ struct CPUMIPSState {
 #define CP0Ca_IV   23
 #define CP0Ca_WP   22
 #define CP0Ca_IP    8
+#define CP0Ca_IP_mask 0x0000FF00
 #define CP0Ca_EC    2
     target_ulong CP0_EPC;
     uint32_t CP0_PRid;
Index: target-mips/exec.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/exec.h,v
retrieving revision 1.15
diff -u -d -p -r1.15 exec.h
--- target-mips/exec.h	3 Jan 2007 15:18:08 -0000	1.15
+++ target-mips/exec.h	23 Jan 2007 19:57:10 -0000
@@ -164,6 +164,7 @@ uint32_t cpu_mips_get_random (CPUState *
 uint32_t cpu_mips_get_count (CPUState *env);
 void cpu_mips_store_count (CPUState *env, uint32_t value);
 void cpu_mips_store_compare (CPUState *env, uint32_t value);
+void cpu_mips_update_irq(CPUState *env);
 void cpu_mips_clock_init (CPUState *env);
 void cpu_mips_tlb_flush (CPUState *env, int flush_global);
 
Index: target-mips/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op.c,v
retrieving revision 1.19
diff -u -d -p -r1.19 op.c
--- target-mips/op.c	1 Jan 2007 20:35:21 -0000	1.19
+++ target-mips/op.c	23 Jan 2007 19:57:10 -0000
@@ -1351,7 +1351,7 @@ void op_mtc0_compare (void)
 
 void op_mtc0_status (void)
 {
-    uint32_t val, old, mask;
+    uint32_t val, old;
 
     val = T0 & (int32_t)0xFA78FF01;
     old = env->CP0_Status;
@@ -1368,21 +1368,9 @@ void op_mtc0_status (void)
     else
         env->hflags &= ~MIPS_HFLAG_EXL;
     env->CP0_Status = val;
-    /* If we unmasked an asserted IRQ, raise it */
-    mask = 0x0000FF00;
     if (loglevel & CPU_LOG_TB_IN_ASM)
        CALL_FROM_TB2(do_mtc0_status_debug, old, val);
-    if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
-        !(env->hflags & MIPS_HFLAG_EXL) &&
-        !(env->hflags & MIPS_HFLAG_ERL) &&
-        !(env->hflags & MIPS_HFLAG_DM) &&
-        (env->CP0_Status & env->CP0_Cause & mask)) {
-        env->interrupt_request |= CPU_INTERRUPT_HARD;
-       if (logfile)
-           CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
-    } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) {
-        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-    }
+    CALL_FROM_TB1(cpu_mips_update_irq, env);
     RETURN();
 }
 
@@ -1402,22 +1390,13 @@ void op_mtc0_srsctl (void)
 
 void op_mtc0_cause (void)
 {
-    uint32_t val, old;
+    env->CP0_Cause = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300);
 
-    val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300);
-    old = env->CP0_Cause;
-    env->CP0_Cause = val;
-#if 0
-    {
-        int i, mask;
-       /* Check if we ever asserted a software IRQ */
-        for (i = 0; i < 2; i++) {
-            mask = 0x100 << i;
-            if ((val & mask) & !(old & mask))
-                CALL_FROM_TB1(mips_set_irq, i);
-        }
+    /* Handle the software interrupt as an hardware one, as they
+       are very similar */
+    if (T0 & CP0Ca_IP_mask) {
+        CALL_FROM_TB1(cpu_mips_update_irq, env);
     }
-#endif
     RETURN();
 }
 
@@ -1928,36 +1907,17 @@ void op_pmon (void)
 
 void op_di (void)
 {
-    uint32_t val;
-
     T0 = env->CP0_Status;
-    val = T0 & ~(1 << CP0St_IE);
-    if (val != T0) {
-        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-        env->CP0_Status = val;
-    }
+    env->CP0_Status = T0 & ~(1 << CP0St_IE);
+    CALL_FROM_TB1(cpu_mips_update_irq, env);
     RETURN();
 }
 
 void op_ei (void)
 {
-    uint32_t val;
-
     T0 = env->CP0_Status;
-    val = T0 | (1 << CP0St_IE);
-    if (val != T0) {
-       const uint32_t mask = 0x0000FF00;
-
-       env->CP0_Status = val;
-       if (!(env->hflags & MIPS_HFLAG_EXL) &&
-           !(env->hflags & MIPS_HFLAG_ERL) &&
-           !(env->hflags & MIPS_HFLAG_DM) &&
-           (env->CP0_Status & env->CP0_Cause & mask)) {
-               env->interrupt_request |= CPU_INTERRUPT_HARD;
-               if (logfile)
-                   CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
-       }
-    }
+    env->CP0_Status = T0 | (1 << CP0St_IE);
+    CALL_FROM_TB1(cpu_mips_update_irq, env);
     RETURN();
 }
 
Index: target-mips/op_helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op_helper.c,v
retrieving revision 1.26
diff -u -d -p -r1.26 op_helper.c
--- target-mips/op_helper.c	22 Jan 2007 20:50:42 -0000	1.26
+++ target-mips/op_helper.c	23 Jan 2007 19:57:10 -0000
@@ -265,6 +265,11 @@ void cpu_mips_store_compare(CPUState *en
     cpu_abort(env, "mtc0 compare\n");
 }
 
+void cpu_mips_update_irq(CPUState *env)
+{
+    cpu_abort(env, "mtc0 status / mtc0 cause\n");
+}
+
 void do_mtc0_status_debug(uint32_t old, uint32_t val)
 {
     cpu_abort(env, "mtc0 status debug\n");

-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

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

* Re: [Qemu-devel] [PATCH] Reworking MIPS interrupts handling
  2007-01-23 20:00 ` Aurelien Jarno
@ 2007-01-23 20:19   ` Fabrice Bellard
  0 siblings, 0 replies; 3+ messages in thread
From: Fabrice Bellard @ 2007-01-23 20:19 UTC (permalink / raw)
  To: qemu-devel

Good. I prefer this implementation to the current one!

Fabrice.

Aurelien Jarno wrote:
> On Tue, Jan 23, 2007 at 07:42:20PM +0100, Aurelien Jarno wrote:
> 
>>Hi all,
>>
>>Please find below a patch to fix the IRQ issue on the MIPS platform. I
>>have tested it on both 2.4 and 2.6 kernel and it works fine.
>>
> 
> 
> Here is an updated patch including the comments from Paul Brook via IRC.
> Thanks Paul for the review.

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

end of thread, other threads:[~2007-01-23 20:31 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-01-23 18:42 [Qemu-devel] [PATCH] Reworking MIPS interrupts handling Aurelien Jarno
2007-01-23 20:00 ` Aurelien Jarno
2007-01-23 20:19   ` Fabrice Bellard

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