arch-arm: ELUsingAArch32K from armarm pseudocode
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Wed, 3 Jan 2018 11:01:17 +0000 (11:01 +0000)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Wed, 7 Feb 2018 15:06:50 +0000 (15:06 +0000)
This patch implements the ELUsingAArch32K pseudocode, which is returning
true if the provided Exception Level is using A32 ISA, but it is not
panicking (quitting simulation) if the information is unknown (see
documentation).
The panicking is the current behaviour of the ELIs32 utility in gem5.

Change-Id: Iad7b56077d7e0f8ee223b5b9593cb8097f26bb29
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/7222
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>

src/arch/arm/utility.cc
src/arch/arm/utility.hh

index a49f82971180e9f895a124b3deea014505cd762f..4e99d980e0e9564d5982d3b34c08052ac4ae5296 100644 (file)
@@ -243,20 +243,31 @@ ELIs64(ThreadContext *tc, ExceptionLevel el)
 bool
 ELIs32(ThreadContext *tc, ExceptionLevel el)
 {
-    // Return true if the specified EL is in aarch32 state.
+    bool known, aarch32;
+    std::tie(known, aarch32) = ELUsingAArch32K(tc, el);
+    panic_if(!known, "EL state is UNKNOWN");
+    return aarch32;
+}
 
+std::pair<bool, bool>
+ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
+{
+    // Return true if the specified EL is in aarch32 state.
     const bool have_el3 = ArmSystem::haveSecurity(tc);
     const bool have_el2 = ArmSystem::haveVirtualization(tc);
 
     panic_if(el == EL2 && !have_el2, "Asking for EL2 when it doesn't exist");
     panic_if(el == EL3 && !have_el3, "Asking for EL3 when it doesn't exist");
 
-    if (ArmSystem::highestELIs64(tc)
-              && ArmSystem::highestEL(tc) == el) {
-        return false;
+    bool known, aarch32;
+    known = aarch32 = false;
+    if (ArmSystem::highestELIs64(tc) && ArmSystem::highestEL(tc) == el) {
+        // Target EL is the highest one in a system where
+        // the highest is using AArch64.
+        known = true; aarch32 = false;
     } else if (!ArmSystem::highestELIs64(tc)) {
-        // All levels are using AArch32
-        return true;
+        // All ELs are using AArch32:
+        known = true; aarch32 = true;
     } else {
         SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
         bool aarch32_below_el3 = (have_el3 && scr.rw == 0);
@@ -268,15 +279,19 @@ ELIs32(ThreadContext *tc, ExceptionLevel el)
 
         // Only know if EL0 using AArch32 from PSTATE
         if (el == EL0 && !aarch32_at_el1) {
-            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
-            panic_if(cpsr.el != EL0, "EL0 state is UNKNOWN");
             // EL0 controlled by PSTATE
-            return cpsr.width != 0;
+            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
+
+            known = (cpsr.el == EL0);
+            aarch32 = (cpsr.width == 1);
         } else {
-            return (aarch32_below_el3 && el != EL3)
-                     || (aarch32_at_el1 && (el == EL0 || el == EL1) );
+            known = true;
+            aarch32 = (aarch32_below_el3 && el != EL3)
+                      || (aarch32_at_el1 && (el == EL0 || el == EL1) );
         }
     }
+
+    return std::make_pair(known, aarch32);
 }
 
 bool
index 6e4e76b75117020e1dcae70416390dc88d13a54d..8efe4ad109e57d4c70bdccbd916ad009f1a1902e 100644 (file)
@@ -157,6 +157,24 @@ currEL(ThreadContext *tc)
     return (ExceptionLevel) (uint8_t) cpsr.el;
 }
 
+/**
+ * This function checks whether selected EL provided as an argument
+ * is using the AArch32 ISA. This information might be unavailable
+ * at the current EL status: it hence returns a pair of boolean values:
+ * a first boolean, true if information is available (known),
+ * and a second one, true if EL is using AArch32, false for AArch64.
+ *
+ * @param tc The thread context.
+ * @param el The target exception level.
+ * @retval known is FALSE for EL0 if the current Exception level
+ *               is not EL0 and EL1 is using AArch64, since it cannot
+ *               determine the state of EL0; TRUE otherwise.
+ * @retval aarch32 is TRUE if the specified Exception level is using AArch32;
+ *                 FALSE otherwise.
+ */
+std::pair<bool, bool>
+ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el);
+
 bool ELIs32(ThreadContext *tc, ExceptionLevel el);
 
 bool ELIs64(ThreadContext *tc, ExceptionLevel el);