Move TLB faults into the normal fault classes. Now they are executed when the fault...
authorKevin Lim <ktlim@umich.edu>
Sat, 22 Apr 2006 22:09:08 +0000 (18:09 -0400)
committerKevin Lim <ktlim@umich.edu>
Sat, 22 Apr 2006 22:09:08 +0000 (18:09 -0400)
--HG--
extra : convert_revision : b5f00fff277e863b3fe43422bc39d0487c482e60

arch/alpha/faults.cc
arch/alpha/faults.hh
arch/alpha/tlb.cc
arch/alpha/tlb.hh

index e0918da21cb1a1ffe0fbf55aabfd2f71b55bf9b3..0083aa9f36106e51f3ce100008de25d0b8f29a74 100644 (file)
@@ -30,6 +30,9 @@
 #include "cpu/exec_context.hh"
 #include "cpu/base.hh"
 #include "base/trace.hh"
+#if FULL_SYSTEM
+#include "arch/alpha/ev5.hh"
+#endif
 
 namespace AlphaISA
 {
@@ -70,6 +73,10 @@ FaultName DtbAcvFault::_name = "dfault";
 FaultVect DtbAcvFault::_vect = 0x0381;
 FaultStat DtbAcvFault::_count;
 
+FaultName DtbAlignmentFault::_name = "unalign";
+FaultVect DtbAlignmentFault::_vect = 0x0301;
+FaultStat DtbAlignmentFault::_count;
+
 FaultName ItbMissFault::_name = "itbmiss";
 FaultVect ItbMissFault::_vect = 0x0181;
 FaultStat ItbMissFault::_count;
@@ -125,6 +132,44 @@ void ArithmeticFault::invoke(ExecContext * xc)
     panic("Arithmetic traps are unimplemented!");
 }
 
+void DtbFault::invoke(ExecContext * xc)
+{
+    // Set fault address and flags.  Even though we're modeling an
+    // EV5, we use the EV6 technique of not latching fault registers
+    // on VPTE loads (instead of locking the registers until IPR_VA is
+    // read, like the EV5).  The EV6 approach is cleaner and seems to
+    // work with EV5 PAL code, but not the other way around.
+    if (!xc->misspeculating()
+        && !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) {
+        // set VA register with faulting address
+        xc->setMiscReg(AlphaISA::IPR_VA, vaddr);
+
+        // set MM_STAT register flags
+        xc->setMiscReg(AlphaISA::IPR_MM_STAT,
+            (((EV5::Opcode(xc->getInst()) & 0x3f) << 11)
+             | ((EV5::Ra(xc->getInst()) & 0x1f) << 6)
+             | (flags & 0x3f)));
+
+        // set VA_FORM register with faulting formatted address
+        xc->setMiscReg(AlphaISA::IPR_VA_FORM,
+            xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3));
+    }
+
+    AlphaFault::invoke(xc);
+}
+
+void ItbFault::invoke(ExecContext * xc)
+{
+    if (!xc->misspeculating()) {
+        xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc);
+        xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM,
+                       xc->readMiscReg(AlphaISA::IPR_IVPTBR) |
+                       (AlphaISA::VAddr(pc).vpn() << 3));
+    }
+
+    AlphaFault::invoke(xc);
+}
+
 #endif
 
 } // namespace AlphaISA
index 1a196cc941c9760dbf3fa5c649f13a31ae5b10e2..e8ccc6b79b21ebd26d7c06373e44be69f9c2d188 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef __ALPHA_FAULTS_HH__
 #define __ALPHA_FAULTS_HH__
 
+#include "arch/alpha/isa_traits.hh"
 #include "sim/faults.hh"
 
 // The design of the "name" and "vect" functions is in sim/faults.hh
@@ -130,85 +131,167 @@ class InterruptFault : public AlphaFault
     FaultStat & countStat() {return _count;}
 };
 
-class NDtbMissFault : public AlphaFault
+class DtbFault : public AlphaFault
+{
+#if FULL_SYSTEM
+  private:
+    AlphaISA::VAddr vaddr;
+    uint32_t reqFlags;
+    uint64_t flags;
+  public:
+    DtbFault(AlphaISA::VAddr _vaddr, uint32_t _reqFlags, uint64_t _flags)
+        : vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags)
+    { }
+#endif
+    FaultName name() = 0;
+    FaultVect vect() = 0;
+    FaultStat & countStat() = 0;
+#if FULL_SYSTEM
+    void invoke(ExecContext * xc);
+#endif
+};
+
+class NDtbMissFault : public DtbFault
 {
   private:
     static FaultName _name;
     static FaultVect _vect;
     static FaultStat _count;
   public:
+#if FULL_SYSTEM
+    NDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+        : DtbFault(vaddr, reqFlags, flags)
+    { }
+#endif
     FaultName name() {return _name;}
     FaultVect vect() {return _vect;}
     FaultStat & countStat() {return _count;}
 };
 
-class PDtbMissFault : public AlphaFault
+class PDtbMissFault : public DtbFault
 {
   private:
     static FaultName _name;
     static FaultVect _vect;
     static FaultStat _count;
   public:
+#if FULL_SYSTEM
+    PDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+        : DtbFault(vaddr, reqFlags, flags)
+    { }
+#endif
     FaultName name() {return _name;}
     FaultVect vect() {return _vect;}
     FaultStat & countStat() {return _count;}
 };
 
-class DtbPageFault : public AlphaFault
+class DtbPageFault : public DtbFault
 {
   private:
     static FaultName _name;
     static FaultVect _vect;
     static FaultStat _count;
   public:
+#if FULL_SYSTEM
+    DtbPageFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+        : DtbFault(vaddr, reqFlags, flags)
+    { }
+#endif
     FaultName name() {return _name;}
     FaultVect vect() {return _vect;}
     FaultStat & countStat() {return _count;}
 };
 
-class DtbAcvFault : public AlphaFault
+class DtbAcvFault : public DtbFault
 {
   private:
     static FaultName _name;
     static FaultVect _vect;
     static FaultStat _count;
   public:
+#if FULL_SYSTEM
+    DtbAcvFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+        : DtbFault(vaddr, reqFlags, flags)
+    { }
+#endif
     FaultName name() {return _name;}
     FaultVect vect() {return _vect;}
     FaultStat & countStat() {return _count;}
 };
 
-class ItbMissFault : public AlphaFault
+class DtbAlignmentFault : public DtbFault
+{
+  private:
+    static FaultName _name;
+    static FaultVect _vect;
+    static FaultStat _count;
+  public:
+#if FULL_SYSTEM
+    DtbAlignmentFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
+        : DtbFault(vaddr, reqFlags, flags)
+    { }
+#endif
+    FaultName name() {return _name;}
+    FaultVect vect() {return _vect;}
+    FaultStat & countStat() {return _count;}
+};
+
+class ItbFault : public AlphaFault
+{
+  private:
+    Addr pc;
+  public:
+    ItbFault(Addr _pc)
+        : pc(_pc)
+    { }
+    FaultName name() = 0;
+    FaultVect vect() = 0;
+    FaultStat & countStat() = 0;
+#if FULL_SYSTEM
+    void invoke(ExecContext * xc);
+#endif
+};
+
+class ItbMissFault : public ItbFault
 {
   private:
     static FaultName _name;
     static FaultVect _vect;
     static FaultStat _count;
   public:
+    ItbMissFault(Addr pc)
+        : ItbFault(pc)
+    { }
     FaultName name() {return _name;}
     FaultVect vect() {return _vect;}
     FaultStat & countStat() {return _count;}
 };
 
-class ItbPageFault : public AlphaFault
+class ItbPageFault : public ItbFault
 {
   private:
     static FaultName _name;
     static FaultVect _vect;
     static FaultStat _count;
   public:
+    ItbPageFault(Addr pc)
+        : ItbFault(pc)
+    { }
     FaultName name() {return _name;}
     FaultVect vect() {return _vect;}
     FaultStat & countStat() {return _count;}
 };
 
-class ItbAcvFault : public AlphaFault
+class ItbAcvFault : public ItbFault
 {
   private:
     static FaultName _name;
     static FaultVect _vect;
     static FaultStat _count;
   public:
+    ItbAcvFault(Addr pc)
+        : ItbFault(pc)
+    { }
     FaultName name() {return _name;}
     FaultVect vect() {return _vect;}
     FaultStat & countStat() {return _count;}
index e30a8e595968d87684e27aaa0c319fd316d53773..562235ef8d9aec6cc5b56c1a0310c3276ab1e138 100644 (file)
@@ -290,17 +290,6 @@ AlphaITB::regStats()
     accesses = hits + misses;
 }
 
-void
-AlphaITB::fault(Addr pc, ExecContext *xc) const
-{
-    if (!xc->misspeculating()) {
-        xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc);
-        xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM,
-                       xc->readMiscReg(AlphaISA::IPR_IVPTBR) |
-                       (AlphaISA::VAddr(pc).vpn() << 3));
-    }
-}
-
 
 Fault
 AlphaITB::translate(MemReqPtr &req) const
@@ -319,9 +308,8 @@ AlphaITB::translate(MemReqPtr &req) const
     } else {
         // verify that this is a good virtual address
         if (!validVirtualAddress(req->vaddr)) {
-            fault(req->vaddr, req->xc);
             acv++;
-            return new ItbAcvFault;
+            return new ItbAcvFault(req->vaddr);
         }
 
 
@@ -336,9 +324,8 @@ AlphaITB::translate(MemReqPtr &req) const
             // only valid in kernel mode
             if (ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM)) !=
                 AlphaISA::mode_kernel) {
-                fault(req->vaddr, req->xc);
                 acv++;
-                return new ItbAcvFault;
+                return new ItbAcvFault(req->vaddr);
             }
 
             req->paddr = req->vaddr & PAddrImplMask;
@@ -358,9 +345,8 @@ AlphaITB::translate(MemReqPtr &req) const
                                         asn);
 
             if (!pte) {
-                fault(req->vaddr, req->xc);
                 misses++;
-                return new ItbPageFault;
+                return new ItbPageFault(req->vaddr);
             }
 
             req->paddr = (pte->ppn << AlphaISA::PageShift) +
@@ -370,9 +356,8 @@ AlphaITB::translate(MemReqPtr &req) const
             if (!(pte->xre &
                   (1 << ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM))))) {
                 // instruction access fault
-                fault(req->vaddr, req->xc);
                 acv++;
-                return new ItbAcvFault;
+                return new ItbAcvFault(req->vaddr);
             }
 
             hits++;
@@ -465,34 +450,6 @@ AlphaDTB::regStats()
     accesses = read_accesses + write_accesses;
 }
 
-void
-AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
-{
-    ExecContext *xc = req->xc;
-    AlphaISA::VAddr vaddr = req->vaddr;
-
-    // Set fault address and flags.  Even though we're modeling an
-    // EV5, we use the EV6 technique of not latching fault registers
-    // on VPTE loads (instead of locking the registers until IPR_VA is
-    // read, like the EV5).  The EV6 approach is cleaner and seems to
-    // work with EV5 PAL code, but not the other way around.
-    if (!xc->misspeculating()
-        && !(req->flags & VPTE) && !(req->flags & NO_FAULT)) {
-        // set VA register with faulting address
-        xc->setMiscReg(AlphaISA::IPR_VA, req->vaddr);
-
-        // set MM_STAT register flags
-        xc->setMiscReg(AlphaISA::IPR_MM_STAT,
-            (((Opcode(xc->getInst()) & 0x3f) << 11)
-             | ((Ra(xc->getInst()) & 0x1f) << 6)
-             | (flags & 0x3f)));
-
-        // set VA_FORM register with faulting formatted address
-        xc->setMiscReg(AlphaISA::IPR_VA_FORM,
-            xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3));
-    }
-}
-
 Fault
 AlphaDTB::translate(MemReqPtr &req, bool write) const
 {
@@ -507,10 +464,10 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
      * Check for alignment faults
      */
     if (req->vaddr & (req->size - 1)) {
-        fault(req, write ? MM_STAT_WR_MASK : 0);
         DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr,
                 req->size);
-        return genAlignmentFault();
+        uint64_t flags = write ? MM_STAT_WR_MASK : 0;
+        return new DtbAlignmentFault(req->vaddr, req->flags, flags);
     }
 
     if (pc & 0x1) {
@@ -525,12 +482,11 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
     } else {
         // verify that this is a good virtual address
         if (!validVirtualAddress(req->vaddr)) {
-            fault(req, (write ? MM_STAT_WR_MASK : 0) |
-                  MM_STAT_BAD_VA_MASK |
-                  MM_STAT_ACV_MASK);
-
             if (write) { write_acv++; } else { read_acv++; }
-            return new DtbPageFault;
+            uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
+                MM_STAT_BAD_VA_MASK |
+                MM_STAT_ACV_MASK;
+            return new DtbPageFault(req->vaddr, req->flags, flags);
         }
 
         // Check for "superpage" mapping
@@ -544,10 +500,10 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
             // only valid in kernel mode
             if (DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM)) !=
                 AlphaISA::mode_kernel) {
-                fault(req, ((write ? MM_STAT_WR_MASK : 0) |
-                            MM_STAT_ACV_MASK));
                 if (write) { write_acv++; } else { read_acv++; }
-                return new DtbAcvFault;
+                uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
+                                  MM_STAT_ACV_MASK);
+                return new DtbAcvFault(req->vaddr, req->flags, flags);
             }
 
             req->paddr = req->vaddr & PAddrImplMask;
@@ -574,12 +530,14 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
 
             if (!pte) {
                 // page fault
-                fault(req, (write ? MM_STAT_WR_MASK : 0) |
-                      MM_STAT_DTB_MISS_MASK);
                 if (write) { write_misses++; } else { read_misses++; }
+                uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
+                    MM_STAT_DTB_MISS_MASK;
                 return (req->flags & VPTE) ?
-                    (Fault)(new PDtbMissFault) :
-                    (Fault)(new NDtbMissFault);
+                    (Fault)(new PDtbMissFault(req->vaddr, req->flags,
+                                              flags)) :
+                    (Fault)(new NDtbMissFault(req->vaddr, req->flags,
+                                              flags));
             }
 
             req->paddr = (pte->ppn << AlphaISA::PageShift) +
@@ -588,29 +546,29 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
             if (write) {
                 if (!(pte->xwe & MODE2MASK(mode))) {
                     // declare the instruction access fault
-                    fault(req, MM_STAT_WR_MASK |
-                          MM_STAT_ACV_MASK |
-                          (pte->fonw ? MM_STAT_FONW_MASK : 0));
                     write_acv++;
-                    return new DtbPageFault;
+                    uint64_t flags = MM_STAT_WR_MASK |
+                        MM_STAT_ACV_MASK |
+                        (pte->fonw ? MM_STAT_FONW_MASK : 0);
+                    return new DtbPageFault(req->vaddr, req->flags, flags);
                 }
                 if (pte->fonw) {
-                    fault(req, MM_STAT_WR_MASK |
-                          MM_STAT_FONW_MASK);
                     write_acv++;
-                    return new DtbPageFault;
+                    uint64_t flags = MM_STAT_WR_MASK |
+                        MM_STAT_FONW_MASK;
+                    return new DtbPageFault(req->vaddr, req->flags, flags);
                 }
             } else {
                 if (!(pte->xre & MODE2MASK(mode))) {
-                    fault(req, MM_STAT_ACV_MASK |
-                          (pte->fonr ? MM_STAT_FONR_MASK : 0));
                     read_acv++;
-                    return new DtbAcvFault;
+                    uint64_t flags = MM_STAT_ACV_MASK |
+                        (pte->fonr ? MM_STAT_FONR_MASK : 0);
+                    return new DtbAcvFault(req->vaddr, req->flags, flags);
                 }
                 if (pte->fonr) {
-                    fault(req, MM_STAT_FONR_MASK);
                     read_acv++;
-                    return new DtbPageFault;
+                    uint64_t flags = MM_STAT_FONR_MASK;
+                    return new DtbPageFault(req->vaddr, req->flags, flags);
                 }
             }
         }
index de955fa46bea37a8204ec6cd05d95fa91ec50a8d..676345f01b7221412f4baaca3073da010d1a4e97 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <map>
 
+#include "arch/alpha/ev5.hh"
 #include "arch/alpha/isa_traits.hh"
 #include "arch/alpha/faults.hh"
 #include "base/statistics.hh"
@@ -87,9 +88,6 @@ class AlphaITB : public AlphaTLB
     mutable Stats::Scalar<> acv;
     mutable Stats::Formula accesses;
 
-  protected:
-    void fault(Addr pc, ExecContext *xc) const;
-
   public:
     AlphaITB(const std::string &name, int size);
     virtual void regStats();
@@ -113,9 +111,6 @@ class AlphaDTB : public AlphaTLB
     Stats::Formula acv;
     Stats::Formula accesses;
 
-  protected:
-    void fault(MemReqPtr &req, uint64_t flags) const;
-
   public:
     AlphaDTB(const std::string &name, int size);
     virtual void regStats();