diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc index 528fc32a5..f1ecd31b9 100644 --- a/src/arch/arm/faults.cc +++ b/src/arch/arm/faults.cc @@ -50,29 +50,29 @@ namespace ArmISA { -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"reset", 0x00, MODE_SVC, 0, 0, true, true}; -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"Undefined Instruction", 0x04, MODE_UNDEFINED, 4 ,2, false, false} ; -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"Supervisor Call", 0x08, MODE_SVC, 4, 2, false, false}; -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"Prefetch Abort", 0x0C, MODE_ABORT, 4, 4, true, false}; -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"Data Abort", 0x10, MODE_ABORT, 8, 8, true, false}; -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::vals = {"IRQ", 0x18, MODE_IRQ, 4, 4, true, false}; -template<> ArmFaultBase::FaultVals ArmFault::vals = +template<> ArmFault::FaultVals ArmFaultVals::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 +void +AbortFault::invoke(ThreadContext *tc) +{ + ArmFaultVals::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::invoke(ThreadContext *tc); +template void AbortFault::invoke(ThreadContext *tc); + // return via SUBS pc, lr, xxx; rfe, movs, ldm diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh index 64940dd26..7339e0e63 100644 --- a/src/arch/arm/faults.hh +++ b/src/arch/arm/faults.hh @@ -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 -class ArmFault : public ArmFaultBase +class ArmFaultVals : public ArmFault { protected: static FaultVals vals; @@ -103,9 +129,9 @@ class ArmFault : public ArmFaultBase }; -class Reset : public ArmFault {}; +class Reset : public ArmFaultVals {}; -class UndefinedInstruction : public ArmFault +class UndefinedInstruction : public ArmFaultVals { #if !FULL_SYSTEM protected: @@ -125,7 +151,7 @@ class UndefinedInstruction : public ArmFault #endif }; -class SupervisorCall : public ArmFault +class SupervisorCall : public ArmFaultVals { #if !FULL_SYSTEM protected: @@ -138,10 +164,50 @@ class SupervisorCall : public ArmFault void invoke(ThreadContext *tc); #endif }; -class PrefetchAbort : public ArmFault {}; -class DataAbort : public ArmFault {}; -class Interrupt : public ArmFault {}; -class FastInterrupt : public ArmFault {}; + +template +class AbortFault : public ArmFaultVals +{ + 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 +{ + public: + static const MiscRegIndex FsrIndex = MISCREG_IFSR; + static const MiscRegIndex FarIndex = MISCREG_IFAR; + + PrefetchAbort(Addr _addr, uint8_t _status) : + AbortFault(_addr, false, 0, _status) + {} +}; + +class DataAbort : public AbortFault +{ + 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(_addr, _write, _domain, _status) + {} +}; + +class Interrupt : public ArmFaultVals {}; +class FastInterrupt : public ArmFaultVals {}; } // ArmISA namespace diff --git a/src/arch/arm/miscregs.hh b/src/arch/arm/miscregs.hh index badad6c31..9c781f515 100644 --- a/src/arch/arm/miscregs.hh +++ b/src/arch/arm/miscregs.hh @@ -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__ diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index 8e1baf126..f9257a005 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -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); } } }