arch: Make and use endian specific versions of the mem helpers.
[gem5.git] / src / arch / mips / faults.hh
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 #include "sim/full_system.hh"
44
45 namespace MipsISA
46 {
47
48 typedef Addr FaultVect;
49
50 enum ExcCode {
51 // A dummy value to use when the code isn't defined or doesn't matter.
52 ExcCodeDummy = 0,
53
54 ExcCodeInt = 0,
55 ExcCodeMod = 1,
56 ExcCodeTlbL = 2,
57 ExcCodeTlbS = 3,
58 ExcCodeAdEL = 4,
59 ExcCodeAdES = 5,
60 ExcCodeIBE = 6,
61 ExcCodeDBE = 7,
62 ExcCodeSys = 8,
63 ExcCodeBp = 9,
64 ExcCodeRI = 10,
65 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
76 class 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
109 template <typename T>
110 class 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
120 class SystemCallFault : public MipsFault<SystemCallFault> {};
121 class ReservedInstructionFault : public MipsFault<ReservedInstructionFault> {};
122 class ThreadFault : public MipsFault<ThreadFault> {};
123 class IntegerOverflowFault : public MipsFault<IntegerOverflowFault> {};
124 class TrapFault : public MipsFault<TrapFault> {};
125 class BreakpointFault : public MipsFault<BreakpointFault> {};
126 class DspStateDisabledFault : public MipsFault<DspStateDisabledFault> {};
127
128 class MachineCheckFault : public MipsFault<MachineCheckFault>
129 {
130 public:
131 bool isMachineCheckFault() { return true; }
132 };
133
134 class ResetFault : public MipsFault<ResetFault>
135 {
136 public:
137 void invoke(ThreadContext * tc, const StaticInstPtr &inst =
138 StaticInst::nullStaticInstPtr);
139
140 };
141
142 class SoftResetFault : public MipsFault<SoftResetFault>
143 {
144 public:
145 void invoke(ThreadContext * tc, const StaticInstPtr &inst =
146 StaticInst::nullStaticInstPtr);
147 };
148
149 class NonMaskableInterrupt : public MipsFault<NonMaskableInterrupt>
150 {
151 public:
152 void invoke(ThreadContext * tc, const StaticInstPtr &inst =
153 StaticInst::nullStaticInstPtr);
154 };
155
156 class 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
177 class 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
189 template <typename T>
190 class 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
209 class 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
224 template <typename T>
225 class 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
273 class 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
288 class 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
296 class 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 */
310 template<> MipsFaultBase::FaultVals MipsFault<SystemCallFault>::vals;
311 template<> MipsFaultBase::FaultVals MipsFault<ReservedInstructionFault>::vals;
312 template<> MipsFaultBase::FaultVals MipsFault<ThreadFault>::vals;
313 template<> MipsFaultBase::FaultVals MipsFault<IntegerOverflowFault>::vals;
314 template<> MipsFaultBase::FaultVals MipsFault<TrapFault>::vals;
315 template<> MipsFaultBase::FaultVals MipsFault<BreakpointFault>::vals;
316 template<> MipsFaultBase::FaultVals MipsFault<DspStateDisabledFault>::vals;
317 template<> MipsFaultBase::FaultVals MipsFault<MachineCheckFault>::vals;
318 template<> MipsFaultBase::FaultVals MipsFault<ResetFault>::vals;
319 template<> MipsFaultBase::FaultVals MipsFault<SoftResetFault>::vals;
320 template<> MipsFaultBase::FaultVals MipsFault<NonMaskableInterrupt>::vals;
321 template<> MipsFaultBase::FaultVals MipsFault<CoprocessorUnusableFault>::vals;
322 template<> MipsFaultBase::FaultVals MipsFault<InterruptFault>::vals;
323 template<> MipsFaultBase::FaultVals MipsFault<AddressErrorFault>::vals;
324 template<> MipsFaultBase::FaultVals MipsFault<TlbInvalidFault>::vals;
325 template<> MipsFaultBase::FaultVals MipsFault<TlbRefillFault>::vals;
326 template<> MipsFaultBase::FaultVals MipsFault<TlbModifiedFault>::vals;
327
328
329
330 } // namespace MipsISA
331
332 #endif // __MIPS_FAULTS_HH__