2c2
< * Copyright (c) 2010 ARM Limited
---
> * Copyright (c) 2010, 2012-2013 ARM Limited
42a43,44
> * Giacomo Gabrielli
> * Thomas Grocutt
48a51
> #include "arch/arm/pagetable.hh"
62a66,75
> ExtMachInst machInst;
> uint32_t issRaw;
>
> // Helper variables for ARMv8 exception handling
> bool from64; // True if the exception is generated from the AArch64 state
> bool to64; // True if the exception is taken in AArch64 state
> ExceptionLevel fromEL; // Source exception level
> ExceptionLevel toEL; // Target exception level
> OperatingMode fromMode; // Source operating mode
>
63a77
> Addr getVector64(ThreadContext *tc);
66c80,84
< enum StatusEncoding
---
> /// Generic fault source enums used to index into
> /// {short/long/aarch64}DescFaultSources[] to get the actual encodings based
> /// on the current register width state and the translation table format in
> /// use
> enum FaultSource
68,89c86,100
< // 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,
< SynchronousExternalAbort1 = 0x8,
< Domain1 = 0xb,
< TranslationTableWalkExtAbt0 = 0xc,
< Permission0 = 0xd,
< TranslationTableWalkExtAbt1 = 0xe,
< Permission1 = 0xf,
< AsynchronousExternalAbort = 0x16,
< MemoryAccessAsynchronousParityError = 0x18,
< MemoryAccessSynchronousParityError = 0x19,
< TranslationTableWalkPrtyErr0 = 0x1c,
< TranslationTableWalkPrtyErr1 = 0x1e,
---
> AlignmentFault = 0,
> InstructionCacheMaintenance, // Short-desc. format only
> SynchExtAbtOnTranslTableWalkLL,
> SynchPtyErrOnTranslTableWalkLL = SynchExtAbtOnTranslTableWalkLL + 4,
> TranslationLL = SynchPtyErrOnTranslTableWalkLL + 4,
> AccessFlagLL = TranslationLL + 4,
> DomainLL = AccessFlagLL + 4,
> PermissionLL = DomainLL + 4,
> DebugEvent = PermissionLL + 4,
> SynchronousExternalAbort,
> TLBConflictAbort, // Requires LPAE
> SynchPtyErrOnMemoryAccess,
> AsynchronousExternalAbort,
> AsynchPtyErrOnMemoryAccess,
> AddressSizeLL, // AArch64 only
91,96c102,109
< // not a real fault. This is a status code
< // to allow the translation function to inform
< // the memory access function not to proceed
< // for a Prefetch that misses in the TLB.
< PrefetchTLBMiss = 0x1f,
< PrefetchUncacheable = 0x20
---
> // Not real faults. These are faults to allow the translation function
> // to inform the memory access function not to proceed for a prefetch
> // that misses in the TLB or that targets an uncacheable address
> PrefetchTLBMiss = AddressSizeLL + 4,
> PrefetchUncacheable,
>
> NumFaultSources,
> FaultSourceInvalid = 0xff
98a112,140
> /// Encodings of the fault sources when the short-desc. translation table
> /// format is in use (ARM ARM Issue C B3.13.3)
> static uint8_t shortDescFaultSources[NumFaultSources];
> /// Encodings of the fault sources when the long-desc. translation table
> /// format is in use (ARM ARM Issue C B3.13.3)
> static uint8_t longDescFaultSources[NumFaultSources];
> /// Encodings of the fault sources in AArch64 state
> static uint8_t aarch64FaultSources[NumFaultSources];
>
> enum AnnotationIDs
> {
> S1PTW, // DataAbort, PrefetchAbort: Stage 1 Page Table Walk,
> OVA, // DataAbort, PrefetchAbort: stage 1 Virtual Address for stage 2 faults
> SAS, // DataAbort: Syndrome Access Size
> SSE, // DataAbort: Syndrome Sign Extend
> SRT, // DataAbort: Syndrome Register Transfer
>
> // AArch64 only
> SF, // DataAbort: width of the accessed register is SixtyFour
> AR // DataAbort: Acquire/Release semantics
> };
>
> enum TranMethod
> {
> LpaeTran,
> VmsaTran,
> UnknownTran
> };
>
101a144
>
102a146,152
>
> // Offsets used for exceptions taken in AArch64 state
> const uint16_t currELTOffset;
> const uint16_t currELHOffset;
> const uint16_t lowerEL64Offset;
> const uint16_t lowerEL32Offset;
>
103a154
>
105a157,163
> // The following two values are used in place of armPcOffset and
> // thumbPcOffset when the exception return address is saved into ELR
> // registers (exceptions taken in HYP mode or in AArch64 state)
> const uint8_t armPcElrOffset;
> const uint8_t thumbPcElrOffset;
>
> const bool hypTrappable;
107a166,170
>
> // Exception class used to appropriately set the syndrome register
> // (exceptions taken in HYP mode or in AArch64 state)
> const ExceptionClass ec;
>
110a174,183
> ArmFault(ExtMachInst _machInst = 0, uint32_t _iss = 0) :
> machInst(_machInst), issRaw(_iss), from64(false), to64(false) {}
>
> // Returns the actual syndrome register to use based on the target
> // exception level
> MiscRegIndex getSyndromeReg64() const;
> // Returns the actual fault address register to use based on the target
> // exception level
> MiscRegIndex getFaultAddrReg64() const;
>
112a186,188
> void invoke64(ThreadContext *tc,
> StaticInstPtr inst = StaticInst::nullStaticInstPtr);
> virtual void annotate(AnnotationIDs id, uint64_t val) {}
114c190,191
< virtual FaultOffset offset() = 0;
---
> virtual FaultOffset offset(ThreadContext *tc) = 0;
> virtual FaultOffset offset64() = 0;
116,119c193,205
< virtual uint8_t armPcOffset() = 0;
< virtual uint8_t thumbPcOffset() = 0;
< virtual bool abortDisable() = 0;
< virtual bool fiqDisable() = 0;
---
> virtual bool routeToMonitor(ThreadContext *tc) const = 0;
> virtual bool routeToHyp(ThreadContext *tc) const { return false; }
> virtual uint8_t armPcOffset(bool isHyp) = 0;
> virtual uint8_t thumbPcOffset(bool isHyp) = 0;
> virtual uint8_t armPcElrOffset() = 0;
> virtual uint8_t thumbPcElrOffset() = 0;
> virtual bool abortDisable(ThreadContext *tc) = 0;
> virtual bool fiqDisable(ThreadContext *tc) = 0;
> virtual ExceptionClass ec(ThreadContext *tc) const = 0;
> virtual uint32_t iss() const = 0;
> virtual bool isStage2() const { return false; }
> virtual FSR getFsr(ThreadContext *tc) { return 0; }
> virtual void setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg);
128a215,216
> ArmFaultVals<T>(ExtMachInst _machInst = 0, uint32_t _iss = 0) :
> ArmFault(_machInst, _iss) {}
130,131c218,234
< FaultStat & countStat() {return vals.count;}
< FaultOffset offset() { return vals.offset; }
---
> FaultStat & countStat() { return vals.count; }
> FaultOffset offset(ThreadContext *tc);
>
> FaultOffset
> offset64()
> {
> if (toEL == fromEL) {
> if (opModeIsT(fromMode))
> return vals.currELTOffset;
> return vals.currELHOffset;
> } else {
> if (from64)
> return vals.lowerEL64Offset;
> return vals.lowerEL32Offset;
> }
> }
>
133,136c236,246
< uint8_t armPcOffset() { return vals.armPcOffset; }
< uint8_t thumbPcOffset() { return vals.thumbPcOffset; }
< bool abortDisable() { return vals.abortDisable; }
< bool fiqDisable() { return vals.fiqDisable; }
---
> virtual bool routeToMonitor(ThreadContext *tc) const { return false; }
> uint8_t armPcOffset(bool isHyp) { return isHyp ? vals.armPcElrOffset
> : vals.armPcOffset; }
> uint8_t thumbPcOffset(bool isHyp) { return isHyp ? vals.thumbPcElrOffset
> : vals.thumbPcOffset; }
> uint8_t armPcElrOffset() { return vals.armPcElrOffset; }
> uint8_t thumbPcElrOffset() { return vals.thumbPcElrOffset; }
> virtual bool abortDisable(ThreadContext* tc) { return vals.abortDisable; }
> virtual bool fiqDisable(ThreadContext* tc) { return vals.fiqDisable; }
> virtual ExceptionClass ec(ThreadContext *tc) const { return vals.ec; }
> virtual uint32_t iss() const { return issRaw; }
149d258
< ExtMachInst machInst;
152a262
> ExceptionClass overrideEc;
159,164c269,271
< machInst(_machInst), unknown(_unknown),
< mnemonic(_mnemonic), disabled(_disabled)
< {
< }
< UndefinedInstruction() :
< machInst(0), unknown(false), mnemonic("undefined"), disabled(false)
---
> ArmFaultVals<UndefinedInstruction>(_machInst),
> unknown(_unknown), mnemonic(_mnemonic), disabled(_disabled),
> overrideEc(EC_INVALID)
165a273,276
> UndefinedInstruction(ExtMachInst _machInst, uint32_t _iss, ExceptionClass _overrideEc) :
> ArmFaultVals<UndefinedInstruction>(_machInst, _iss),
> overrideEc(_overrideEc)
> {}
168a280,282
> bool routeToHyp(ThreadContext *tc) const;
> ExceptionClass ec(ThreadContext *tc) const;
> uint32_t iss() const;
174c288,294
< ExtMachInst machInst;
---
> ExceptionClass overrideEc;
> public:
> SupervisorCall(ExtMachInst _machInst, uint32_t _iss,
> ExceptionClass _overrideEc = EC_INVALID) :
> ArmFaultVals<SupervisorCall>(_machInst, _iss),
> overrideEc(_overrideEc)
> {}
175a296,304
> void invoke(ThreadContext *tc,
> StaticInstPtr inst = StaticInst::nullStaticInstPtr);
> bool routeToHyp(ThreadContext *tc) const;
> ExceptionClass ec(ThreadContext *tc) const;
> uint32_t iss() const;
> };
>
> class SecureMonitorCall : public ArmFaultVals<SecureMonitorCall>
> {
177c306,307
< SupervisorCall(ExtMachInst _machInst) : machInst(_machInst)
---
> SecureMonitorCall(ExtMachInst _machInst) :
> ArmFaultVals<SecureMonitorCall>(_machInst)
179,180d308
< SupervisorCall() : machInst(0)
< {}
183a312,313
> ExceptionClass ec(ThreadContext *tc) const;
> uint32_t iss() const;
185a316,369
> class SupervisorTrap : public ArmFaultVals<SupervisorTrap>
> {
> protected:
> ExtMachInst machInst;
> ExceptionClass overrideEc;
>
> public:
> SupervisorTrap(ExtMachInst _machInst, uint32_t _iss,
> ExceptionClass _overrideEc = EC_INVALID) :
> ArmFaultVals<SupervisorTrap>(_machInst, _iss),
> overrideEc(_overrideEc)
> {}
>
> ExceptionClass ec(ThreadContext *tc) const;
> };
>
> class SecureMonitorTrap : public ArmFaultVals<SecureMonitorTrap>
> {
> protected:
> ExtMachInst machInst;
> ExceptionClass overrideEc;
>
> public:
> SecureMonitorTrap(ExtMachInst _machInst, uint32_t _iss,
> ExceptionClass _overrideEc = EC_INVALID) :
> ArmFaultVals<SecureMonitorTrap>(_machInst, _iss),
> overrideEc(_overrideEc)
> {}
>
> ExceptionClass ec(ThreadContext *tc) const;
> };
>
> class HypervisorCall : public ArmFaultVals<HypervisorCall>
> {
> public:
> HypervisorCall(ExtMachInst _machInst, uint32_t _imm);
> };
>
> class HypervisorTrap : public ArmFaultVals<HypervisorTrap>
> {
> protected:
> ExtMachInst machInst;
> ExceptionClass overrideEc;
>
> public:
> HypervisorTrap(ExtMachInst _machInst, uint32_t _iss,
> ExceptionClass _overrideEc = EC_INVALID) :
> ArmFaultVals<HypervisorTrap>(_machInst, _iss),
> overrideEc(_overrideEc)
> {}
>
> ExceptionClass ec(ThreadContext *tc) const;
> };
>
189a374,379
> /**
> * The virtual address the fault occured at. If 2 stages of
> * translation are being used then this is the intermediate
> * physical address that is the starting point for the second
> * stage of translation.
> */
190a381,386
> /**
> * Original virtual address. If the fault was generated on the
> * second stage of translation then this variable stores the
> * virtual address used in the original stage 1 translation.
> */
> Addr OVAddr;
192,193c388,393
< uint8_t domain;
< uint8_t status;
---
> TlbEntry::DomainType domain;
> uint8_t source;
> uint8_t srcEncoded;
> bool stage2;
> bool s1ptw;
> ArmFault::TranMethod tranMethod;
196,199c396,399
< AbortFault(Addr _faultAddr, bool _write,
< uint8_t _domain, uint8_t _status) :
< faultAddr(_faultAddr), write(_write),
< domain(_domain), status(_status)
---
> AbortFault(Addr _faultAddr, bool _write, TlbEntry::DomainType _domain, uint8_t _source,
> bool _stage2, ArmFault::TranMethod _tranMethod = ArmFault::UnknownTran) :
> faultAddr(_faultAddr), write(_write), domain(_domain), source(_source),
> stage2(_stage2), s1ptw(false), tranMethod(_tranMethod)
203a404,410
>
> FSR getFsr(ThreadContext *tc);
> bool abortDisable(ThreadContext *tc);
> uint32_t iss() const;
> bool isStage2() const { return stage2; }
> void annotate(ArmFault::AnnotationIDs id, uint64_t val);
> bool isMMUFault() const;
209,210c416,418
< static const MiscRegIndex FsrIndex = MISCREG_IFSR;
< static const MiscRegIndex FarIndex = MISCREG_IFAR;
---
> static const MiscRegIndex FsrIndex = MISCREG_IFSR;
> static const MiscRegIndex FarIndex = MISCREG_IFAR;
> static const MiscRegIndex HFarIndex = MISCREG_HIFAR;
212,213c420,423
< PrefetchAbort(Addr _addr, uint8_t _status) :
< AbortFault<PrefetchAbort>(_addr, false, 0, _status)
---
> PrefetchAbort(Addr _addr, uint8_t _source, bool _stage2 = false,
> ArmFault::TranMethod _tranMethod = ArmFault::UnknownTran) :
> AbortFault<PrefetchAbort>(_addr, false, TlbEntry::DomainType::NoAccess,
> _source, _stage2, _tranMethod)
214a425,429
>
> ExceptionClass ec(ThreadContext *tc) const;
> // @todo: external aborts should be routed if SCR.EA == 1
> bool routeToMonitor(ThreadContext *tc) const;
> bool routeToHyp(ThreadContext *tc) const;
220,221c435,441
< static const MiscRegIndex FsrIndex = MISCREG_DFSR;
< static const MiscRegIndex FarIndex = MISCREG_DFAR;
---
> static const MiscRegIndex FsrIndex = MISCREG_DFSR;
> static const MiscRegIndex FarIndex = MISCREG_DFAR;
> static const MiscRegIndex HFarIndex = MISCREG_HDFAR;
> bool isv;
> uint8_t sas;
> uint8_t sse;
> uint8_t srt;
223,224c443,451
< DataAbort(Addr _addr, uint8_t _domain, bool _write, uint8_t _status) :
< AbortFault<DataAbort>(_addr, _write, _domain, _status)
---
> // AArch64 only
> bool sf;
> bool ar;
>
> DataAbort(Addr _addr, TlbEntry::DomainType _domain, bool _write, uint8_t _source,
> bool _stage2 = false, ArmFault::TranMethod _tranMethod = ArmFault::UnknownTran) :
> AbortFault<DataAbort>(_addr, _write, _domain, _source, _stage2,
> _tranMethod),
> isv(false), sas (0), sse(0), srt(0), sf(false), ar(false)
225a453,459
>
> ExceptionClass ec(ThreadContext *tc) const;
> // @todo: external aborts should be routed if SCR.EA == 1
> bool routeToMonitor(ThreadContext *tc) const;
> bool routeToHyp(ThreadContext *tc) const;
> uint32_t iss() const;
> void annotate(AnnotationIDs id, uint64_t val);
228,229c462,467
< class Interrupt : public ArmFaultVals<Interrupt> {};
< class FastInterrupt : public ArmFaultVals<FastInterrupt> {};
---
> class VirtualDataAbort : public AbortFault<VirtualDataAbort>
> {
> public:
> static const MiscRegIndex FsrIndex = MISCREG_DFSR;
> static const MiscRegIndex FarIndex = MISCREG_DFAR;
> static const MiscRegIndex HFarIndex = MISCREG_HDFAR;
230a469,536
> VirtualDataAbort(Addr _addr, TlbEntry::DomainType _domain, bool _write,
> uint8_t _source) :
> AbortFault<VirtualDataAbort>(_addr, _write, _domain, _source, false)
> {}
>
> void invoke(ThreadContext *tc, StaticInstPtr inst);
> };
>
> class Interrupt : public ArmFaultVals<Interrupt>
> {
> public:
> bool routeToMonitor(ThreadContext *tc) const;
> bool routeToHyp(ThreadContext *tc) const;
> bool abortDisable(ThreadContext *tc);
> };
>
> class VirtualInterrupt : public ArmFaultVals<VirtualInterrupt>
> {
> public:
> VirtualInterrupt();
> };
>
> class FastInterrupt : public ArmFaultVals<FastInterrupt>
> {
> public:
> bool routeToMonitor(ThreadContext *tc) const;
> bool routeToHyp(ThreadContext *tc) const;
> bool abortDisable(ThreadContext *tc);
> bool fiqDisable(ThreadContext *tc);
> };
>
> class VirtualFastInterrupt : public ArmFaultVals<VirtualFastInterrupt>
> {
> public:
> VirtualFastInterrupt();
> };
>
> /// PC alignment fault (AArch64 only)
> class PCAlignmentFault : public ArmFaultVals<PCAlignmentFault>
> {
> protected:
> /// The unaligned value of the PC
> Addr faultPC;
> public:
> PCAlignmentFault(Addr _faultPC) : faultPC(_faultPC)
> {}
> void invoke(ThreadContext *tc,
> StaticInstPtr inst = StaticInst::nullStaticInstPtr);
> };
>
> /// Stack pointer alignment fault (AArch64 only)
> class SPAlignmentFault : public ArmFaultVals<SPAlignmentFault>
> {
> public:
> SPAlignmentFault();
> };
>
> /// System error (AArch64 only)
> class SystemError : public ArmFaultVals<SystemError>
> {
> public:
> SystemError();
> void invoke(ThreadContext *tc,
> StaticInstPtr inst = StaticInst::nullStaticInstPtr);
> bool routeToMonitor(ThreadContext *tc) const;
> bool routeToHyp(ThreadContext *tc) const;
> };
>
248a555,561
> /// Illegal Instruction Set State fault (AArch64 only)
> class IllegalInstSetStateFault : public ArmFaultVals<IllegalInstSetStateFault>
> {
> public:
> IllegalInstSetStateFault();
> };
>