summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrendan Fennell <bfennell@skynet.ie>2012-09-26 16:46:28 +0100
committerMichael Roth <mdroth@linux.vnet.ibm.com>2012-10-11 21:44:21 -0500
commit806d996789a01b09953b051350321183e272c76d (patch)
treeefc7c162bbbf5f1fc5592b952f48eea609cfced3
parentd893e56f7249708080e2d363ce19d30a6de30733 (diff)
downloadqemu-806d996789a01b09953b051350321183e272c76d.tar.gz
pl190: fix read of VECTADDR
Reading VECTADDR was causing us to set the current priority to the wrong value, the most obvious effect of which was that we would return the vector for the wrong interrupt as the result of the read. Signed-off-by: Brendan Fennell <bfennell@skynet.ie> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> (cherry picked from commit 14c126baf1c38607c5bd988878de85a06cefd8cf) Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
-rw-r--r--hw/pl190.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/hw/pl190.c b/hw/pl190.c
index cb50afb9f4..7332f4dbae 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -117,12 +117,18 @@ static uint64_t pl190_read(void *opaque, target_phys_addr_t offset,
return s->protected;
case 12: /* VECTADDR */
/* Read vector address at the start of an ISR. Increases the
- current priority level to that of the current interrupt. */
- for (i = 0; i < s->priority; i++)
- {
- if ((s->level | s->soft_level) & s->prio_mask[i])
- break;
- }
+ * current priority level to that of the current interrupt.
+ *
+ * Since an enabled interrupt X at priority P causes prio_mask[Y]
+ * to have bit X set for all Y > P, this loop will stop with
+ * i == the priority of the highest priority set interrupt.
+ */
+ for (i = 0; i < s->priority; i++) {
+ if ((s->level | s->soft_level) & s->prio_mask[i + 1]) {
+ break;
+ }
+ }
+
/* Reading this value with no pending interrupts is undefined.
We return the default address. */
if (i == PL190_NUM_PRIO)