qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH pic32 4/7] Added support for external interrupt cont


From: Serge Vakulenko
Subject: [Qemu-devel] [PATCH pic32 4/7] Added support for external interrupt controller (EIC) mode.
Date: Mon, 29 Jun 2015 22:04:38 -0700

Signed-off-by: Serge Vakulenko <address@hidden>
---
 hw/mips/cputimer.c   | 17 +++++++++++++++--
 hw/mips/mips_int.c   | 11 +++++++++--
 target-mips/cpu.h    |  9 ++++++++-
 target-mips/helper.c | 20 ++++++++++++++------
 4 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
index ec0cffa..da72363 100644
--- a/hw/mips/cputimer.c
+++ b/hw/mips/cputimer.c
@@ -54,7 +54,13 @@ static void cpu_mips_timer_expire(CPUMIPSState *env)
     if (env->insn_flags & ISA_MIPS32R2) {
         env->CP0_Cause |= 1 << CP0Ca_TI;
     }
-    qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
+    if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
+        /* External interrupt controller mode. */
+        env->eic_timer_irq(env, 1);
+    } else {
+        /* Legacy or vectored interrupt mode. */
+        qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
+    }
 }

 uint32_t cpu_mips_get_count (CPUMIPSState *env)
@@ -102,7 +108,14 @@ void cpu_mips_store_compare (CPUMIPSState *env,
uint32_t value)
         cpu_mips_timer_update(env);
     if (env->insn_flags & ISA_MIPS32R2)
         env->CP0_Cause &= ~(1 << CP0Ca_TI);
-    qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
+
+    if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
+        /* External interrupt controller mode: nothing to do. */
+        env->eic_timer_irq(env, 0);
+    } else {
+        /* Legacy or vectored interrupt mode. */
+        qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
+    }
 }

 void cpu_mips_start_count(CPUMIPSState *env)
diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
index d740046..64dad0c 100644
--- a/hw/mips/mips_int.c
+++ b/hw/mips/mips_int.c
@@ -32,7 +32,7 @@ static void cpu_mips_irq_request(void *opaque, int
irq, int level)
     CPUMIPSState *env = &cpu->env;
     CPUState *cs = CPU(cpu);

-    if (irq < 0 || irq > 7)
+    if (irq < 0 || irq > 7 || (env->CP0_Config3 & (1 << CP0C3_VEIC)))
         return;

     if (level) {
@@ -74,5 +74,12 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level)
         return;
     }

-    qemu_set_irq(env->irq[irq], level);
+    if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
+        /* External interrupt controller mode. */
+        if (level > 0)
+            env->eic_soft_irq(env, irq);
+    } else {
+        /* Legacy or vectored interrupt mode. */
+        qemu_set_irq(env->irq[irq], level);
+    }
 }
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index c476166..ab830ee 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -596,6 +596,11 @@ struct CPUMIPSState {
     void *irq[8];
     QEMUTimer *timer; /* Internal timer */
     unsigned count_freq; /* rate of Count register */
+
+    /* Fields for external interrupt controller. */
+    void *eic_context;
+    void (*eic_timer_irq)(CPUMIPSState *env, int raise);
+    void (*eic_soft_irq)(CPUMIPSState *env, int num);
 };

 #include "cpu-qom.h"
@@ -664,7 +669,9 @@ static inline int
cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
     if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
         /* A MIPS configured with a vectorizing external interrupt controller
            will feed a vector into the Cause pending lines. The core treats
-           the status lines as a vector level, not as indiviual masks.  */
+           the status lines as a vector level, not as individual masks.  */
+        pending >>= CP0Ca_IP + 2;
+        status >>= CP0Ca_IP + 2;
         r = pending > status;
     } else {
         /* A MIPS configured with compatibility or VInt (Vectored Interrupts)
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 8e3204a..7e25998 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -574,23 +574,31 @@ void mips_cpu_do_interrupt(CPUState *cs)
             unsigned int vector;
             unsigned int pending = (env->CP0_Cause & CP0Ca_IP_mask) >> 8;

-            pending &= env->CP0_Status >> 8;
             /* Compute the Vector Spacing.  */
             spacing = (env->CP0_IntCtl >> CP0IntCtl_VS) & ((1 << 6) - 1);
             spacing <<= 5;

-            if (env->CP0_Config3 & (1 << CP0C3_VInt)) {
+            if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
+                /* For VEIC mode, the external interrupt controller feeds the
+                 * vector through the CP0Cause IP lines. */
+                vector = pending;
+
+                /* Architecturally, this is chip-specific behavior.
+                 * TODO: some processors, like PIC32MZ,
+                 * provide vector in a different way.
+                 * Some processors, like PIC32, have a separate
+                 * bit INTCON.MVEC to explicitly enable vectored mode,
+                 * disabled by default. */
+                spacing = 0;
+            } else {
                 /* For VInt mode, the MIPS computes the vector internally.  */
+                pending &= env->CP0_Status >> 8;
                 for (vector = 7; vector > 0; vector--) {
                     if (pending & (1 << vector)) {
                         /* Found it.  */
                         break;
                     }
                 }
-            } else {
-                /* For VEIC mode, the external interrupt controller feeds the
-                   vector through the CP0Cause IP lines.  */
-                vector = pending;
             }
             offset = 0x200 + vector * spacing;
         }
--
1.9.1



reply via email to

[Prev in Thread] Current Thread [Next in Thread]