qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH v2 05/26] armv7m: add armv7m_excp_running_prio()


From: Michael Davidsaver
Subject: [Qemu-devel] [PATCH v2 05/26] armv7m: add armv7m_excp_running_prio()
Date: Wed, 2 Dec 2015 19:18:32 -0500

Implements v7m exception priority algorithm
using FAULTMASK, PRIMASK, BASEPRI, and the highest
priority active exception.

The number returned is the current execution priority
which may be in the range [-2,0x7f] when an exception is active
or 0x100 when no exception is active.
---
 hw/intc/armv7m_nvic.c | 25 +++++++++++++++++++++++++
 target-arm/cpu.h      |  1 +
 2 files changed, 26 insertions(+)

diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 6fc167e..0145ca7 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -18,6 +18,8 @@
 
 typedef struct {
     GICState gic;
+    uint8_t prigroup;
+
     struct {
         uint32_t control;
         uint32_t reload;
@@ -116,6 +118,29 @@ static void systick_reset(nvic_state *s)
     timer_del(s->systick.timer);
 }
 
+/* @returns the active (running) exception priority.
+ *    only a higher (numerically lower) priority can preempt.
+ */
+int armv7m_excp_running_prio(ARMCPU *cpu)
+{
+    CPUARMState *env = &cpu->env;
+    nvic_state *s = env->nvic;
+    int running;
+
+    if (env->daif & PSTATE_F) { /* FAULTMASK */
+        running = -1;
+    } else if (env->daif & PSTATE_I) { /* PRIMASK */
+        running = 0;
+    } else if (env->v7m.basepri > 0) {
+        /* BASEPRI==1 -> masks [1,255] (not same as PRIMASK==1) */
+        running = env->v7m.basepri >> (s->prigroup+1);
+    } else {
+        running = 0x100; /* lower than any possible priority */
+    }
+    /* consider priority of active handler */
+    return MIN(running, env->v7m.exception_prio);
+}
+
 /* The external routines use the hardware vector numbering, ie. the first
    IRQ is #16.  The internal GIC routines use #32 as the first IRQ.  */
 void armv7m_nvic_set_pending(void *opaque, int irq)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index c193fbb..e2d9e75 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1034,6 +1034,7 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t 
excp_idx,
                                  uint32_t cur_el, bool secure);
 
 /* Interface between CPU and Interrupt controller.  */
+int armv7m_excp_running_prio(ARMCPU *cpu);
 void armv7m_nvic_set_pending(void *opaque, int irq);
 int armv7m_nvic_acknowledge_irq(void *opaque);
 void armv7m_nvic_complete_irq(void *opaque, int irq);
-- 
2.1.4




reply via email to

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