diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2019-05-07 12:55:03 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-05-07 12:55:03 +0100 |
commit | b01e2f0284a2df11aef990219104e3f52c317061 (patch) | |
tree | 3b0541553b7ac1a6d8a42a754f13f3efa1d0dfb8 /hw | |
parent | 946376c21be1cd9dcc3c7936b204b113781603f7 (diff) |
hw/arm/armv7m_nvic: Check subpriority in nvic_recompute_state_secure()
Rule R_CQRV says that if two pending interrupts have the same
group priority then ties are broken by looking at the subpriority.
We had a comment describing this but had forgotten to actually
implement the subpriority comparison. Correct the omission.
(The further tie break rules of "lowest exception number" and
"secure before non-secure" are handled implicitly by the order
in which we iterate through the exceptions in the loops.)
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190430131439.25251-2-peter.maydell@linaro.org
Diffstat (limited to 'hw')
-rw-r--r-- | hw/intc/armv7m_nvic.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index fff6e694e6..131b5938b9 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -213,6 +213,7 @@ static void nvic_recompute_state_secure(NVICState *s) int active_prio = NVIC_NOEXC_PRIO; int pend_irq = 0; bool pending_is_s_banked = false; + int pend_subprio = 0; /* R_CQRV: precedence is by: * - lowest group priority; if both the same then @@ -226,7 +227,7 @@ static void nvic_recompute_state_secure(NVICState *s) for (i = 1; i < s->num_irq; i++) { for (bank = M_REG_S; bank >= M_REG_NS; bank--) { VecInfo *vec; - int prio; + int prio, subprio; bool targets_secure; if (bank == M_REG_S) { @@ -241,8 +242,12 @@ static void nvic_recompute_state_secure(NVICState *s) } prio = exc_group_prio(s, vec->prio, targets_secure); - if (vec->enabled && vec->pending && prio < pend_prio) { + subprio = vec->prio & ~nvic_gprio_mask(s, targets_secure); + if (vec->enabled && vec->pending && + ((prio < pend_prio) || + (prio == pend_prio && prio >= 0 && subprio < pend_subprio))) { pend_prio = prio; + pend_subprio = subprio; pend_irq = i; pending_is_s_banked = (bank == M_REG_S); } |