From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36099) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a4Hc0-00049B-AU for qemu-devel@nongnu.org; Wed, 02 Dec 2015 19:19:05 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1a4Hbz-0001wr-6G for qemu-devel@nongnu.org; Wed, 02 Dec 2015 19:19:04 -0500 From: Michael Davidsaver Date: Wed, 2 Dec 2015 19:18:32 -0500 Message-Id: <1449101933-24928-6-git-send-email-mdavidsaver@gmail.com> In-Reply-To: <1449101933-24928-1-git-send-email-mdavidsaver@gmail.com> References: <1449101933-24928-1-git-send-email-mdavidsaver@gmail.com> Subject: [Qemu-devel] [PATCH v2 05/26] armv7m: add armv7m_excp_running_prio() List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Peter Maydell , Peter Crosthwaite , qemu-arm@nongnu.org, Michael Davidsaver 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