summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:14 -0500
committerGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:14 -0500
commit527b735cfc1e9031dc0a63ab43b1eb2ecf1fa4ec (patch)
tree61134ba71b8da4a6f288abcda2eb8517a1648891 /src
parent4491170df6e7a130c43d38d4220e5dff3c1dd214 (diff)
downloadgem5-527b735cfc1e9031dc0a63ab43b1eb2ecf1fa4ec.tar.xz
ARM: Implement and update the DFSR and IFSR registers on faults.
Diffstat (limited to 'src')
-rw-r--r--src/arch/arm/faults.cc36
-rw-r--r--src/arch/arm/faults.hh84
-rw-r--r--src/arch/arm/miscregs.hh19
-rw-r--r--src/arch/arm/tlb.cc3
4 files changed, 118 insertions, 24 deletions
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<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
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<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
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);
}
}
}