ARM: Fix checkpoint restoration into O3 CPU and the way O3 switchCpu works.
authorAli Saidi <Ali.Saidi@ARM.com>
Mon, 4 Apr 2011 16:42:28 +0000 (11:42 -0500)
committerAli Saidi <Ali.Saidi@ARM.com>
Mon, 4 Apr 2011 16:42:28 +0000 (11:42 -0500)
This change fixes a small bug in the arm copyRegs() code where some registers
wouldn't be copied if the processor was in a mode other than MODE_USER.
Additionally, this change simplifies the way the O3 switchCpu code works by
utilizing TheISA::copyRegs() to copy the required context information
rather than the adhoc copying that goes on in the CPU model. The current code
makes assumptions about the visibility of int and float registers that aren't
true for all architectures in FS mode.

src/arch/arm/isa.cc
src/arch/arm/miscregs.hh
src/arch/arm/utility.cc
src/cpu/o3/thread_context_impl.hh

index 216ae04e746b89c473969c1e5af296d40dac0a77..9988d431a597cdd95c6c8b3be5f4234b10bb2014 100644 (file)
@@ -447,6 +447,7 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
                   default:
                       panic("Security Extensions not implemented!");
               }
+              warn("Translating via MISCREG in atomic mode! Fix Me!\n");
               req->setVirt(0, val, 1, flags, tc->pcState().pc());
               fault = tc->getDTBPtr()->translateAtomic(req, tc, mode);
               if (fault == NoFault) {
@@ -475,7 +476,13 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
             tc->getITBPtr()->invalidateMiscReg();
             tc->getDTBPtr()->invalidateMiscReg();
             break;
-
+          case MISCREG_CPSR_MODE:
+            // This miscreg is used by copy*Regs to set the CPSR mode
+            // without updating other CPSR variables. It's used to
+            // make sure the register map is in such a state that we can
+            // see all of the registers for the copy.
+            updateRegMap(val);
+            return;
         }
     }
     setMiscRegNoEffect(misc_reg, newVal);
index fc18fa11424c20b359f88fceac9f28c0072f7b6e..2ccd9b4c2159950bba3bf1b4f494c8c00e4daf37 100644 (file)
@@ -170,6 +170,7 @@ namespace ArmISA
         MISCREG_ID_ISAR3,
         MISCREG_ID_ISAR4,
         MISCREG_ID_ISAR5,
+        MISCREG_CPSR_MODE,
         MISCREG_CP15_UNIMP_START,
         MISCREG_TCMTR = MISCREG_CP15_UNIMP_START,
         MISCREG_ID_PFR1,
@@ -233,6 +234,7 @@ namespace ArmISA
         "pmceid1", "pmc_other", "pmxevcntr",
         "pmuserenr", "pmintenset", "pmintenclr",
         "id_isar0", "id_isar1", "id_isar2", "id_isar3", "id_isar4", "id_isar5",
+        "cpsr_mode",
          // Unimplemented below
         "tcmtr",
         "id_pfr1", "id_dfr0", "id_afr0",
index 0d91c9f909944ad5730a7717d216458e1150320f..6bca632915506a745e2496858cbbf9902f585c14 100644 (file)
@@ -124,8 +124,21 @@ void
 copyRegs(ThreadContext *src, ThreadContext *dest)
 {
     int i;
+
+    int saved_mode = ((CPSR)src->readMiscReg(MISCREG_CPSR)).mode;
+
+    // Make sure we're in user mode, so we can easily see all the registers
+    // in the copy loop
+    src->setMiscReg(MISCREG_CPSR_MODE, MODE_USER);
+    dest->setMiscReg(MISCREG_CPSR_MODE, MODE_USER);
+
     for(i = 0; i < TheISA::NumIntRegs; i++)
         dest->setIntReg(i, src->readIntReg(i));
+
+    // Restore us back to the old mode
+    src->setMiscReg(MISCREG_CPSR_MODE, saved_mode);
+    dest->setMiscReg(MISCREG_CPSR_MODE, saved_mode);
+
     for(i = 0; i < TheISA::NumFloatRegs; i++)
         dest->setFloatReg(i, src->readFloatReg(i));
     for(i = 0; i < TheISA::NumMiscRegs; i++)
index e7b0540d1c671f5f92598be6050b8daae72dea9c..b179ad50e8d31610c43327a18edd4b2ae04a74a7 100755 (executable)
@@ -231,36 +231,11 @@ template <class Impl>
 void
 O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc)
 {
-    // This function will mess things up unless the ROB is empty and
-    // there are no instructions in the pipeline.
-    ThreadID tid = thread->threadId();
-    PhysRegIndex renamed_reg;
-
-    // First loop through the integer registers.
-    for (int i = 0; i < TheISA::NumIntRegs; ++i) {
-        renamed_reg = cpu->renameMap[tid].lookup(i);
-
-        DPRINTF(O3CPU, "Copying over register %i, had data %lli, "
-                "now has data %lli.\n",
-                renamed_reg, cpu->readIntReg(renamed_reg),
-                tc->readIntReg(i));
-
-        cpu->setIntReg(renamed_reg, tc->readIntReg(i));
-    }
-
-    // Then loop through the floating point registers.
-    for (int i = 0; i < TheISA::NumFloatRegs; ++i) {
-        renamed_reg = cpu->renameMap[tid].lookup(i + TheISA::FP_Base_DepTag);
-        cpu->setFloatRegBits(renamed_reg,
-                             tc->readFloatRegBits(i));
-    }
-
-    // Copy the misc regs.
-    TheISA::copyMiscRegs(tc, this);
+    // Prevent squashing
+    thread->inSyscall = true;
+    TheISA::copyRegs(tc, this);
+    thread->inSyscall = false;
 
-    // Then finally set the PC, the next PC, the nextNPC, the micropc, and the
-    // next micropc.
-    cpu->pcState(tc->pcState(), tid);
 #if !FULL_SYSTEM
     this->thread->funcExeInst = tc->readFuncExeInst();
 #endif