Set the pstate.priv bit to 1 in hyperpriveleged mode. The description in the manual...
authorGabe Black <gblack@eecs.umich.edu>
Mon, 20 Nov 2006 23:07:58 +0000 (18:07 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Mon, 20 Nov 2006 23:07:58 +0000 (18:07 -0500)
--HG--
extra : convert_revision : 9ecb6af06657e936a208cbeb8e4a18305869b949

src/arch/sparc/faults.cc

index 3ec41ba61eaf38dd9178b74cd22b36f8367d13b3..9a29f24d56a627e374de7fdf477f94dcaa911263 100644 (file)
@@ -284,6 +284,11 @@ void enterREDState(ThreadContext *tc)
     //HPSTATE.hpriv = 1
     HPSTATE |= (1 << 2);
     tc->setMiscRegWithEffect(MISCREG_HPSTATE, HPSTATE);
+    //PSTATE.priv is set to 1 here. The manual says it should be 0, but
+    //Legion sets it to 1.
+    MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
+    PSTATE |= (1 << 2);
+    tc->setMiscRegWithEffect(MISCREG_PSTATE, PSTATE);
 }
 
 /**
@@ -340,10 +345,12 @@ void doREDFault(ThreadContext *tc, TrapType tt)
     PSTATE |= (1 << 4);
     //set PSTATE.am to 0
     PSTATE &= ~(1 << 3);
-    //set PSTATE.priv to 0
-    PSTATE &= ~(1 << 2);
+/*    //set PSTATE.priv to 0
+    PSTATE &= ~(1 << 2);*/
     //set PSTATE.ie to 0
-    PSTATE &= ~(1 << 1);
+    //PSTATE.priv is set to 1 here. The manual says it should be 0, but
+    //Legion sets it to 1.
+    PSTATE |= (1 << 2);
     //set PSTATE.cle to 0
     PSTATE &= ~(1 << 9);
     //PSTATE.tle is unchanged
@@ -451,7 +458,9 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
     else
     {
         //PSTATE.priv = 0
-        PSTATE &= ~(1 << 2);
+        //PSTATE.priv is set to 1 here. The manual says it should be 0, but
+        //Legion sets it to 1.
+        PSTATE |= (1 << 2);
         //PSTATE.cle = 0
         PSTATE &= ~(1 << 9);
     }
@@ -533,20 +542,22 @@ void SparcFaultBase::invoke(ThreadContext * tc)
     Addr PC, NPC;
 
     PrivilegeLevel current;
-    if(!(PSTATE & (1 << 2)))
-        current = User;
-    else if(!(HPSTATE & (1 << 2)))
+    if(HPSTATE & (1 << 2))
+        current = Hyperprivileged;
+    else if(PSTATE & (1 << 2))
         current = Privileged;
     else
-        current = Hyperprivileged;
+        current = User;
 
     PrivilegeLevel level = getNextLevel(current);
 
     if(HPSTATE & (1 << 5) || TL == MaxTL - 1)
     {
         getREDVector(5, PC, NPC);
-        enterREDState(tc);
         doREDFault(tc, TT);
+        //This changes the hpstate and pstate, so we need to make sure we
+        //save the old version on the trap stack in doREDFault.
+        enterREDState(tc);
     }
     else if(TL == MaxTL)
     {
@@ -578,9 +589,6 @@ void SparcFaultBase::invoke(ThreadContext * tc)
 
 void PowerOnReset::invoke(ThreadContext * tc)
 {
-    //First, enter RED state.
-    enterREDState(tc);
-
     //For SPARC, when a system is first started, there is a power
     //on reset Trap which sets the processor into the following state.
     //Bits that aren't set aren't defined on startup.
@@ -589,8 +597,8 @@ void PowerOnReset::invoke(ThreadContext * tc)
     tc->setMiscReg(MISCREG_TT, trapType());
     tc->setMiscRegWithEffect(MISCREG_GL, MaxGL);
 
-    //Turn on pef, set everything else to 0
-    tc->setMiscReg(MISCREG_PSTATE, 1 << 4);
+    //Turn on pef and priv, set everything else to 0
+    tc->setMiscReg(MISCREG_PSTATE, (1 << 4) | (1 << 2));
 
     //Turn on red and hpriv, set everything else to 0
     MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
@@ -607,6 +615,10 @@ void PowerOnReset::invoke(ThreadContext * tc)
     //The tick register is unreadable by nonprivileged software
     tc->setMiscReg(MISCREG_TICK, 1ULL << 63);
 
+    //Enter RED state. We do this last so that the actual state preserved in
+    //the trap stack is the state from before this fault.
+    enterREDState(tc);
+
     Addr PC, NPC;
     getREDVector(trapType(), PC, NPC);
     tc->setPC(PC);