From 9a38dc6194b4c0ad85972b356a3d42e5ad1f55ee Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 19 Sep 2011 06:17:21 -0700 Subject: [PATCH] MIPS: Final overhaul of MIPS faults to kill #if FULL_SYSTEM This change is a significant reorganization of the MIPS fault code that gets rid of duplication, fixes some bugs, doubtlessly introduces others, and adds names for the exception code constants. --- src/arch/mips/faults.cc | 227 +++++++---------------------- src/arch/mips/faults.hh | 312 ++++++++++++++++++++++------------------ 2 files changed, 226 insertions(+), 313 deletions(-) diff --git a/src/arch/mips/faults.cc b/src/arch/mips/faults.cc index 509e03036e..9ec93f3fed 100644 --- a/src/arch/mips/faults.cc +++ b/src/arch/mips/faults.cc @@ -48,54 +48,56 @@ namespace MipsISA typedef MipsFaultBase::FaultVals FaultVals; -template <> FaultVals MipsFault::vals = - { "Machine Check", 0x0401 }; - -template <> FaultVals MipsFault::vals = -#if FULL_SYSTEM - { "Reset Fault", 0xBFC00000}; -#else - { "Reset Fault", 0x001}; -#endif - -template <> FaultVals MipsFault::vals = - { "Address Error", 0x0180 }; - template <> FaultVals MipsFault::vals = - { "Syscall", 0x0180 }; - -template <> FaultVals MipsFault::vals = - { "Coprocessor Unusable Fault", 0x180 }; + { "Syscall", 0x180, ExcCodeSys }; template <> FaultVals MipsFault::vals = - { "Reserved Instruction Fault", 0x0180 }; + { "Reserved Instruction Fault", 0x180, ExcCodeRI }; template <> FaultVals MipsFault::vals = - { "Thread Fault", 0x00F1 }; + { "Thread Fault", 0x180, ExcCodeDummy }; template <> FaultVals MipsFault::vals = - { "Integer Overflow Exception", 0x180 }; - -template <> FaultVals MipsFault::vals = - { "interrupt", 0x0180 }; + { "Integer Overflow Exception", 0x180, ExcCodeOv }; template <> FaultVals MipsFault::vals = - { "Trap", 0x0180 }; + { "Trap", 0x180, ExcCodeTr }; template <> FaultVals MipsFault::vals = - { "Breakpoint", 0x0180 }; - -template <> FaultVals MipsFault::vals = - { "Invalid TLB Entry Exception", 0x0180 }; - -template <> FaultVals MipsFault::vals = - { "TLB Refill Exception", 0x0180 }; - -template <> FaultVals MipsFault::vals = - { "TLB Modified Exception", 0x0180 }; + { "Breakpoint", 0x180, ExcCodeBp }; template <> FaultVals MipsFault::vals = - { "DSP Disabled Fault", 0x001a }; + { "DSP Disabled Fault", 0x180, ExcCodeDummy }; + +template <> FaultVals MipsFault::vals = + { "Machine Check", 0x180, ExcCodeMCheck }; + +template <> FaultVals MipsFault::vals = + { "Reset Fault", 0x000, ExcCodeDummy }; + +template <> FaultVals MipsFault::vals = + { "Soft Reset Fault", 0x000, ExcCodeDummy }; + +template <> FaultVals MipsFault::vals = + { "Non Maskable Interrupt", 0x000, ExcCodeDummy }; + +template <> FaultVals MipsFault::vals = + { "Coprocessor Unusable Fault", 0x180, ExcCodeCpU }; + +template <> FaultVals MipsFault::vals = + { "Interrupt", 0x000, ExcCodeInt }; + +template <> FaultVals MipsFault::vals = + { "Address Error", 0x180, ExcCodeDummy }; + +template <> FaultVals MipsFault::vals = + { "Invalid TLB Entry Exception", 0x180, ExcCodeDummy }; + +template <> FaultVals MipsFault::vals = + { "TLB Refill Exception", 0x180, ExcCodeDummy }; + +template <> FaultVals MipsFault::vals = + { "TLB Modified Exception", 0x180, ExcCodeMod }; void MipsFaultBase::setExceptionState(ThreadContext *tc, uint8_t excCode) @@ -129,118 +131,28 @@ MipsFaultBase::setExceptionState(ThreadContext *tc, uint8_t excCode) tc->setMiscRegNoEffect(MISCREG_CAUSE, cause); } -#if FULL_SYSTEM - void -IntegerOverflowFault::invoke(ThreadContext *tc, StaticInstPtr inst) +MipsFaultBase::invoke(ThreadContext *tc, StaticInstPtr inst) { - DPRINTF(MipsPRA, "%s encountered.\n", name()); - setExceptionState(tc, 0xC); - - // Set new PC - StatusReg status = tc->readMiscReg(MISCREG_STATUS); - if (!status.bev) { - // See MIPS ARM Vol 3, Revision 2, Page 38 - tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE)); + if (FULL_SYSTEM) { + DPRINTF(MipsPRA, "Fault %s encountered.\n", name()); + setExceptionState(tc, code()); + tc->pcState(vect(tc)); } else { - tc->pcState(0xBFC00200); + panic("Fault %s encountered.\n", name()); } } -void -TrapFault::invoke(ThreadContext *tc, StaticInstPtr inst) -{ - DPRINTF(MipsPRA, "%s encountered.\n", name()); - setExceptionState(tc, 0xD); - - tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE)); -} - -void -BreakpointFault::invoke(ThreadContext *tc, StaticInstPtr inst) -{ - setExceptionState(tc, 0x9); - - tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE)); -} - -void -AddressErrorFault::invoke(ThreadContext *tc, StaticInstPtr inst) -{ - DPRINTF(MipsPRA, "%s encountered.\n", name()); - setExceptionState(tc, store ? 0x5 : 0x4); - tc->setMiscRegNoEffect(MISCREG_BADVADDR, vaddr); - - tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE)); -} - -void -TlbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst) -{ - setTlbExceptionState(tc, store ? 0x3 : 0x2); - tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE)); -} - -void -TlbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst) -{ - // Since handler depends on EXL bit, must check EXL bit before setting it!! - StatusReg status = tc->readMiscReg(MISCREG_STATUS); - - setTlbExceptionState(tc, store ? 0x3 : 0x2); - - // See MIPS ARM Vol 3, Revision 2, Page 38 - if (status.exl == 1) { - tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE)); - } else { - tc->pcState(tc->readMiscReg(MISCREG_EBASE)); - } -} - -void -TlbModifiedFault::invoke(ThreadContext *tc, StaticInstPtr inst) -{ - setTlbExceptionState(tc, 0x1); - - tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE)); -} - -void -SystemCallFault::invoke(ThreadContext *tc, StaticInstPtr inst) -{ - DPRINTF(MipsPRA, "%s encountered.\n", name()); - setExceptionState(tc, 0x8); - - tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE)); -} - -void -InterruptFault::invoke(ThreadContext *tc, StaticInstPtr inst) -{ - DPRINTF(MipsPRA, "%s encountered.\n", name()); - setExceptionState(tc, 0x0A); - - CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE); - if (cause.iv) { - // Offset 200 for release 2 - tc->pcState(0x20 + vect() + tc->readMiscRegNoEffect(MISCREG_EBASE)); - } else { - //Ofset at 180 for release 1 - tc->pcState(vect() + tc->readMiscRegNoEffect(MISCREG_EBASE)); - } -} - -#endif // FULL_SYSTEM - void ResetFault::invoke(ThreadContext *tc, StaticInstPtr inst) { -#if FULL_SYSTEM - DPRINTF(MipsPRA, "%s encountered.\n", name()); - /* All reset activity must be invoked from here */ - tc->pcState(vect()); - DPRINTF(MipsPRA, "ResetFault::invoke : PC set to %x", tc->readPC()); -#endif + if (FULL_SYSTEM) { + DPRINTF(MipsPRA, "%s encountered.\n", name()); + /* All reset activity must be invoked from here */ + Addr handler = vect(tc); + tc->pcState(handler); + DPRINTF(MipsPRA, "ResetFault::invoke : PC set to %x", handler); + } // Set Coprocessor 1 (Floating Point) To Usable StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS); @@ -249,46 +161,15 @@ ResetFault::invoke(ThreadContext *tc, StaticInstPtr inst) } void -ReservedInstructionFault::invoke(ThreadContext *tc, StaticInstPtr inst) +SoftResetFault::invoke(ThreadContext *tc, StaticInstPtr inst) { -#if FULL_SYSTEM - DPRINTF(MipsPRA, "%s encountered.\n", name()); - setExceptionState(tc, 0x0A); - tc->pcState(vect() + tc->readMiscRegNoEffect(MISCREG_EBASE)); -#else - panic("%s encountered.\n", name()); -#endif + panic("Soft reset not implemented.\n"); } void -ThreadFault::invoke(ThreadContext *tc, StaticInstPtr inst) +NonMaskableInterrupt::invoke(ThreadContext *tc, StaticInstPtr inst) { - DPRINTF(MipsPRA, "%s encountered.\n", name()); - panic("%s encountered.\n", name()); -} - -void -DspStateDisabledFault::invoke(ThreadContext *tc, StaticInstPtr inst) -{ - DPRINTF(MipsPRA, "%s encountered.\n", name()); - panic("%s encountered.\n", name()); -} - -void -CoprocessorUnusableFault::invoke(ThreadContext *tc, StaticInstPtr inst) -{ -#if FULL_SYSTEM - DPRINTF(MipsPRA, "%s encountered.\n", name()); - setExceptionState(tc, 0xb); - // The ID of the coprocessor causing the exception is stored in - // CoprocessorUnusableFault::coProcID - CauseReg cause = tc->readMiscReg(MISCREG_CAUSE); - cause.ce = coProcID; - tc->setMiscRegNoEffect(MISCREG_CAUSE, cause); - tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE)); -#else - warn("%s (CP%d) encountered.\n", name(), coProcID); -#endif + panic("Non maskable interrupt not implemented.\n"); } } // namespace MipsISA diff --git a/src/arch/mips/faults.hh b/src/arch/mips/faults.hh index afc9b400ad..e78abbb433 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 @@ -68,7 +110,81 @@ class MipsFault : public MipsFaultBase static FaultVals vals; public: FaultName name() const { return vals.name; } - FaultVect vect() const { return vals.vect; } + FaultVect offset(ThreadContext *tc) const { return vals.offset; } + ExcCode code() const { return vals.code; } +}; + +class SystemCallFault : public MipsFault {}; +class ReservedInstructionFault : public MipsFault {}; +class ThreadFault : public MipsFault {}; +class IntegerOverflowFault : public MipsFault {}; +class TrapFault : public MipsFault {}; +class BreakpointFault : public MipsFault {}; +class DspStateDisabledFault : public MipsFault {}; + +class MachineCheckFault : public MipsFault +{ + public: + bool isMachineCheckFault() { return true; } +}; + +static inline Fault genMachineCheckFault() +{ + return new MachineCheckFault; +} + +class ResetFault : public MipsFault +{ + public: + void invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); + +}; + +class SoftResetFault : public MipsFault +{ + public: + void invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +class NonMaskableInterrupt : public MipsFault +{ + public: + void invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr); +}; + +class CoprocessorUnusableFault : public MipsFault +{ + protected: + int coProcID; + public: + CoprocessorUnusableFault(int _procid) : coProcID(_procid) + {} + + void + invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr) + { + MipsFault::invoke(tc, inst); + if (FULL_SYSTEM) { + CauseReg cause = tc->readMiscReg(MISCREG_CAUSE); + cause.ce = coProcID; + tc->setMiscReg(MISCREG_CAUSE, cause); + } + } +}; + +class InterruptFault : public MipsFault +{ + public: + FaultVect + offset(ThreadContext *tc) const + { + CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE); + return cause.iv ? 0x200 : 0x000; + } }; template @@ -80,6 +196,30 @@ class AddressFault : public MipsFault AddressFault(Addr _vaddr, bool _store) : vaddr(_vaddr), store(_store) {} + + void + invoke(ThreadContext * tc, + StaticInstPtr inst = StaticInst::nullStaticInstPtr) + { + MipsFault::invoke(tc, inst); + if (FULL_SYSTEM) + tc->setMiscRegNoEffect(MISCREG_BADVADDR, vaddr); + } +}; + +class AddressErrorFault : public AddressFault +{ + public: + AddressErrorFault(Addr _vaddr, bool _store) : + AddressFault(_vaddr, _store) + {} + + ExcCode + code() const + { + return store ? ExcCodeAdES : ExcCodeAdEL; + } + }; template @@ -96,7 +236,6 @@ class TlbFault : public AddressFault void setTlbExceptionState(ThreadContext *tc, uint8_t excCode) { - DPRINTF(MipsPRA, "%s encountered.\n", name()); this->setExceptionState(tc, excCode); tc->setMiscRegNoEffect(MISCREG_BADVADDR, this->vaddr); @@ -110,122 +249,25 @@ class TlbFault : public AddressFault context.badVPN2 = this->vpn >> 2; tc->setMiscRegNoEffect(MISCREG_CONTEXT, context); } -}; -class MachineCheckFault : public MipsFault -{ - public: - bool isMachineCheckFault() {return true;} -}; + 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::invoke(tc, inst); + } + } -static inline Fault genMachineCheckFault() -{ - return new MachineCheckFault; -} - -class NonMaskableInterrupt : public MipsFault -{ - public: - bool isNonMaskableInterrupt() {return true;} -}; - -class AddressErrorFault : public AddressFault -{ - public: - AddressErrorFault(Addr _vaddr, bool _store) : - AddressFault(_vaddr, _store) - {} -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif - -}; - -class ResetFault : public MipsFault -{ - public: - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); - -}; - -class SystemCallFault : public MipsFault -{ - public: -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif -}; - -class SoftResetFault : public MipsFault -{ - public: - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -}; - -class CoprocessorUnusableFault : public MipsFault -{ - protected: - int coProcID; - public: - CoprocessorUnusableFault(int _procid) : coProcID(_procid) - {} - - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -}; - -class ReservedInstructionFault : public MipsFault -{ - public: - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -}; - -class ThreadFault : public MipsFault -{ - public: - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -}; - -class IntegerOverflowFault : public MipsFault -{ - public: -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif -}; - -class InterruptFault : public MipsFault -{ - public: -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif -}; - -class TrapFault : public MipsFault -{ - public: -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif -}; - -class BreakpointFault : public MipsFault -{ - public: -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif + ExcCode + code() const + { + return this->store ? ExcCodeTlbS : ExcCodeTlbL; + } }; class TlbRefillFault : public TlbFault @@ -234,10 +276,13 @@ class TlbRefillFault : public TlbFault TlbRefillFault(Addr asid, Addr vaddr, Addr vpn, bool store) : TlbFault(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 @@ -246,10 +291,6 @@ class TlbInvalidFault : public TlbFault TlbInvalidFault(Addr asid, Addr vaddr, Addr vpn, bool store) : TlbFault(asid, vaddr, vpn, store) {} -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif }; class TlbModifiedFault : public TlbFault @@ -258,17 +299,8 @@ class TlbModifiedFault : public TlbFault TlbModifiedFault(Addr asid, Addr vaddr, Addr vpn) : TlbFault(asid, vaddr, vpn, false) {} -#if FULL_SYSTEM - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); -#endif -}; -class DspStateDisabledFault : public MipsFault -{ - public: - void invoke(ThreadContext * tc, - StaticInstPtr inst = StaticInst::nullStaticInstPtr); + ExcCode code() const { return vals.code; } }; } // namespace MipsISA