arch-arm: Don't change PSTATE in Illegal Exception return
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 19 Dec 2017 10:18:13 +0000 (10:18 +0000)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Thu, 8 Feb 2018 09:48:02 +0000 (09:48 +0000)
This patch fixes the Illegal Exception return handler. According to the
armarm documentation, when PSTATE.IL is set to one because of an illegal
exception return, PSTATE.{EL, nRW, SP} are unchanged. This means the
Exception level, Execution state, and stack pointer selection do not
change as a result of the return.

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

src/arch/arm/insts/static_inst.cc
src/arch/arm/isa.cc

index aace1de2b05bfb4846002fdf0ab588e60353d6a9..a7ba91e03ed42acddbe62cce7c4e8ab4f253db71 100644 (file)
@@ -1018,7 +1018,17 @@ ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const
     new_cpsr.ss = 0;
 
     if (illegalExceptionReturn(tc, cpsr, spsr)) {
+        // If the SPSR specifies an illegal exception return,
+        // then PSTATE.{M, nRW, EL, SP} are unchanged and PSTATE.IL
+        // is set to 1.
         new_cpsr.il = 1;
+        if (cpsr.width) {
+            new_cpsr.mode = cpsr.mode;
+        } else {
+            new_cpsr.width = cpsr.width;
+            new_cpsr.el = cpsr.el;
+            new_cpsr.sp = cpsr.sp;
+        }
     } else {
         new_cpsr.il = spsr.il;
         if (spsr.width && badMode32((OperatingMode)(uint8_t)spsr.mode)) {
index c917abacf408f5d3f70660d14ad2fbab9ccebdaf..5d34e188a08da90f79b86b51e9367a7f87ad65b3 100644 (file)
@@ -726,7 +726,7 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
         CPSR old_cpsr = miscRegs[MISCREG_CPSR];
         int old_mode = old_cpsr.mode;
         CPSR cpsr = val;
-        if (old_mode != cpsr.mode) {
+        if (old_mode != cpsr.mode || cpsr.il != old_cpsr.il) {
             getITBPtr(tc)->invalidateMiscReg();
             getDTBPtr(tc)->invalidateMiscReg();
         }