ARM: Implement and update the DFSR and IFSR registers on faults.

This commit is contained in:
Gabe Black 2010-06-02 12:58:14 -05:00
parent 4491170df6
commit 527b735cfc
4 changed files with 118 additions and 24 deletions

View file

@ -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

View 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

View 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__

View 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);
}
}
}