faults.hh revision 8738:66bf413b0d5b
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * Copyright (c) 2007 MIPS Technologies, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Gabe Black
30 *          Korey Sewell
31 *          Jaidev Patwardhan
32 */
33
34#ifndef __MIPS_FAULTS_HH__
35#define __MIPS_FAULTS_HH__
36
37#include "arch/mips/pra_constants.hh"
38#include "cpu/thread_context.hh"
39#include "debug/MipsPRA.hh"
40#include "sim/faults.hh"
41#include "sim/full_system.hh"
42
43namespace MipsISA
44{
45
46typedef const Addr FaultVect;
47
48enum ExcCode {
49    // A dummy value to use when the code isn't defined or doesn't matter.
50    ExcCodeDummy = 0,
51
52    ExcCodeInt = 0,
53    ExcCodeMod = 1,
54    ExcCodeTlbL = 2,
55    ExcCodeTlbS = 3,
56    ExcCodeAdEL = 4,
57    ExcCodeAdES = 5,
58    ExcCodeIBE = 6,
59    ExcCodeDBE = 7,
60    ExcCodeSys = 8,
61    ExcCodeBp = 9,
62    ExcCodeRI = 10,
63    ExcCodeCpU = 11,
64    ExcCodeOv = 12,
65    ExcCodeTr = 13,
66    ExcCodeC2E = 18,
67    ExcCodeMDMX = 22,
68    ExcCodeWatch = 23,
69    ExcCodeMCheck = 24,
70    ExcCodeThread = 25,
71    ExcCodeCacheErr = 30
72};
73
74class MipsFaultBase : public FaultBase
75{
76  public:
77    struct FaultVals
78    {
79        const FaultName name;
80        const FaultVect offset;
81        const ExcCode code;
82    };
83
84    void setExceptionState(ThreadContext *, uint8_t);
85
86    virtual FaultVect offset(ThreadContext *tc) const = 0;
87    virtual ExcCode code() const = 0;
88    virtual FaultVect base(ThreadContext *tc) const
89    {
90        StatusReg status = tc->readMiscReg(MISCREG_STATUS);
91        if (status.bev)
92            return tc->readMiscReg(MISCREG_EBASE);
93        else
94            return 0xbfc00200;
95    }
96
97    FaultVect
98    vect(ThreadContext *tc) const
99    {
100        return base(tc) + offset(tc);
101    }
102
103    void invoke(ThreadContext * tc,
104            StaticInstPtr inst = StaticInst::nullStaticInstPtr);
105};
106
107template <typename T>
108class MipsFault : public MipsFaultBase
109{
110  protected:
111    static FaultVals vals;
112  public:
113    FaultName name() const { return vals.name; }
114    FaultVect offset(ThreadContext *tc) const { return vals.offset; }
115    ExcCode code() const { return vals.code; }
116};
117
118class SystemCallFault : public MipsFault<SystemCallFault> {};
119class ReservedInstructionFault : public MipsFault<ReservedInstructionFault> {};
120class ThreadFault : public MipsFault<ThreadFault> {};
121class IntegerOverflowFault : public MipsFault<IntegerOverflowFault> {};
122class TrapFault : public MipsFault<TrapFault> {};
123class BreakpointFault : public MipsFault<BreakpointFault> {};
124class DspStateDisabledFault : public MipsFault<DspStateDisabledFault> {};
125
126class MachineCheckFault : public MipsFault<MachineCheckFault>
127{
128  public:
129    bool isMachineCheckFault() { return true; }
130};
131
132class ResetFault : public MipsFault<ResetFault>
133{
134  public:
135    void invoke(ThreadContext * tc,
136            StaticInstPtr inst = StaticInst::nullStaticInstPtr);
137
138};
139
140class SoftResetFault : public MipsFault<SoftResetFault>
141{
142  public:
143    void invoke(ThreadContext * tc,
144            StaticInstPtr inst = StaticInst::nullStaticInstPtr);
145};
146
147class NonMaskableInterrupt : public MipsFault<NonMaskableInterrupt>
148{
149  public:
150    void invoke(ThreadContext * tc,
151            StaticInstPtr inst = StaticInst::nullStaticInstPtr);
152};
153
154class CoprocessorUnusableFault : public MipsFault<CoprocessorUnusableFault>
155{
156  protected:
157    int coProcID;
158  public:
159    CoprocessorUnusableFault(int _procid) : coProcID(_procid)
160    {}
161
162    void
163    invoke(ThreadContext * tc,
164            StaticInstPtr inst = StaticInst::nullStaticInstPtr)
165    {
166        MipsFault<CoprocessorUnusableFault>::invoke(tc, inst);
167        if (FullSystem) {
168            CauseReg cause = tc->readMiscReg(MISCREG_CAUSE);
169            cause.ce = coProcID;
170            tc->setMiscReg(MISCREG_CAUSE, cause);
171        }
172    }
173};
174
175class InterruptFault : public MipsFault<InterruptFault>
176{
177  public:
178    FaultVect
179    offset(ThreadContext *tc) const
180    {
181        CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE);
182        return cause.iv ? 0x200 : 0x000;
183    }
184};
185
186template <typename T>
187class AddressFault : public MipsFault<T>
188{
189  protected:
190    Addr vaddr;
191    bool store;
192
193    AddressFault(Addr _vaddr, bool _store) : vaddr(_vaddr), store(_store)
194    {}
195
196    void
197    invoke(ThreadContext * tc,
198            StaticInstPtr inst = StaticInst::nullStaticInstPtr)
199    {
200        MipsFault<T>::invoke(tc, inst);
201        if (FullSystem)
202            tc->setMiscRegNoEffect(MISCREG_BADVADDR, vaddr);
203    }
204};
205
206class AddressErrorFault : public AddressFault<AddressErrorFault>
207{
208  public:
209    AddressErrorFault(Addr _vaddr, bool _store) :
210        AddressFault<AddressErrorFault>(_vaddr, _store)
211    {}
212
213    ExcCode
214    code() const
215    {
216        return store ? ExcCodeAdES : ExcCodeAdEL;
217    }
218
219};
220
221template <typename T>
222class TlbFault : public AddressFault<T>
223{
224  protected:
225    Addr asid;
226    Addr vpn;
227
228    TlbFault(Addr _asid, Addr _vaddr, Addr _vpn, bool _store) :
229        AddressFault<T>(_vaddr, _store), asid(_asid), vpn(_vpn)
230    {}
231
232    void
233    setTlbExceptionState(ThreadContext *tc, uint8_t excCode)
234    {
235        this->setExceptionState(tc, excCode);
236
237        tc->setMiscRegNoEffect(MISCREG_BADVADDR, this->vaddr);
238        EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
239        entryHi.asid = this->asid;
240        entryHi.vpn2 = this->vpn >> 2;
241        entryHi.vpn2x = this->vpn & 0x3;
242        tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
243
244        ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
245        context.badVPN2 = this->vpn >> 2;
246        tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
247    }
248
249    void
250    invoke(ThreadContext * tc,
251            StaticInstPtr inst = StaticInst::nullStaticInstPtr)
252    {
253        if (FullSystem) {
254            DPRINTF(MipsPRA, "Fault %s encountered.\n", name());
255            tc->pcState(this->vect(tc));
256            setTlbExceptionState(tc, this->code());
257        } else {
258            AddressFault<T>::invoke(tc, inst);
259        }
260    }
261
262    ExcCode
263    code() const
264    {
265        return this->store ? ExcCodeTlbS : ExcCodeTlbL;
266    }
267};
268
269class TlbRefillFault : public TlbFault<TlbRefillFault>
270{
271  public:
272    TlbRefillFault(Addr asid, Addr vaddr, Addr vpn, bool store) :
273        TlbFault<TlbRefillFault>(asid, vaddr, vpn, store)
274    {}
275
276    FaultVect
277    offset(ThreadContext *tc) const
278    {
279        StatusReg status = tc->readMiscReg(MISCREG_STATUS);
280        return status.exl ? 0x180 : 0x000;
281    }
282};
283
284class TlbInvalidFault : public TlbFault<TlbInvalidFault>
285{
286  public:
287    TlbInvalidFault(Addr asid, Addr vaddr, Addr vpn, bool store) :
288        TlbFault<TlbInvalidFault>(asid, vaddr, vpn, store)
289    {}
290};
291
292class TlbModifiedFault : public TlbFault<TlbModifiedFault>
293{
294  public:
295    TlbModifiedFault(Addr asid, Addr vaddr, Addr vpn) :
296        TlbFault<TlbModifiedFault>(asid, vaddr, vpn, false)
297    {}
298
299    ExcCode code() const { return vals.code; }
300};
301
302} // namespace MipsISA
303
304#endif // __MIPS_FAULTS_HH__
305