summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/utility.cc37
-rw-r--r--src/arch/arm/utility.hh18
2 files changed, 44 insertions, 11 deletions
diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc
index a49f82971..4e99d980e 100644
--- a/src/arch/arm/utility.cc
+++ b/src/arch/arm/utility.cc
@@ -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
diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh
index 6e4e76b75..8efe4ad10 100644
--- a/src/arch/arm/utility.hh
+++ b/src/arch/arm/utility.hh
@@ -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);