Blame 0236-pl190-fix-read-of-VECTADDR.patch

5544c1
From 12d4393d0830a2a63828d302f177a9b8e31f433a Mon Sep 17 00:00:00 2001
5544c1
From: Brendan Fennell <bfennell@skynet.ie>
5544c1
Date: Wed, 26 Sep 2012 16:46:28 +0100
5544c1
Subject: [PATCH] pl190: fix read of VECTADDR
5544c1
5544c1
Reading VECTADDR was causing us to set the current priority to
5544c1
the wrong value, the most obvious effect of which was that we
5544c1
would return the vector for the wrong interrupt as the result
5544c1
of the read.
5544c1
5544c1
Signed-off-by: Brendan Fennell <bfennell@skynet.ie>
5544c1
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5544c1
(cherry picked from commit 14c126baf1c38607c5bd988878de85a06cefd8cf)
5544c1
5544c1
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
5544c1
---
5544c1
 hw/pl190.c | 18 ++++++++++++------
5544c1
 1 file changed, 12 insertions(+), 6 deletions(-)
5544c1
5544c1
diff --git a/hw/pl190.c b/hw/pl190.c
5544c1
index cb50afb..7332f4d 100644
5544c1
--- a/hw/pl190.c
5544c1
+++ b/hw/pl190.c
5544c1
@@ -117,12 +117,18 @@ static uint64_t pl190_read(void *opaque, target_phys_addr_t offset,
5544c1
         return s->protected;
5544c1
     case 12: /* VECTADDR */
5544c1
         /* Read vector address at the start of an ISR.  Increases the
5544c1
-           current priority level to that of the current interrupt.  */
5544c1
-        for (i = 0; i < s->priority; i++)
5544c1
-          {
5544c1
-            if ((s->level | s->soft_level) & s->prio_mask[i])
5544c1
-              break;
5544c1
-          }
5544c1
+         * current priority level to that of the current interrupt.
5544c1
+         *
5544c1
+         * Since an enabled interrupt X at priority P causes prio_mask[Y]
5544c1
+         * to have bit X set for all Y > P, this loop will stop with
5544c1
+         * i == the priority of the highest priority set interrupt.
5544c1
+         */
5544c1
+        for (i = 0; i < s->priority; i++) {
5544c1
+            if ((s->level | s->soft_level) & s->prio_mask[i + 1]) {
5544c1
+                break;
5544c1
+            }
5544c1
+        }
5544c1
+
5544c1
         /* Reading this value with no pending interrupts is undefined.
5544c1
            We return the default address.  */
5544c1
         if (i == PL190_NUM_PRIO)
5544c1
-- 
5544c1
1.7.12.1
5544c1