diff options
Diffstat (limited to 'src/arch/mips/faults.hh')
-rw-r--r-- | src/arch/mips/faults.hh | 282 |
1 files changed, 157 insertions, 125 deletions
diff --git a/src/arch/mips/faults.hh b/src/arch/mips/faults.hh index afc9b400a..e78abbb43 100644 --- a/src/arch/mips/faults.hh +++ b/src/arch/mips/faults.hh @@ -44,21 +44,63 @@ namespace MipsISA typedef const Addr FaultVect; +enum ExcCode { + // A dummy value to use when the code isn't defined or doesn't matter. + ExcCodeDummy = 0, + + ExcCodeInt = 0, + ExcCodeMod = 1, + ExcCodeTlbL = 2, + ExcCodeTlbS = 3, + ExcCodeAdEL = 4, + ExcCodeAdES = 5, + ExcCodeIBE = 6, + ExcCodeDBE = 7, + ExcCodeSys = 8, + ExcCodeBp = 9, + ExcCodeRI = 10, + ExcCodeCpU = 11, + ExcCodeOv = 12, + ExcCodeTr = 13, + ExcCodeC2E = 18, + ExcCodeMDMX = 22, + ExcCodeWatch = 23, + ExcCodeMCheck = 24, + ExcCodeThread = 25, + ExcCodeCacheErr = 30 +}; + class MipsFaultBase : public FaultBase { public: struct FaultVals { const FaultName name; - const FaultVect vect; + const FaultVect offset; + const ExcCode code; }; -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInst::StaticInstPtr inst = StaticInst::nullStaticInstPtr) - {} -#endif void setExceptionState(ThreadContext *, uint8_t); + + virtual FaultVect offset(ThreadContext *tc) const = 0; + virtual ExcCode code() const = 0; + virtual FaultVect base(ThreadContext *tc) const + { + StatusReg status = tc->readMiscReg(MISCREG_STATUS); + if (status.bev) + return tc->readMiscReg(MISCREG_EBASE); + else + return 0xbfc00200; + } + + FaultVect + vect(ThreadContext *tc) const + { + return base(tc) + offset(tc); + } + + void invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); }; template <typename T> @@ -68,54 +110,22 @@ class MipsFault : public MipsFaultBase static FaultVals vals; public: FaultName name() const { return vals.name; } - FaultVect vect() const { return vals.vect; } -}; - -template <typename T> -class AddressFault : public MipsFault<T> -{ - protected: - Addr vaddr; - bool store; - - AddressFault(Addr _vaddr, bool _store) : vaddr(_vaddr), store(_store) - {} + FaultVect offset(ThreadContext *tc) const { return vals.offset; } + ExcCode code() const { return vals.code; } }; -template <typename T> -class TlbFault : public AddressFault<T> -{ - protected: - Addr asid; - Addr vpn; - - TlbFault(Addr _asid, Addr _vaddr, Addr _vpn, bool _store) : - AddressFault<T>(_vaddr, _store), asid(_asid), vpn(_vpn) - {} - - void - setTlbExceptionState(ThreadContext *tc, uint8_t excCode) - { - DPRINTF(MipsPRA, "%s encountered.\n", name()); - this->setExceptionState(tc, excCode); - - tc->setMiscRegNoEffect(MISCREG_BADVADDR, this->vaddr); - EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI); - entryHi.asid = this->asid; - entryHi.vpn2 = this->vpn >> 2; - entryHi.vpn2x = this->vpn & 0x3; - tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi); - - ContextReg context = tc->readMiscReg(MISCREG_CONTEXT); - context.badVPN2 = this->vpn >> 2; - tc->setMiscRegNoEffect(MISCREG_CONTEXT, context); - } -}; +class SystemCallFault : public MipsFault<SystemCallFault> {}; +class ReservedInstructionFault : public MipsFault<ReservedInstructionFault> {}; +class ThreadFault : public MipsFault<ThreadFault> {}; +class IntegerOverflowFault : public MipsFault<IntegerOverflowFault> {}; +class TrapFault : public MipsFault<TrapFault> {}; +class BreakpointFault : public MipsFault<BreakpointFault> {}; +class DspStateDisabledFault : public MipsFault<DspStateDisabledFault> {}; class MachineCheckFault : public MipsFault<MachineCheckFault> { public: - bool isMachineCheckFault() {return true;} + bool isMachineCheckFault() { return true; } }; static inline Fault genMachineCheckFault() @@ -123,25 +133,6 @@ static inline Fault genMachineCheckFault() return new MachineCheckFault; } -class NonMaskableInterrupt : public MipsFault<NonMaskableInterrupt> -{ - public: - bool isNonMaskableInterrupt() {return true;} -}; - -class AddressErrorFault : public AddressFault<AddressErrorFault> -{ - public: - AddressErrorFault(Addr _vaddr, bool _store) : - AddressFault<AddressErrorFault>(_vaddr, _store) - {} -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif - -}; - class ResetFault : public MipsFault<ResetFault> { public: @@ -150,16 +141,14 @@ class ResetFault : public MipsFault<ResetFault> }; -class SystemCallFault : public MipsFault<SystemCallFault> +class SoftResetFault : public MipsFault<SoftResetFault> { public: -#if FULL_SYSTEM void invoke(ThreadContext * tc, StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif }; -class SoftResetFault : public MipsFault<SoftResetFault> +class NonMaskableInterrupt : public MipsFault<NonMaskableInterrupt> { public: void invoke(ThreadContext * tc, @@ -174,58 +163,111 @@ class CoprocessorUnusableFault : public MipsFault<CoprocessorUnusableFault> CoprocessorUnusableFault(int _procid) : coProcID(_procid) {} - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); + void + invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr) + { + MipsFault<CoprocessorUnusableFault>::invoke(tc, inst); + if (FULL_SYSTEM) { + CauseReg cause = tc->readMiscReg(MISCREG_CAUSE); + cause.ce = coProcID; + tc->setMiscReg(MISCREG_CAUSE, cause); + } + } }; -class ReservedInstructionFault : public MipsFault<ReservedInstructionFault> +class InterruptFault : public MipsFault<InterruptFault> { public: - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); + FaultVect + offset(ThreadContext *tc) const + { + CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE); + return cause.iv ? 0x200 : 0x000; + } }; -class ThreadFault : public MipsFault<ThreadFault> +template <typename T> +class AddressFault : public MipsFault<T> { - public: - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -}; + protected: + Addr vaddr; + bool store; -class IntegerOverflowFault : public MipsFault<IntegerOverflowFault> -{ - public: -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif -}; + AddressFault(Addr _vaddr, bool _store) : vaddr(_vaddr), store(_store) + {} -class InterruptFault : public MipsFault<InterruptFault> -{ - public: -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif + void + invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr) + { + MipsFault<T>::invoke(tc, inst); + if (FULL_SYSTEM) + tc->setMiscRegNoEffect(MISCREG_BADVADDR, vaddr); + } }; -class TrapFault : public MipsFault<TrapFault> +class AddressErrorFault : public AddressFault<AddressErrorFault> { public: -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif + AddressErrorFault(Addr _vaddr, bool _store) : + AddressFault<AddressErrorFault>(_vaddr, _store) + {} + + ExcCode + code() const + { + return store ? ExcCodeAdES : ExcCodeAdEL; + } + }; -class BreakpointFault : public MipsFault<BreakpointFault> +template <typename T> +class TlbFault : public AddressFault<T> { - public: -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif + protected: + Addr asid; + Addr vpn; + + TlbFault(Addr _asid, Addr _vaddr, Addr _vpn, bool _store) : + AddressFault<T>(_vaddr, _store), asid(_asid), vpn(_vpn) + {} + + void + setTlbExceptionState(ThreadContext *tc, uint8_t excCode) + { + this->setExceptionState(tc, excCode); + + tc->setMiscRegNoEffect(MISCREG_BADVADDR, this->vaddr); + EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI); + entryHi.asid = this->asid; + entryHi.vpn2 = this->vpn >> 2; + entryHi.vpn2x = this->vpn & 0x3; + tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi); + + ContextReg context = tc->readMiscReg(MISCREG_CONTEXT); + context.badVPN2 = this->vpn >> 2; + tc->setMiscRegNoEffect(MISCREG_CONTEXT, context); + } + + void + invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr) + { + if (FULL_SYSTEM) { + DPRINTF(MipsPRA, "Fault %s encountered.\n", name()); + tc->pcState(this->vect(tc)); + setTlbExceptionState(tc, this->code()); + } else { + AddressFault<T>::invoke(tc, inst); + } + } + + ExcCode + code() const + { + return this->store ? ExcCodeTlbS : ExcCodeTlbL; + } }; class TlbRefillFault : public TlbFault<TlbRefillFault> @@ -234,10 +276,13 @@ class TlbRefillFault : public TlbFault<TlbRefillFault> TlbRefillFault(Addr asid, Addr vaddr, Addr vpn, bool store) : TlbFault<TlbRefillFault>(asid, vaddr, vpn, store) {} -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif + + FaultVect + offset(ThreadContext *tc) const + { + StatusReg status = tc->readMiscReg(MISCREG_STATUS); + return status.exl ? 0x180 : 0x000; + } }; class TlbInvalidFault : public TlbFault<TlbInvalidFault> @@ -246,10 +291,6 @@ class TlbInvalidFault : public TlbFault<TlbInvalidFault> TlbInvalidFault(Addr asid, Addr vaddr, Addr vpn, bool store) : TlbFault<TlbInvalidFault>(asid, vaddr, vpn, store) {} -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif }; class TlbModifiedFault : public TlbFault<TlbModifiedFault> @@ -258,17 +299,8 @@ class TlbModifiedFault : public TlbFault<TlbModifiedFault> TlbModifiedFault(Addr asid, Addr vaddr, Addr vpn) : TlbFault<TlbModifiedFault>(asid, vaddr, vpn, false) {} -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif -}; -class DspStateDisabledFault : public MipsFault<DspStateDisabledFault> -{ - public: - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); + ExcCode code() const { return vals.code; } }; } // namespace MipsISA |