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