faults.hh revision 8578:dee1f3ab92e4
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
42namespace MipsISA
43{
44
45typedef const Addr FaultVect;
46
47enum ExcCode {
48    // A dummy value to use when the code isn't defined or doesn't matter.
49    ExcCodeDummy = 0,
50
51    ExcCodeInt = 0,
52    ExcCodeMod = 1,
53    ExcCodeTlbL = 2,
54    ExcCodeTlbS = 3,
55    ExcCodeAdEL = 4,
56    ExcCodeAdES = 5,
57    ExcCodeIBE = 6,
58    ExcCodeDBE = 7,
59    ExcCodeSys = 8,
60    ExcCodeBp = 9,
61    ExcCodeRI = 10,
62    ExcCodeCpU = 11,
63    ExcCodeOv = 12,
64    ExcCodeTr = 13,
65    ExcCodeC2E = 18,
66    ExcCodeMDMX = 22,
67    ExcCodeWatch = 23,
68    ExcCodeMCheck = 24,
69    ExcCodeThread = 25,
70    ExcCodeCacheErr = 30
71};
72
73class MipsFaultBase : public FaultBase
74{
75  public:
76    struct FaultVals
77    {
78        const FaultName name;
79        const FaultVect offset;
80        const ExcCode code;
81    };
82
83    void setExceptionState(ThreadContext *, uint8_t);
84
85    virtual FaultVect offset(ThreadContext *tc) const = 0;
86    virtual ExcCode code() const = 0;
87    virtual FaultVect base(ThreadContext *tc) const
88    {
89        StatusReg status = tc->readMiscReg(MISCREG_STATUS);
90        if (status.bev)
91            return tc->readMiscReg(MISCREG_EBASE);
92        else
93            return 0xbfc00200;
94    }
95
96    FaultVect
97    vect(ThreadContext *tc) const
98    {
99        return base(tc) + offset(tc);
100    }
101
102    void invoke(ThreadContext * tc,
103            StaticInstPtr inst = StaticInst::nullStaticInstPtr);
104};
105
106template <typename T>
107class MipsFault : public MipsFaultBase
108{
109  protected:
110    static FaultVals vals;
111  public:
112    FaultName name() const { return vals.name; }
113    FaultVect offset(ThreadContext *tc) const { return vals.offset; }
114    ExcCode code() const { return vals.code; }
115};
116
117class SystemCallFault : public MipsFault<SystemCallFault> {};
118class ReservedInstructionFault : public MipsFault<ReservedInstructionFault> {};
119class ThreadFault : public MipsFault<ThreadFault> {};
120class IntegerOverflowFault : public MipsFault<IntegerOverflowFault> {};
121class TrapFault : public MipsFault<TrapFault> {};
122class BreakpointFault : public MipsFault<BreakpointFault> {};
123class DspStateDisabledFault : public MipsFault<DspStateDisabledFault> {};
124
125class MachineCheckFault : public MipsFault<MachineCheckFault>
126{
127  public:
128    bool isMachineCheckFault() { return true; }
129};
130
131static inline Fault genMachineCheckFault()
132{
133    return new MachineCheckFault;
134}
135
136class ResetFault : public MipsFault<ResetFault>
137{
138  public:
139    void invoke(ThreadContext * tc,
140            StaticInstPtr inst = StaticInst::nullStaticInstPtr);
141
142};
143
144class SoftResetFault : public MipsFault<SoftResetFault>
145{
146  public:
147    void invoke(ThreadContext * tc,
148            StaticInstPtr inst = StaticInst::nullStaticInstPtr);
149};
150
151class NonMaskableInterrupt : public MipsFault<NonMaskableInterrupt>
152{
153  public:
154    void invoke(ThreadContext * tc,
155            StaticInstPtr inst = StaticInst::nullStaticInstPtr);
156};
157
158class CoprocessorUnusableFault : public MipsFault<CoprocessorUnusableFault>
159{
160  protected:
161    int coProcID;
162  public:
163    CoprocessorUnusableFault(int _procid) : coProcID(_procid)
164    {}
165
166    void
167    invoke(ThreadContext * tc,
168            StaticInstPtr inst = StaticInst::nullStaticInstPtr)
169    {
170        MipsFault<CoprocessorUnusableFault>::invoke(tc, inst);
171        if (FULL_SYSTEM) {
172            CauseReg cause = tc->readMiscReg(MISCREG_CAUSE);
173            cause.ce = coProcID;
174            tc->setMiscReg(MISCREG_CAUSE, cause);
175        }
176    }
177};
178
179class InterruptFault : public MipsFault<InterruptFault>
180{
181  public:
182    FaultVect
183    offset(ThreadContext *tc) const
184    {
185        CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE);
186        return cause.iv ? 0x200 : 0x000;
187    }
188};
189
190template <typename T>
191class AddressFault : public MipsFault<T>
192{
193  protected:
194    Addr vaddr;
195    bool store;
196
197    AddressFault(Addr _vaddr, bool _store) : vaddr(_vaddr), store(_store)
198    {}
199
200    void
201    invoke(ThreadContext * tc,
202            StaticInstPtr inst = StaticInst::nullStaticInstPtr)
203    {
204        MipsFault<T>::invoke(tc, inst);
205        if (FULL_SYSTEM)
206            tc->setMiscRegNoEffect(MISCREG_BADVADDR, vaddr);
207    }
208};
209
210class AddressErrorFault : public AddressFault<AddressErrorFault>
211{
212  public:
213    AddressErrorFault(Addr _vaddr, bool _store) :
214        AddressFault<AddressErrorFault>(_vaddr, _store)
215    {}
216
217    ExcCode
218    code() const
219    {
220        return store ? ExcCodeAdES : ExcCodeAdEL;
221    }
222
223};
224
225template <typename T>
226class TlbFault : public AddressFault<T>
227{
228  protected:
229    Addr asid;
230    Addr vpn;
231
232    TlbFault(Addr _asid, Addr _vaddr, Addr _vpn, bool _store) :
233        AddressFault<T>(_vaddr, _store), asid(_asid), vpn(_vpn)
234    {}
235
236    void
237    setTlbExceptionState(ThreadContext *tc, uint8_t excCode)
238    {
239        this->setExceptionState(tc, excCode);
240
241        tc->setMiscRegNoEffect(MISCREG_BADVADDR, this->vaddr);
242        EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
243        entryHi.asid = this->asid;
244        entryHi.vpn2 = this->vpn >> 2;
245        entryHi.vpn2x = this->vpn & 0x3;
246        tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
247
248        ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
249        context.badVPN2 = this->vpn >> 2;
250        tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
251    }
252
253    void
254    invoke(ThreadContext * tc,
255            StaticInstPtr inst = StaticInst::nullStaticInstPtr)
256    {
257        if (FULL_SYSTEM) {
258            DPRINTF(MipsPRA, "Fault %s encountered.\n", name());
259            tc->pcState(this->vect(tc));
260            setTlbExceptionState(tc, this->code());
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 vals.code; }
304};
305
306} // namespace MipsISA
307
308#endif // __MIPS_FAULTS_HH__
309