summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--hw/intc/armv7m_nvic.c23
-rw-r--r--hw/intc/trace-events2
-rw-r--r--include/hw/intc/armv7m_nvic.h2
3 files changed, 16 insertions, 11 deletions
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index a11df3d155..fa5dd23f09 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -61,10 +61,10 @@ static const uint8_t nvic_id[] = {
 
 static int nvic_pending_prio(NVICState *s)
 {
-    /* return the priority of the current pending interrupt,
+    /* return the group priority of the current pending interrupt,
      * or NVIC_NOEXC_PRIO if no interrupt is pending
      */
-    return s->vectpending ? s->vectors[s->vectpending].prio : NVIC_NOEXC_PRIO;
+    return s->vectpending_prio;
 }
 
 /* Return the value of the ISCR RETTOBASE bit:
@@ -156,10 +156,17 @@ static void nvic_recompute_state(NVICState *s)
         active_prio &= nvic_gprio_mask(s);
     }
 
+    if (pend_prio > 0) {
+        pend_prio &= nvic_gprio_mask(s);
+    }
+
     s->vectpending = pend_irq;
+    s->vectpending_prio = pend_prio;
     s->exception_prio = active_prio;
 
-    trace_nvic_recompute_state(s->vectpending, s->exception_prio);
+    trace_nvic_recompute_state(s->vectpending,
+                               s->vectpending_prio,
+                               s->exception_prio);
 }
 
 /* Return the current execution priority of the CPU
@@ -323,7 +330,6 @@ void armv7m_nvic_acknowledge_irq(void *opaque)
     CPUARMState *env = &s->cpu->env;
     const int pending = s->vectpending;
     const int running = nvic_exec_prio(s);
-    int pendgroupprio;
     VecInfo *vec;
 
     assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
@@ -333,13 +339,9 @@ void armv7m_nvic_acknowledge_irq(void *opaque)
     assert(vec->enabled);
     assert(vec->pending);
 
-    pendgroupprio = vec->prio;
-    if (pendgroupprio > 0) {
-        pendgroupprio &= nvic_gprio_mask(s);
-    }
-    assert(pendgroupprio < running);
+    assert(s->vectpending_prio < running);
 
-    trace_nvic_acknowledge_irq(pending, vec->prio);
+    trace_nvic_acknowledge_irq(pending, s->vectpending_prio);
 
     vec->active = 1;
     vec->pending = 0;
@@ -1255,6 +1257,7 @@ static void armv7m_nvic_reset(DeviceState *dev)
     s->exception_prio = NVIC_NOEXC_PRIO;
     s->vectpending = 0;
     s->vectpending_is_s_banked = false;
+    s->vectpending_prio = NVIC_NOEXC_PRIO;
 }
 
 static void nvic_systick_trigger(void *opaque, int n, int level)
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 4762329482..5635a5fbbf 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -167,7 +167,7 @@ gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributor 0x%x
 gicv3_redist_send_sgi(uint32_t cpu, int irq) "GICv3 redistributor 0x%x pending SGI %d"
 
 # hw/intc/armv7m_nvic.c
-nvic_recompute_state(int vectpending, int exception_prio) "NVIC state recomputed: vectpending %d exception_prio %d"
+nvic_recompute_state(int vectpending, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d vectpending_prio %d exception_prio %d"
 nvic_set_prio(int irq, uint8_t prio) "NVIC set irq %d priority %d"
 nvic_irq_update(int vectpending, int pendprio, int exception_prio, int level) "NVIC vectpending %d pending prio %d exception_prio %d: setting irq line to %d"
 nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq %d to HardFault: insufficient priority %d >= %d"
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
index 87c78b3c26..329774e82b 100644
--- a/include/hw/intc/armv7m_nvic.h
+++ b/include/hw/intc/armv7m_nvic.h
@@ -62,6 +62,7 @@ typedef struct NVICState {
      *  - vectpending
      *  - vectpending_is_secure
      *  - exception_prio
+     *  - vectpending_prio
      */
     unsigned int vectpending; /* highest prio pending enabled exception */
     /* true if vectpending is a banked secure exception, ie it is in
@@ -69,6 +70,7 @@ typedef struct NVICState {
      */
     bool vectpending_is_s_banked;
     int exception_prio; /* group prio of the highest prio active exception */
+    int vectpending_prio; /* group prio of the exeception in vectpending */
 
     MemoryRegion sysregmem;
     MemoryRegion sysreg_ns_mem;