Fixes for full-system call_pal instruction.
authorSteve Reinhardt <stever@eecs.umich.edu>
Tue, 16 Dec 2003 05:06:09 +0000 (21:06 -0800)
committerSteve Reinhardt <stever@eecs.umich.edu>
Tue, 16 Dec 2003 05:06:09 +0000 (21:06 -0800)
arch/alpha/alpha_memory.cc:
    Rename md_mode_type to mode_type.
arch/alpha/ev5.cc:
    simPalCheck() only gets called on correct path now, so
    there's no need to test misspeculating().
arch/alpha/isa_desc:
    Get privileged call_pall detection right this time (I hope).
    ExecContext::simPalCheck() and Annotate::Callpal() are now
    called only on non-speculative executions... this should fix
    the bogus pal-call stats we've been seeing (since these are
    incremented in simPalCheck()).
    Also check for invalid call_pall function codes.

--HG--
extra : convert_revision : 465d6724884007d3fa066d14cd5e6db0cd3954e1

arch/alpha/alpha_memory.cc
arch/alpha/ev5.cc
arch/alpha/isa_desc

index c79b821d0b260438cb4319ec5d3b95380e412741..d934299b8f80e3d8781f48ad936a4a4128de6773 100644 (file)
@@ -436,12 +436,12 @@ AlphaDtb::translate(MemReqPtr req, bool write) const
     else
         read_accesses++;
 
-    AlphaISA::md_mode_type mode =
-        (AlphaISA::md_mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
+    AlphaISA::mode_type mode =
+        (AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
 
     if (PC_PAL(pc)) {
-        mode = (req->flags & ALTMODE) ? (AlphaISA::md_mode_type)
-            (ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE]))
+        mode = (req->flags & ALTMODE) ?
+            (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE])
             : AlphaISA::mode_kernel;
     }
 
index 6759fdbf9ab92f6c54d069e83e286e56b3122e03..8494ee9f65aeddcad5d35fdff363f1c0d182f3a5 100644 (file)
@@ -551,16 +551,14 @@ ExecContext::simPalCheck(int palFunc)
 
     switch (palFunc) {
       case PAL::halt:
-        if (!misspeculating()) {
-            halt();
-            if (--System::numSystemsRunning == 0)
-                new SimExitEvent("all cpus halted");
-        }
+        halt();
+        if (--System::numSystemsRunning == 0)
+            new SimExitEvent("all cpus halted");
         break;
 
       case PAL::bpt:
       case PAL::bugchk:
-        if (!misspeculating() && system->breakpoint())
+        if (system->breakpoint())
             return false;
         break;
     }
index aef9135d3e78d43419796abb73d1241636b6b437..293b0fcf6b00ed2567cee97fb9e8e3274c7f1f72 100644 (file)
@@ -1399,6 +1399,7 @@ declare {{
       protected:
        int palFunc;    ///< Function code part of instruction
        int palOffset;  ///< Target PC, offset from IPR_PAL_BASE
+       bool palValid;  ///< is the function code valid?
        bool palPriv;   ///< is this call privileged?
 
        /// Constructor.
@@ -1407,9 +1408,22 @@ declare {{
            : AlphaStaticInst(mnem, _machInst, __opClass),
              palFunc(PALFUNC)
        {
-           palPriv = ((machInst & 0x80) != 0);
-           int shortPalFunc = (machInst & 0x3f);
-           palOffset = 0x2001 + (palPriv << 12) + (shortPalFunc << 6);
+           // From the 21164 HRM (paraphrased):
+           // Bit 7 of the function code (mask 0x80) indicates
+           // whether the call is privileged (bit 7 == 0) or
+           // unprivileged (bit 7 == 1).  The privileged call table
+           // starts at 0x2000, the unprivielged call table starts at
+           // 0x3000.  Bits 5-0 (mask 0x3f) are used to calculate the
+           // offset.
+           const int palPrivMask = 0x80;
+           const int palOffsetMask = 0x3f;
+
+           // Pal call is invalid unless all other bits are 0
+           palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0);
+           palPriv = ((machInst & palPrivMask) == 0);
+           int shortPalFunc = (machInst & palOffsetMask);
+           // Add 1 to base to set pal-mode bit
+           palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6);
        }
 
        std::string generateDisassembly(Addr pc, const SymbolTable *symtab)
@@ -2353,25 +2367,33 @@ decode OPCODE default Unknown::unknown() {
 
 #ifdef FULL_SYSTEM
     0x00: CallPal::call_pal({{
-       if (palPriv && !PC_PAL(xc->regs.pc)) {
-           // attempt to do privileged PAL call in non-PAL mode
+       using namespace AlphaISA;
+
+       if (!palValid ||
+           (palPriv && xc->readIpr(IPR_ICM, fault) != mode_kernel)) {
+           // invalid pal function code, or attempt to do privileged
+           // PAL call in non-kernel mode
            fault = Unimplemented_Opcode_Fault;
        }
        else {
-           // check to see if simulator wants to do something special
-           // on this PAL call (including maybe suppress it)
-           bool dopal = xc->simPalCheck(palFunc);
-
            if (!xc->misspeculating()) {
+               // check to see if simulator wants to do something special
+               // on this PAL call (including maybe suppress it)
+               bool dopal = xc->simPalCheck(palFunc);
+
                Annotate::Callpal(xc, palFunc);
+
+               if (dopal) {
+                   swap_palshadow(&xc->regs, true);
+                   xc->setIpr(IPR_EXC_ADDR, NPC);
+               }
            }
 
+           // if we're misspeculating, it's still safe (if
+           // unrealistic) to set NPC, as the control-flow change
+           // won't get committed.
            if (dopal) {
-               if (!xc->misspeculating()) {
-                   AlphaISA::swap_palshadow(&xc->regs, true);
-               }
-               xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
-               NPC = xc->readIpr(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
+               NPC = xc->readIpr(IPR_PAL_BASE, fault) + palOffset;
            }
        }
     }});