arch-arm: BadMode checking if corresponding EL is implemented
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Thu, 7 Jun 2018 16:17:16 +0000 (17:17 +0100)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Fri, 22 Jun 2018 10:52:55 +0000 (10:52 +0000)
The old utility function called badMode was only checking if the mode
passed as an argument was a recognized mode. It was not checking if the
corresponding mode/EL was implemented. That function has been renamed to
unknownMode and a new badMode has been introduced.  This is used by the
cpsrWriteByInstruction function.  In this way any try to change the
execution mode won't succeed if the mode hasn't been implemented.

Change-Id: Ibfe385c5465b904acc0d2eb9647710891d72c9df
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/11196
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>

src/arch/arm/insts/static_inst.cc
src/arch/arm/insts/static_inst.hh
src/arch/arm/isa/formats/mem.isa
src/arch/arm/isa/formats/uncond.isa
src/arch/arm/isa/insts/str.isa
src/arch/arm/types.hh
src/arch/arm/utility.cc
src/arch/arm/utility.hh

index 40a1fe4b3c971444f4a0fcc18cebce87afadba85..b7f235e9899881b7824bff5da886f4208f5e0687 100644 (file)
@@ -961,7 +961,7 @@ static bool
 illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
 {
     const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode;
-    if (badMode(mode))
+    if (unknownMode(mode))
         return true;
 
     const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode;
@@ -1000,7 +1000,7 @@ illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
             return true;
     } else {
         // aarch32
-        return badMode32(mode);
+        return unknownMode32(mode);
     }
 
     return false;
@@ -1029,7 +1029,7 @@ ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const
         }
     } else {
         new_cpsr.il = spsr.il;
-        if (spsr.width && badMode32((OperatingMode)(uint8_t)spsr.mode)) {
+        if (spsr.width && unknownMode32((OperatingMode)(uint8_t)spsr.mode)) {
             new_cpsr.il = 1;
         } else if (spsr.width) {
             new_cpsr.mode = spsr.mode;
index 69ae58e66bb56392034d18b00e4dd6fb60fb669f..873dfff02adba49342bacb3a0f2620a65c30acfa 100644 (file)
@@ -230,7 +230,7 @@ class ArmStaticInst : public StaticInst
                 // Now check the new mode is allowed
                 OperatingMode newMode = (OperatingMode) (val & mask(5));
                 OperatingMode oldMode = (OperatingMode)(uint32_t)cpsr.mode;
-                if (!badMode(newMode)) {
+                if (!badMode(tc, newMode)) {
                     bool validModeChange = true;
                     // Check for attempts to enter modes only permitted in
                     // Secure state from Non-secure state. These are Monitor
index 1a30fbb9d39a2b8f7701a99eda70ac8f45a1a94d..50e3e358ff41d842630b48c8a749783b328e967a 100644 (file)
@@ -282,7 +282,12 @@ def format Thumb32SrsRfe() {{
             }
         } else {
             const uint32_t mode = bits(machInst, 4, 0);
-            if (badMode32((OperatingMode)mode))
+            // We check at decode stage if the mode exists even
+            // if the checking is re-done by Srs::execute.
+            // This is done because we will otherwise panic if
+            // trying to read the banked stack pointer of an
+            // unrecognized mode.
+            if (unknownMode32((OperatingMode)mode))
                 return new Unknown(machInst);
             if (!add && !wb) {
                 return new %(srs)s(machInst, mode,
index c376cd9ce665672ead14f1ea06d5971ceb91ceed..e0b07ab5a5f4b13977c98efcff2b1594d7b24897 100644 (file)
@@ -166,7 +166,12 @@ def format ArmUnconditional() {{
                     const uint32_t val = ((machInst >> 20) & 0x5);
                     if (val == 0x4) {
                         const uint32_t mode = bits(machInst, 4, 0);
-                        if (badMode32((OperatingMode)mode))
+                        // We check at decode stage if the mode exists even
+                        // if the checking is re-done by Srs::execute.
+                        // This is done because we will otherwise panic if
+                        // trying to read the banked stack pointer of an
+                        // unrecognized mode.
+                        if (unknownMode32((OperatingMode)mode))
                             return new Unknown(machInst);
                         switch (bits(machInst, 24, 21)) {
                           case 0x2:
index 1c697d3ff6f4f5e4ce13cd75badf9954bd989420..c165eaf1afe0422368cdba5bd80c7b3d8cb1c8eb 100644 (file)
@@ -112,6 +112,12 @@ let {{
             if self.add:
                 wbDiff = 8
             accCode = '''
+
+            auto tc = xc->tcBase();
+            if (badMode32(tc, static_cast<OperatingMode>(regMode))) {
+                return undefinedFault32(tc, opModeToEL(currOpMode(tc)));
+            }
+
             CPSR cpsr = Cpsr;
             Mem_ud = (uint64_t)cSwap(LR_uw, cpsr.e) |
                      ((uint64_t)cSwap(Spsr_uw, cpsr.e) << 32);
index 07cdfadc8027ca5f2868c861899fa61af09cd351..9ce02524e22f4f5b4c42c0d31f843597a5eb5a53 100644 (file)
@@ -710,7 +710,7 @@ namespace ArmISA
     }
 
     static inline bool
-    badMode(OperatingMode mode)
+    unknownMode(OperatingMode mode)
     {
         switch (mode) {
           case MODE_EL0T:
@@ -735,9 +735,8 @@ namespace ArmISA
         }
     }
 
-
     static inline bool
-    badMode32(OperatingMode mode)
+    unknownMode32(OperatingMode mode)
     {
         switch (mode) {
           case MODE_USER:
index 7659e1e793203bfc4da790618f1822290fa6f073..dec85ef65ad23b813ddb69ccd3fd62e82ac99040 100644 (file)
@@ -313,6 +313,18 @@ isBigEndian64(ThreadContext *tc)
     }
 }
 
+bool
+badMode32(ThreadContext *tc, OperatingMode mode)
+{
+    return unknownMode32(mode) || !ArmSystem::haveEL(tc, opModeToEL(mode));
+}
+
+bool
+badMode(ThreadContext *tc, OperatingMode mode)
+{
+    return unknownMode(mode) || !ArmSystem::haveEL(tc, opModeToEL(mode));
+}
+
 Addr
 purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el,
                  TTBCR tcr)
index 796ded7713aa209ab4378edc40e327b0b60fa221..9d0131b49781288966c051d4f21a94d864915671 100644 (file)
@@ -181,6 +181,26 @@ bool ELIs64(ThreadContext *tc, ExceptionLevel el);
 
 bool isBigEndian64(ThreadContext *tc);
 
+/**
+ * badMode is checking if the execution mode provided as an argument is
+ * valid and implemented for AArch32
+ *
+ * @param tc ThreadContext
+ * @param mode OperatingMode to check
+ * @return false if mode is valid and implemented, true otherwise
+ */
+bool badMode32(ThreadContext *tc, OperatingMode mode);
+
+/**
+ * badMode is checking if the execution mode provided as an argument is
+ * valid and implemented.
+ *
+ * @param tc ThreadContext
+ * @param mode OperatingMode to check
+ * @return false if mode is valid and implemented, true otherwise
+ */
+bool badMode(ThreadContext *tc, OperatingMode mode);
+
 static inline uint8_t
 itState(CPSR psr)
 {