summaryrefslogtreecommitdiffstats
path: root/hw/intc/armv7m_nvic.c
diff options
context:
space:
mode:
authorPeter Maydell2017-09-12 20:13:51 +0200
committerPeter Maydell2017-09-21 17:29:27 +0200
commit5255fcf8e47acd059e2f0d414841c40231c1bd22 (patch)
tree1b2757f564e9e87a050c45527b2d3d0a29af5b4b /hw/intc/armv7m_nvic.c
parentnvic: Add cached vectpending_is_s_banked state (diff)
downloadqemu-5255fcf8e47acd059e2f0d414841c40231c1bd22.tar.gz
qemu-5255fcf8e47acd059e2f0d414841c40231c1bd22.tar.xz
qemu-5255fcf8e47acd059e2f0d414841c40231c1bd22.zip
nvic: Add cached vectpending_prio state
Instead of looking up the pending priority in nvic_pending_prio(), cache it in a new state struct field. The calculation of the pending priority given the interrupt number is more complicated in v8M with the security extension, so the caching will be worthwhile. This changes nvic_pending_prio() from returning a full (group + subpriority) priority value to returning a group priority. This doesn't require changes to its callsites because we use it only in comparisons of the form execution_prio > nvic_pending_prio() and execution priority is always a group priority, so a test (exec prio > full prio) is true if and only if (execprio > group_prio). (Architecturally the expected comparison is with the group priority for this sort of "would we preempt" test; we were only doing a test with a full priority as an optimisation to avoid the mask, which is possible precisely because the two comparisons always give the same answer.) Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 1505240046-11454-5-git-send-email-peter.maydell@linaro.org
Diffstat (limited to 'hw/intc/armv7m_nvic.c')
-rw-r--r--hw/intc/armv7m_nvic.c23
1 files changed, 13 insertions, 10 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)