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
#if FULL_SYSTEM
void
-ArmFaultBase::invoke(ThreadContext *tc)
+ArmFault::invoke(ThreadContext *tc)
{
// ARM ARM B1.6.3
FaultBase::invoke(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
#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"
{
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;
};
template<typename T>
-class ArmFault : public ArmFaultBase
+class ArmFaultVals : public ArmFault
{
protected:
static FaultVals vals;
};
-class Reset : public ArmFault<Reset> {};
+class Reset : public ArmFaultVals<Reset> {};
-class UndefinedInstruction : public ArmFault<UndefinedInstruction>
+class UndefinedInstruction : public ArmFaultVals<UndefinedInstruction>
{
#if !FULL_SYSTEM
protected:
#endif
};
-class SupervisorCall : public ArmFault<SupervisorCall>
+class SupervisorCall : public ArmFaultVals<SupervisorCall>
{
#if !FULL_SYSTEM
protected:
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
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,
MISCREG_PAR,
MISCREG_AIDR,
MISCREG_ACTLR,
- MISCREG_DFSR,
- MISCREG_IFSR,
MISCREG_ADFSR,
MISCREG_AIFSR,
- MISCREG_DFAR,
- MISCREG_IFAR,
MISCREG_DCIMVAC,
MISCREG_DCISW,
MISCREG_MCCSW,
"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",
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__
if (sctlr.a || (flags & AllowUnaligned) == 0) {
if ((vaddr & flags & AlignmentMask) != 0) {
- return new DataAbort;
+ return new DataAbort(vaddr, (mode == Write), 0,
+ ArmFault::AlignmentFault);
}
}
}