faults.hh revision 12176
112855Sgabeblack@google.com/*
212855Sgabeblack@google.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
312855Sgabeblack@google.com * Copyright (c) 2007 MIPS Technologies, Inc.
412855Sgabeblack@google.com * All rights reserved.
512855Sgabeblack@google.com *
612855Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
712855Sgabeblack@google.com * modification, are permitted provided that the following conditions are
812855Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
912855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
1012855Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1112855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1212855Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1312855Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1412855Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1512855Sgabeblack@google.com * this software without specific prior written permission.
1612855Sgabeblack@google.com *
1712855Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1812855Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1912855Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2012855Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2112855Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2212855Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2312855Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2412855Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2512855Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2612855Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2712855Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2812855Sgabeblack@google.com *
2912855Sgabeblack@google.com * Authors: Gabe Black
3012855Sgabeblack@google.com *          Korey Sewell
3112855Sgabeblack@google.com *          Jaidev Patwardhan
3212855Sgabeblack@google.com *          Zhengxing Li
3312855Sgabeblack@google.com *          Deyuan Guo
3412855Sgabeblack@google.com */
3512855Sgabeblack@google.com
3612855Sgabeblack@google.com#ifndef __MIPS_FAULTS_HH__
3712855Sgabeblack@google.com#define __MIPS_FAULTS_HH__
3812855Sgabeblack@google.com
3912855Sgabeblack@google.com#include "arch/mips/pra_constants.hh"
4012855Sgabeblack@google.com#include "cpu/thread_context.hh"
4112855Sgabeblack@google.com#include "debug/MipsPRA.hh"
4212855Sgabeblack@google.com#include "sim/faults.hh"
4312855Sgabeblack@google.com#include "sim/full_system.hh"
4412855Sgabeblack@google.com
4512855Sgabeblack@google.comnamespace MipsISA
4612855Sgabeblack@google.com{
4712855Sgabeblack@google.com
4812855Sgabeblack@google.comtypedef Addr FaultVect;
4912855Sgabeblack@google.com
5012855Sgabeblack@google.comenum ExcCode {
5112855Sgabeblack@google.com    // A dummy value to use when the code isn't defined or doesn't matter.
5212855Sgabeblack@google.com    ExcCodeDummy = 0,
5312855Sgabeblack@google.com
5412855Sgabeblack@google.com    ExcCodeInt = 0,
5512855Sgabeblack@google.com    ExcCodeMod = 1,
5612855Sgabeblack@google.com    ExcCodeTlbL = 2,
5712855Sgabeblack@google.com    ExcCodeTlbS = 3,
5812855Sgabeblack@google.com    ExcCodeAdEL = 4,
5912855Sgabeblack@google.com    ExcCodeAdES = 5,
6012855Sgabeblack@google.com    ExcCodeIBE = 6,
6112855Sgabeblack@google.com    ExcCodeDBE = 7,
6212855Sgabeblack@google.com    ExcCodeSys = 8,
6312855Sgabeblack@google.com    ExcCodeBp = 9,
6412855Sgabeblack@google.com    ExcCodeRI = 10,
6512855Sgabeblack@google.com    ExcCodeCpU = 11,
66    ExcCodeOv = 12,
67    ExcCodeTr = 13,
68    ExcCodeC2E = 18,
69    ExcCodeMDMX = 22,
70    ExcCodeWatch = 23,
71    ExcCodeMCheck = 24,
72    ExcCodeThread = 25,
73    ExcCodeCacheErr = 30
74};
75
76class MipsFaultBase : public FaultBase
77{
78  public:
79    struct FaultVals
80    {
81        const FaultName name;
82        const FaultVect offset;
83        const ExcCode code;
84    };
85
86    void setExceptionState(ThreadContext *, uint8_t);
87
88    virtual FaultVect offset(ThreadContext *tc) const = 0;
89    virtual ExcCode code() const = 0;
90    virtual FaultVect base(ThreadContext *tc) const
91    {
92        StatusReg status = tc->readMiscReg(MISCREG_STATUS);
93        if (!status.bev)
94            return tc->readMiscReg(MISCREG_EBASE);
95        else
96            return 0xbfc00200;
97    }
98
99    FaultVect
100    vect(ThreadContext *tc) const
101    {
102        return base(tc) + offset(tc);
103    }
104
105    void invoke(ThreadContext * tc, const StaticInstPtr &inst =
106                StaticInst::nullStaticInstPtr);
107};
108
109template <typename T>
110class MipsFault : public MipsFaultBase
111{
112  protected:
113    static FaultVals vals;
114  public:
115    FaultName name() const { return vals.name; }
116    FaultVect offset(ThreadContext *tc) const { return vals.offset; }
117    ExcCode code() const { return vals.code; }
118};
119
120class SystemCallFault : public MipsFault<SystemCallFault> {};
121class ReservedInstructionFault : public MipsFault<ReservedInstructionFault> {};
122class ThreadFault : public MipsFault<ThreadFault> {};
123class IntegerOverflowFault : public MipsFault<IntegerOverflowFault> {};
124class TrapFault : public MipsFault<TrapFault> {};
125class BreakpointFault : public MipsFault<BreakpointFault> {};
126class DspStateDisabledFault : public MipsFault<DspStateDisabledFault> {};
127
128class MachineCheckFault : public MipsFault<MachineCheckFault>
129{
130  public:
131    bool isMachineCheckFault() { return true; }
132};
133
134class ResetFault : public MipsFault<ResetFault>
135{
136  public:
137    void invoke(ThreadContext * tc, const StaticInstPtr &inst =
138                StaticInst::nullStaticInstPtr);
139
140};
141
142class SoftResetFault : public MipsFault<SoftResetFault>
143{
144  public:
145    void invoke(ThreadContext * tc, const StaticInstPtr &inst =
146                StaticInst::nullStaticInstPtr);
147};
148
149class NonMaskableInterrupt : public MipsFault<NonMaskableInterrupt>
150{
151  public:
152    void invoke(ThreadContext * tc, const StaticInstPtr &inst =
153                StaticInst::nullStaticInstPtr);
154};
155
156class CoprocessorUnusableFault : public MipsFault<CoprocessorUnusableFault>
157{
158  protected:
159    int coProcID;
160  public:
161    CoprocessorUnusableFault(int _procid) : coProcID(_procid)
162    {}
163
164    void
165    invoke(ThreadContext * tc, const StaticInstPtr &inst =
166           StaticInst::nullStaticInstPtr)
167    {
168        MipsFault<CoprocessorUnusableFault>::invoke(tc, inst);
169        if (FullSystem) {
170            CauseReg cause = tc->readMiscReg(MISCREG_CAUSE);
171            cause.ce = coProcID;
172            tc->setMiscRegNoEffect(MISCREG_CAUSE, cause);
173        }
174    }
175};
176
177class InterruptFault : public MipsFault<InterruptFault>
178{
179  public:
180    FaultVect
181    offset(ThreadContext *tc) const
182    {
183        CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE);
184        // offset 0x200 for release 2, 0x180 for release 1.
185        return cause.iv ? 0x200 : 0x180;
186    }
187};
188
189template <typename T>
190class AddressFault : public MipsFault<T>
191{
192  protected:
193    Addr vaddr;
194    bool store;
195
196    AddressFault(Addr _vaddr, bool _store) : vaddr(_vaddr), store(_store)
197    {}
198
199    void
200    invoke(ThreadContext * tc, const StaticInstPtr &inst =
201           StaticInst::nullStaticInstPtr)
202    {
203        MipsFault<T>::invoke(tc, inst);
204        if (FullSystem)
205            tc->setMiscRegNoEffect(MISCREG_BADVADDR, vaddr);
206    }
207};
208
209class AddressErrorFault : public AddressFault<AddressErrorFault>
210{
211  public:
212    AddressErrorFault(Addr _vaddr, bool _store) :
213        AddressFault<AddressErrorFault>(_vaddr, _store)
214    {}
215
216    ExcCode
217    code() const
218    {
219        return store ? ExcCodeAdES : ExcCodeAdEL;
220    }
221
222};
223
224template <typename T>
225class TlbFault : public AddressFault<T>
226{
227  protected:
228    Addr asid;
229    Addr vpn;
230
231    TlbFault(Addr _asid, Addr _vaddr, Addr _vpn, bool _store) :
232        AddressFault<T>(_vaddr, _store), asid(_asid), vpn(_vpn)
233    {}
234
235    void
236    setTlbExceptionState(ThreadContext *tc, uint8_t excCode)
237    {
238        this->setExceptionState(tc, excCode);
239
240        tc->setMiscRegNoEffect(MISCREG_BADVADDR, this->vaddr);
241        EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
242        entryHi.asid = this->asid;
243        entryHi.vpn2 = this->vpn >> 2;
244        entryHi.vpn2x = this->vpn & 0x3;
245        tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
246
247        ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
248        context.badVPN2 = this->vpn >> 2;
249        tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
250    }
251
252    void
253    invoke(ThreadContext * tc, const StaticInstPtr &inst =
254           StaticInst::nullStaticInstPtr)
255    {
256        if (FullSystem) {
257            DPRINTF(MipsPRA, "Fault %s encountered.\n", this->name());
258            Addr vect = this->vect(tc);
259            setTlbExceptionState(tc, this->code());
260            tc->pcState(vect);
261        } else {
262            AddressFault<T>::invoke(tc, inst);
263        }
264    }
265
266    ExcCode
267    code() const
268    {
269        return this->store ? ExcCodeTlbS : ExcCodeTlbL;
270    }
271};
272
273class TlbRefillFault : public TlbFault<TlbRefillFault>
274{
275  public:
276    TlbRefillFault(Addr asid, Addr vaddr, Addr vpn, bool store) :
277        TlbFault<TlbRefillFault>(asid, vaddr, vpn, store)
278    {}
279
280    FaultVect
281    offset(ThreadContext *tc) const
282    {
283        StatusReg status = tc->readMiscReg(MISCREG_STATUS);
284        return status.exl ? 0x180 : 0x000;
285    }
286};
287
288class TlbInvalidFault : public TlbFault<TlbInvalidFault>
289{
290  public:
291    TlbInvalidFault(Addr asid, Addr vaddr, Addr vpn, bool store) :
292        TlbFault<TlbInvalidFault>(asid, vaddr, vpn, store)
293    {}
294};
295
296class TlbModifiedFault : public TlbFault<TlbModifiedFault>
297{
298  public:
299    TlbModifiedFault(Addr asid, Addr vaddr, Addr vpn) :
300        TlbFault<TlbModifiedFault>(asid, vaddr, vpn, false)
301    {}
302
303    ExcCode code() const { return MipsFault<TlbModifiedFault>::code(); }
304};
305
306/*
307 * Explicitly declare template static member variables to avoid warnings
308 * in some clang versions
309 */
310template<> MipsFaultBase::FaultVals MipsFault<SystemCallFault>::vals;
311template<> MipsFaultBase::FaultVals MipsFault<ReservedInstructionFault>::vals;
312template<> MipsFaultBase::FaultVals MipsFault<ThreadFault>::vals;
313template<> MipsFaultBase::FaultVals MipsFault<IntegerOverflowFault>::vals;
314template<> MipsFaultBase::FaultVals MipsFault<TrapFault>::vals;
315template<> MipsFaultBase::FaultVals MipsFault<BreakpointFault>::vals;
316template<> MipsFaultBase::FaultVals MipsFault<DspStateDisabledFault>::vals;
317template<> MipsFaultBase::FaultVals MipsFault<MachineCheckFault>::vals;
318template<> MipsFaultBase::FaultVals MipsFault<ResetFault>::vals;
319template<> MipsFaultBase::FaultVals MipsFault<SoftResetFault>::vals;
320template<> MipsFaultBase::FaultVals MipsFault<NonMaskableInterrupt>::vals;
321template<> MipsFaultBase::FaultVals MipsFault<CoprocessorUnusableFault>::vals;
322template<> MipsFaultBase::FaultVals MipsFault<InterruptFault>::vals;
323template<> MipsFaultBase::FaultVals MipsFault<AddressErrorFault>::vals;
324template<> MipsFaultBase::FaultVals MipsFault<TlbInvalidFault>::vals;
325template<> MipsFaultBase::FaultVals MipsFault<TlbRefillFault>::vals;
326template<> MipsFaultBase::FaultVals MipsFault<TlbModifiedFault>::vals;
327
328
329
330} // namespace MipsISA
331
332#endif // __MIPS_FAULTS_HH__
333