ARM: Implement and update the DFSR and IFSR registers on faults.
authorGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:14 +0000 (12:58 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:14 +0000 (12:58 -0500)
src/arch/arm/faults.cc
src/arch/arm/faults.hh
src/arch/arm/miscregs.hh
src/arch/arm/tlb.cc

index 528fc32a5d49810b75dfe43e1563638dcee0824b..f1ecd31b923859f657ac50f28cb7287a0919a72b 100644 (file)
 namespace ArmISA
 {
 
-template<> ArmFaultBase::FaultVals ArmFault<Reset>::vals = 
+template<> ArmFault::FaultVals ArmFaultVals<Reset>::vals =
     {"reset", 0x00, MODE_SVC, 0, 0, true, true};
 
-template<> ArmFaultBase::FaultVals ArmFault<UndefinedInstruction>::vals = 
+template<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals =
     {"Undefined Instruction", 0x04, MODE_UNDEFINED, 4 ,2, false, false} ;
 
-template<> ArmFaultBase::FaultVals ArmFault<SupervisorCall>::vals = 
+template<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals =
     {"Supervisor Call", 0x08, MODE_SVC, 4, 2, false, false};
 
-template<> ArmFaultBase::FaultVals ArmFault<PrefetchAbort>::vals = 
+template<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals =
     {"Prefetch Abort", 0x0C, MODE_ABORT, 4, 4, true, false};
 
-template<> ArmFaultBase::FaultVals ArmFault<DataAbort>::vals = 
+template<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals =
     {"Data Abort", 0x10, MODE_ABORT, 8, 8, true, false};
 
-template<> ArmFaultBase::FaultVals ArmFault<Interrupt>::vals = 
+template<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals =
     {"IRQ", 0x18, MODE_IRQ, 4, 4, true, false};
 
-template<> ArmFaultBase::FaultVals ArmFault<FastInterrupt>::vals = 
+template<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals =
     {"FIQ", 0x1C, MODE_FIQ, 4, 4, true, true};
 
 Addr 
-ArmFaultBase::getVector(ThreadContext *tc)
+ArmFault::getVector(ThreadContext *tc)
 {
     // ARM ARM B1-3
 
@@ -91,7 +91,7 @@ ArmFaultBase::getVector(ThreadContext *tc)
 #if FULL_SYSTEM
 
 void 
-ArmFaultBase::invoke(ThreadContext *tc)
+ArmFault::invoke(ThreadContext *tc)
 {
     // ARM ARM B1.6.3
     FaultBase::invoke(tc);
@@ -185,6 +185,24 @@ SupervisorCall::invoke(ThreadContext *tc)
 
 #endif // FULL_SYSTEM
 
+template<class T>
+void
+AbortFault<T>::invoke(ThreadContext *tc)
+{
+    ArmFaultVals<T>::invoke(tc);
+    FSR fsr = 0;
+    fsr.fsLow = bits(status, 3, 0);
+    fsr.fsHigh = bits(status, 4);
+    fsr.domain = domain;
+    fsr.wnr = (write ? 1 : 0);
+    fsr.ext = 0;
+    tc->setMiscReg(T::FsrIndex, fsr);
+    tc->setMiscReg(T::FarIndex, faultAddr);
+}
+
+template void AbortFault<PrefetchAbort>::invoke(ThreadContext *tc);
+template void AbortFault<DataAbort>::invoke(ThreadContext *tc);
+
 // return via SUBS pc, lr, xxx; rfe, movs, ldm
 
 
index 64940dd2614a5b8f83a4cb01c48dd7e8547ff65f..7339e0e632c82217f4077f03d0ff05a7e299520f 100644 (file)
@@ -45,6 +45,7 @@
 #ifndef __ARM_FAULTS_HH__
 #define __ARM_FAULTS_HH__
 
+#include "arch/arm/miscregs.hh"
 #include "arch/arm/types.hh"
 #include "config/full_system.hh"
 #include "sim/faults.hh"
@@ -55,12 +56,37 @@ namespace ArmISA
 {
 typedef const Addr FaultOffset;
 
-class ArmFaultBase : public FaultBase
+class ArmFault : public FaultBase
 {
   protected:
     Addr getVector(ThreadContext *tc);
 
   public:
+    enum StatusEncoding
+    {
+        // Fault Status register encodings
+        // ARM ARM B3.9.4
+        AlignmentFault = 0x1,
+        DebugEvent = 0x2,
+        AccessFlag0 = 0x3,
+        InstructionCacheMaintenance = 0x4,
+        Translation0 = 0x5,
+        AccessFlag1 = 0x6,
+        Translation1 = 0x7,
+        SynchronousExternalAbort0 = 0x8,
+        Domain0 = 0x9,
+        Domain1 = 0xb,
+        TranslationTableWalk0 = 0xc,
+        Permission0 = 0xd,
+        SynchronousExternalAbort1 = 0xe,
+        Permission1 = 0xf,
+        AsynchronousExternalAbort = 0x16,
+        MemoryAccessAsynchronousParityError = 0x18,
+        MemoryAccessSynchronousParityError = 0x19,
+        TranslationTableWalk1 = 0x1c,
+        SynchronousParityError = 0x1e
+    };
+
     struct FaultVals
     {
         const FaultName name;
@@ -86,7 +112,7 @@ class ArmFaultBase : public FaultBase
 };
 
 template<typename T>
-class ArmFault : public ArmFaultBase
+class ArmFaultVals : public ArmFault
 {
   protected:
     static FaultVals vals;
@@ -103,9 +129,9 @@ class ArmFault : public ArmFaultBase
 };
 
 
-class Reset                : public ArmFault<Reset> {};
+class Reset : public ArmFaultVals<Reset> {};
 
-class UndefinedInstruction : public ArmFault<UndefinedInstruction>
+class UndefinedInstruction : public ArmFaultVals<UndefinedInstruction>
 {
 #if !FULL_SYSTEM
   protected:
@@ -125,7 +151,7 @@ class UndefinedInstruction : public ArmFault<UndefinedInstruction>
 #endif
 };
 
-class SupervisorCall       : public ArmFault<SupervisorCall>
+class SupervisorCall : public ArmFaultVals<SupervisorCall>
 {
 #if !FULL_SYSTEM
   protected:
@@ -138,10 +164,50 @@ class SupervisorCall       : public ArmFault<SupervisorCall>
     void invoke(ThreadContext *tc);
 #endif
 };
-class PrefetchAbort        : public ArmFault<PrefetchAbort> {};
-class DataAbort            : public ArmFault<DataAbort> {};
-class Interrupt            : public ArmFault<Interrupt> {};
-class FastInterrupt        : public ArmFault<FastInterrupt> {};
+
+template <class T>
+class AbortFault : public ArmFaultVals<T>
+{
+  protected:
+    Addr faultAddr;
+    bool write;
+    uint8_t domain;
+    uint8_t status;
+
+  public:
+    AbortFault(Addr _faultAddr, bool _write,
+            uint8_t _domain, uint8_t _status) :
+        faultAddr(_faultAddr), write(_write),
+        domain(_domain), status(_status)
+    {}
+
+    void invoke(ThreadContext *tc);
+};
+
+class PrefetchAbort : public AbortFault<PrefetchAbort>
+{
+  public:
+    static const MiscRegIndex FsrIndex = MISCREG_IFSR;
+    static const MiscRegIndex FarIndex = MISCREG_IFAR;
+
+    PrefetchAbort(Addr _addr, uint8_t _status) :
+        AbortFault<PrefetchAbort>(_addr, false, 0, _status)
+    {}
+};
+
+class DataAbort : public AbortFault<DataAbort>
+{
+  public:
+    static const MiscRegIndex FsrIndex = MISCREG_DFSR;
+    static const MiscRegIndex FarIndex = MISCREG_DFAR;
+
+    DataAbort(Addr _addr, bool _write, uint8_t _domain, uint8_t _status) :
+        AbortFault<DataAbort>(_addr, _write, _domain, _status)
+    {}
+};
+
+class Interrupt : public ArmFaultVals<Interrupt> {};
+class FastInterrupt : public ArmFaultVals<FastInterrupt> {};
 
 
 } // ArmISA namespace
index badad6c3100c54f49e0acb2034e987b6d16a386f..9c781f5151dec8b0cfd4425aa64385231108e90a 100644 (file)
@@ -124,6 +124,10 @@ namespace ArmISA
         MISCREG_TLBIMVA,
         MISCREG_TLBIASID,
         MISCREG_TLBIMVAA,
+        MISCREG_DFSR,
+        MISCREG_IFSR,
+        MISCREG_DFAR,
+        MISCREG_IFAR,
         MISCREG_CP15_UNIMP_START,
         MISCREG_CTR = MISCREG_CP15_UNIMP_START,
         MISCREG_TCMTR,
@@ -145,12 +149,8 @@ namespace ArmISA
         MISCREG_PAR,
         MISCREG_AIDR,
         MISCREG_ACTLR,
-        MISCREG_DFSR,
-        MISCREG_IFSR,
         MISCREG_ADFSR,
         MISCREG_AIFSR,
-        MISCREG_DFAR,
-        MISCREG_IFAR,
         MISCREG_DCIMVAC,
         MISCREG_DCISW,
         MISCREG_MCCSW,
@@ -203,12 +203,13 @@ namespace ArmISA
         "itlbiall", "itlbimva", "itlbiasid",
         "dtlbiall", "dtlbimva", "dtlbiasid",
         "tlbiall", "tlbimva", "tlbiasid", "tlbimvaa",
+        "dfsr", "ifsr", "dfar", "ifar",
         "ctr", "tcmtr", "mpidr",
         "id_pfr0", "id_pfr1", "id_dfr0", "id_afr0",
         "id_mmfr0", "id_mmfr1", "id_mmfr2", "id_mmfr3",
         "id_isar0", "id_isar1", "id_isar2", "id_isar3", "id_isar4", "id_isar5",
         "par", "aidr", "actlr",
-        "dfsr", "ifsr", "adfsr", "aifsr", "dfar", "ifar",
+        "adfsr", "aifsr",
         "dcimvac", "dcisw", "mccsw",
         "dccmvau",
         "scr", "sder", "nsacr", "ttbcr",
@@ -285,6 +286,14 @@ namespace ArmISA
         Bitfield<30> d32dis;
         Bitfield<31> asedis;
     EndBitUnion(CPACR)
+
+    BitUnion32(FSR)
+        Bitfield<3, 0> fsLow;
+        Bitfield<7, 4> domain;
+        Bitfield<10> fsHigh;
+        Bitfield<11> wnr;
+        Bitfield<12> ext;
+    EndBitUnion(FSR)
 };
 
 #endif // __ARCH_ARM_MISCREGS_HH__
index 8e1baf1261525cccc6b3b5af6a80c21d68550776..f9257a005df3d86c42aadd1f22a6f96e65ed6900 100644 (file)
@@ -299,7 +299,8 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
 
         if (sctlr.a || (flags & AllowUnaligned) == 0) {
             if ((vaddr & flags & AlignmentMask) != 0) {
-                return new DataAbort;
+                return new DataAbort(vaddr, (mode == Write), 0,
+                            ArmFault::AlignmentFault);
             }
         }
     }