faults.cc (8232:b28d06a175be) faults.cc (8566:812d279f7b51)
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#include "arch/mips/faults.hh"
35#include "arch/mips/pra_constants.hh"
36#include "base/trace.hh"
37#include "cpu/base.hh"
38#include "cpu/thread_context.hh"
39#include "debug/MipsPRA.hh"
40
41#if !FULL_SYSTEM
42#include "mem/page_table.hh"
43#include "sim/process.hh"
44#endif
45
46namespace MipsISA
47{
48
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#include "arch/mips/faults.hh"
35#include "arch/mips/pra_constants.hh"
36#include "base/trace.hh"
37#include "cpu/base.hh"
38#include "cpu/thread_context.hh"
39#include "debug/MipsPRA.hh"
40
41#if !FULL_SYSTEM
42#include "mem/page_table.hh"
43#include "sim/process.hh"
44#endif
45
46namespace MipsISA
47{
48
49FaultName MachineCheckFault::_name = "Machine Check";
50FaultVect MachineCheckFault::_vect = 0x0401;
51FaultStat MachineCheckFault::_count;
49typedef MipsFaultBase::FaultVals FaultVals;
52
50
53FaultName AlignmentFault::_name = "Alignment";
54FaultVect AlignmentFault::_vect = 0x0301;
55FaultStat AlignmentFault::_count;
51template <> FaultVals MipsFault<MachineCheckFault>::vals =
52 { "Machine Check", 0x0401 };
56
53
57FaultName ResetFault::_name = "Reset Fault";
54template <> FaultVals MipsFault<AlignmentFault>::vals =
55 { "Alignment", 0x0301 };
56
57template <> FaultVals MipsFault<ResetFault>::vals =
58#if FULL_SYSTEM
58#if FULL_SYSTEM
59FaultVect ResetFault::_vect = 0xBFC00000;
59 { "Reset Fault", 0xBFC00000};
60#else
60#else
61FaultVect ResetFault::_vect = 0x001;
61 { "Reset Fault", 0x001};
62#endif
62#endif
63FaultStat ResetFault::_count;
64
63
65FaultName AddressErrorFault::_name = "Address Error";
66FaultVect AddressErrorFault::_vect = 0x0180;
67FaultStat AddressErrorFault::_count;
64template <> FaultVals MipsFault<AddressErrorFault>::vals =
65 { "Address Error", 0x0180 };
68
66
69FaultName StoreAddressErrorFault::_name = "Store Address Error";
70FaultVect StoreAddressErrorFault::_vect = 0x0180;
71FaultStat StoreAddressErrorFault::_count;
67template <> FaultVals MipsFault<StoreAddressErrorFault>::vals =
68 { "Store Address Error", 0x0180 };
72
69
70template <> FaultVals MipsFault<SystemCallFault>::vals =
71 { "Syscall", 0x0180 };
73
72
74FaultName SystemCallFault::_name = "Syscall";
75FaultVect SystemCallFault::_vect = 0x0180;
76FaultStat SystemCallFault::_count;
73template <> FaultVals MipsFault<CoprocessorUnusableFault>::vals =
74 { "Coprocessor Unusable Fault", 0x180 };
77
75
78FaultName CoprocessorUnusableFault::_name = "Coprocessor Unusable Fault";
79FaultVect CoprocessorUnusableFault::_vect = 0x180;
80FaultStat CoprocessorUnusableFault::_count;
76template <> FaultVals MipsFault<ReservedInstructionFault>::vals =
77 { "Reserved Instruction Fault", 0x0180 };
81
78
82FaultName ReservedInstructionFault::_name = "Reserved Instruction Fault";
83FaultVect ReservedInstructionFault::_vect = 0x0180;
84FaultStat ReservedInstructionFault::_count;
79template <> FaultVals MipsFault<ThreadFault>::vals =
80 { "Thread Fault", 0x00F1 };
85
81
86FaultName ThreadFault::_name = "Thread Fault";
87FaultVect ThreadFault::_vect = 0x00F1;
88FaultStat ThreadFault::_count;
82template <> FaultVals MipsFault<ArithmeticFault>::vals =
83 { "Arithmetic Overflow Exception", 0x180 };
89
84
90FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception";
91FaultVect ArithmeticFault::_vect = 0x180;
92FaultStat ArithmeticFault::_count;
85template <> FaultVals MipsFault<UnimplementedOpcodeFault>::vals =
86 { "opdec", 0x0481 };
93
87
94FaultName UnimplementedOpcodeFault::_name = "opdec";
95FaultVect UnimplementedOpcodeFault::_vect = 0x0481;
96FaultStat UnimplementedOpcodeFault::_count;
88template <> FaultVals MipsFault<InterruptFault>::vals =
89 { "interrupt", 0x0180 };
97
90
98FaultName InterruptFault::_name = "interrupt";
99FaultVect InterruptFault::_vect = 0x0180;
100FaultStat InterruptFault::_count;
91template <> FaultVals MipsFault<TrapFault>::vals =
92 { "Trap", 0x0180 };
101
93
102FaultName TrapFault::_name = "Trap";
103FaultVect TrapFault::_vect = 0x0180;
104FaultStat TrapFault::_count;
94template <> FaultVals MipsFault<BreakpointFault>::vals =
95 { "Breakpoint", 0x0180 };
105
96
106FaultName BreakpointFault::_name = "Breakpoint";
107FaultVect BreakpointFault::_vect = 0x0180;
108FaultStat BreakpointFault::_count;
97template <> FaultVals MipsFault<ItbInvalidFault>::vals =
98 { "Invalid TLB Entry Exception (I-Fetch/LW)", 0x0180 };
109
99
110FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)";
111FaultVect ItbInvalidFault::_vect = 0x0180;
112FaultStat ItbInvalidFault::_count;
100template <> FaultVals MipsFault<ItbPageFault>::vals =
101 { "itbmiss", 0x0181 };
113
102
114FaultName ItbPageFault::_name = "itbmiss";
115FaultVect ItbPageFault::_vect = 0x0181;
116FaultStat ItbPageFault::_count;
103template <> FaultVals MipsFault<ItbMissFault>::vals =
104 { "itbmiss", 0x0181 };
117
105
118FaultName ItbMissFault::_name = "itbmiss";
119FaultVect ItbMissFault::_vect = 0x0181;
120FaultStat ItbMissFault::_count;
106template <> FaultVals MipsFault<ItbAcvFault>::vals =
107 { "iaccvio", 0x0081 };
121
108
122FaultName ItbAcvFault::_name = "iaccvio";
123FaultVect ItbAcvFault::_vect = 0x0081;
124FaultStat ItbAcvFault::_count;
109template <> FaultVals MipsFault<ItbRefillFault>::vals =
110 { "TLB Refill Exception (I-Fetch/LW)", 0x0180 };
125
111
126FaultName ItbRefillFault::_name = "TLB Refill Exception (I-Fetch/LW)";
127FaultVect ItbRefillFault::_vect = 0x0180;
128FaultStat ItbRefillFault::_count;
112template <> FaultVals MipsFault<NDtbMissFault>::vals =
113 { "dtb_miss_single", 0x0201 };
129
114
130FaultName NDtbMissFault::_name = "dtb_miss_single";
131FaultVect NDtbMissFault::_vect = 0x0201;
132FaultStat NDtbMissFault::_count;
115template <> FaultVals MipsFault<PDtbMissFault>::vals =
116 { "dtb_miss_double", 0x0281 };
133
117
134FaultName PDtbMissFault::_name = "dtb_miss_double";
135FaultVect PDtbMissFault::_vect = 0x0281;
136FaultStat PDtbMissFault::_count;
118template <> FaultVals MipsFault<DtbPageFault>::vals =
119 { "dfault", 0x0381 };
137
120
138FaultName DtbPageFault::_name = "dfault";
139FaultVect DtbPageFault::_vect = 0x0381;
140FaultStat DtbPageFault::_count;
121template <> FaultVals MipsFault<DtbAcvFault>::vals =
122 { "dfault", 0x0381 };
141
123
142FaultName DtbAcvFault::_name = "dfault";
143FaultVect DtbAcvFault::_vect = 0x0381;
144FaultStat DtbAcvFault::_count;
124template <> FaultVals MipsFault<DtbInvalidFault>::vals =
125 { "Invalid TLB Entry Exception (Store)", 0x0180 };
145
126
146FaultName DtbInvalidFault::_name = "Invalid TLB Entry Exception (Store)";
147FaultVect DtbInvalidFault::_vect = 0x0180;
148FaultStat DtbInvalidFault::_count;
127template <> FaultVals MipsFault<DtbRefillFault>::vals =
128 { "TLB Refill Exception (Store)", 0x0180 };
149
129
150FaultName DtbRefillFault::_name = "TLB Refill Exception (Store)";
151FaultVect DtbRefillFault::_vect = 0x0180;
152FaultStat DtbRefillFault::_count;
130template <> FaultVals MipsFault<TLBModifiedFault>::vals =
131 { "TLB Modified Exception", 0x0180 };
153
132
154FaultName TLBModifiedFault::_name = "TLB Modified Exception";
155FaultVect TLBModifiedFault::_vect = 0x0180;
156FaultStat TLBModifiedFault::_count;
133template <> FaultVals MipsFault<FloatEnableFault>::vals =
134 { "float_enable_fault", 0x0581 };
157
135
158FaultName FloatEnableFault::_name = "float_enable_fault";
159FaultVect FloatEnableFault::_vect = 0x0581;
160FaultStat FloatEnableFault::_count;
136template <> FaultVals MipsFault<IntegerOverflowFault>::vals =
137 { "Integer Overflow Fault", 0x0501 };
161
138
162FaultName IntegerOverflowFault::_name = "Integer Overflow Fault";
163FaultVect IntegerOverflowFault::_vect = 0x0501;
164FaultStat IntegerOverflowFault::_count;
139template <> FaultVals MipsFault<DspStateDisabledFault>::vals =
140 { "DSP Disabled Fault", 0x001a };
165
141
166FaultName DspStateDisabledFault::_name = "DSP Disabled Fault";
167FaultVect DspStateDisabledFault::_vect = 0x001a;
168FaultStat DspStateDisabledFault::_count;
169
170#if FULL_SYSTEM
171void
142#if FULL_SYSTEM
143void
172MipsFault::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
144MipsFaultBase::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
173{
174 tc->setPC(HandlerBase);
175 tc->setNextPC(HandlerBase + sizeof(MachInst));
176 tc->setNextNPC(HandlerBase + 2 * sizeof(MachInst));
177}
178
179void
145{
146 tc->setPC(HandlerBase);
147 tc->setNextPC(HandlerBase + sizeof(MachInst));
148 tc->setNextNPC(HandlerBase + 2 * sizeof(MachInst));
149}
150
151void
180MipsFault::setExceptionState(ThreadContext *tc, uint8_t excCode)
152MipsFaultBase::setExceptionState(ThreadContext *tc, uint8_t excCode)
181{
182 // modify SRS Ctl - Save CSS, put ESS into CSS
183 StatusReg status = tc->readMiscReg(MISCREG_STATUS);
184 if (status.exl != 1 && status.bev != 1) {
185 // SRS Ctl is modified only if Status_EXL and Status_BEV are not set
186 SRSCtlReg srsCtl = tc->readMiscReg(MISCREG_SRSCTL);
187 srsCtl.pss = srsCtl.css;
188 srsCtl.css = srsCtl.ess;
189 tc->setMiscRegNoEffect(MISCREG_SRSCTL, srsCtl);
190 }
191
192 // set EXL bit (don't care if it is already set!)
193 status.exl = 1;
194 tc->setMiscRegNoEffect(MISCREG_STATUS, status);
195
196 // write EPC
197 // CHECK ME or FIXME or FIX ME or POSSIBLE HACK
198 // Check to see if the exception occurred in the branch delay slot
199 DPRINTF(MipsPRA, "PC: %x, NextPC: %x, NNPC: %x\n",
200 tc->readPC(), tc->readNextPC(), tc->readNextNPC());
201 int bd = 0;
202 if (tc->readPC() + sizeof(MachInst) != tc->readNextPC()) {
203 tc->setMiscRegNoEffect(MISCREG_EPC, tc->readPC() - sizeof(MachInst));
204 // In the branch delay slot? set CAUSE_31
205 bd = 1;
206 } else {
207 tc->setMiscRegNoEffect(MISCREG_EPC, tc->readPC());
208 // In the branch delay slot? reset CAUSE_31
209 bd = 0;
210 }
211
212 // Set Cause_EXCCODE field
213 CauseReg cause = tc->readMiscReg(MISCREG_CAUSE);
214 cause.excCode = excCode;
215 cause.bd = bd;
216 cause.ce = 0;
217 tc->setMiscRegNoEffect(MISCREG_CAUSE, cause);
218}
219
220void
221ArithmeticFault::invoke(ThreadContext *tc, StaticInstPtr inst)
222{
223 DPRINTF(MipsPRA, "%s encountered.\n", name());
224 setExceptionState(tc, 0xC);
225
226 // Set new PC
227 Addr HandlerBase;
228 StatusReg status = tc->readMiscReg(MISCREG_STATUS);
229 // Here, the handler is dependent on BEV, which is not modified by
230 // setExceptionState()
231 if (!status.bev) {
232 // See MIPS ARM Vol 3, Revision 2, Page 38
233 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
234 } else {
235 HandlerBase = 0xBFC00200;
236 }
237 setHandlerPC(HandlerBase, tc);
238}
239
240void
241StoreAddressErrorFault::invoke(ThreadContext *tc, StaticInstPtr inst)
242{
243 DPRINTF(MipsPRA, "%s encountered.\n", name());
244 setExceptionState(tc, 0x5);
245 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
246
247 // Set new PC
248 Addr HandlerBase;
249 // Offset 0x180 - General Exception Vector
250 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
251 setHandlerPC(HandlerBase, tc);
252}
253
254void
255TrapFault::invoke(ThreadContext *tc, StaticInstPtr inst)
256{
257 DPRINTF(MipsPRA, "%s encountered.\n", name());
258 setExceptionState(tc, 0xD);
259
260 // Set new PC
261 Addr HandlerBase;
262 // Offset 0x180 - General Exception Vector
263 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
264 setHandlerPC(HandlerBase, tc);
265}
266
267void
268BreakpointFault::invoke(ThreadContext *tc, StaticInstPtr inst)
269{
270 setExceptionState(tc, 0x9);
271
272 // Set new PC
273 Addr HandlerBase;
274 // Offset 0x180 - General Exception Vector
275 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
276 setHandlerPC(HandlerBase, tc);
277}
278
279void
280DtbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst)
281{
282 DPRINTF(MipsPRA, "%s encountered.\n", name());
283
284 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
285 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
286 entryHi.asid = entryHiAsid;
287 entryHi.vpn2 = entryHiVPN2;
288 entryHi.vpn2x = entryHiVPN2X;
289 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
290
291 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
292 context.badVPN2 = contextBadVPN2;
293 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
294 setExceptionState(tc, 0x3);
295
296
297 // Set new PC
298 Addr HandlerBase;
299 // Offset 0x180 - General Exception Vector
300 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
301 setHandlerPC(HandlerBase, tc);
302}
303
304void
305AddressErrorFault::invoke(ThreadContext *tc, StaticInstPtr inst)
306{
307 DPRINTF(MipsPRA, "%s encountered.\n", name());
308 setExceptionState(tc, 0x4);
309 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
310
311 // Set new PC
312 Addr HandlerBase;
313 // Offset 0x180 - General Exception Vector
314 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
315 setHandlerPC(HandlerBase, tc);
316}
317
318void
319ItbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst)
320{
321 DPRINTF(MipsPRA, "%s encountered.\n", name());
322 setExceptionState(tc, 0x2);
323 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
324 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
325 entryHi.asid = entryHiAsid;
326 entryHi.vpn2 = entryHiVPN2;
327 entryHi.vpn2x = entryHiVPN2X;
328 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
329
330 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
331 context.badVPN2 = contextBadVPN2;
332 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
333
334
335 // Set new PC
336 Addr HandlerBase;
337 // Offset 0x180 - General Exception Vector
338 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
339 setHandlerPC(HandlerBase,tc);
340 DPRINTF(MipsPRA, "Exception Handler At: %x , EPC set to %x\n",
341 HandlerBase, tc->readMiscReg(MISCREG_EPC));
342}
343
344void
345ItbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst)
346{
347 DPRINTF(MipsPRA, "%s encountered (%x).\n", name(), MISCREG_BADVADDR);
348 Addr HandlerBase;
349 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
350 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
351 entryHi.asid = entryHiAsid;
352 entryHi.vpn2 = entryHiVPN2;
353 entryHi.vpn2x = entryHiVPN2X;
354 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
355 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
356 context.badVPN2 = contextBadVPN2;
357 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
358
359 StatusReg status = tc->readMiscReg(MISCREG_STATUS);
360 // Since handler depends on EXL bit, must check EXL bit before setting it!!
361 // See MIPS ARM Vol 3, Revision 2, Page 38
362 if (status.exl == 1) {
363 // Offset 0x180 - General Exception Vector
364 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
365 } else {
366 // Offset 0x000
367 HandlerBase = tc->readMiscReg(MISCREG_EBASE);
368 }
369
370 setExceptionState(tc, 0x2);
371 setHandlerPC(HandlerBase, tc);
372}
373
374void
375DtbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst)
376{
377 // Set new PC
378 DPRINTF(MipsPRA, "%s encountered.\n", name());
379 Addr HandlerBase;
380 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
381 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
382 entryHi.asid = entryHiAsid;
383 entryHi.vpn2 = entryHiVPN2;
384 entryHi.vpn2x = entryHiVPN2X;
385 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
386
387 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
388 context.badVPN2 = contextBadVPN2;
389 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
390
391 StatusReg status = tc->readMiscReg(MISCREG_STATUS);
392 // Since handler depends on EXL bit, must check EXL bit before setting it!!
393 // See MIPS ARM Vol 3, Revision 2, Page 38
394 if (status.exl) {
395 // Offset 0x180 - General Exception Vector
396 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
397 } else {
398 // Offset 0x000
399 HandlerBase = tc->readMiscReg(MISCREG_EBASE);
400 }
401
402 setExceptionState(tc, 0x3);
403
404 setHandlerPC(HandlerBase, tc);
405}
406
407void
408TLBModifiedFault::invoke(ThreadContext *tc, StaticInstPtr inst)
409{
410 DPRINTF(MipsPRA, "%s encountered.\n", name());
411 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
412 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
413 entryHi.asid = entryHiAsid;
414 entryHi.vpn2 = entryHiVPN2;
415 entryHi.vpn2x = entryHiVPN2X;
416 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
417
418 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
419 context.badVPN2 = contextBadVPN2;
420 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
421
422 // Set new PC
423 Addr HandlerBase;
424 // Offset 0x180 - General Exception Vector
425 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
426 setExceptionState(tc, 0x1);
427 setHandlerPC(HandlerBase, tc);
428
429}
430
431void
432SystemCallFault::invoke(ThreadContext *tc, StaticInstPtr inst)
433{
434 DPRINTF(MipsPRA, "%s encountered.\n", name());
435 setExceptionState(tc, 0x8);
436
437 // Set new PC
438 Addr HandlerBase;
439 // Offset 0x180 - General Exception Vector
440 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
441 setHandlerPC(HandlerBase, tc);
442}
443
444void
445InterruptFault::invoke(ThreadContext *tc, StaticInstPtr inst)
446{
447#if FULL_SYSTEM
448 DPRINTF(MipsPRA, "%s encountered.\n", name());
449 setExceptionState(tc, 0x0A);
450 Addr HandlerBase;
451
452 CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE);
453 if (cause.iv) {
454 // Offset 200 for release 2
455 HandlerBase = 0x20 + vect() + tc->readMiscRegNoEffect(MISCREG_EBASE);
456 } else {
457 //Ofset at 180 for release 1
458 HandlerBase = vect() + tc->readMiscRegNoEffect(MISCREG_EBASE);
459 }
460
461 setHandlerPC(HandlerBase, tc);
462#endif
463}
464
465#endif // FULL_SYSTEM
466
467void
468ResetFault::invoke(ThreadContext *tc, StaticInstPtr inst)
469{
470#if FULL_SYSTEM
471 DPRINTF(MipsPRA, "%s encountered.\n", name());
472 /* All reset activity must be invoked from here */
473 tc->setPC(vect());
474 tc->setNextPC(vect() + sizeof(MachInst));
475 tc->setNextNPC(vect() + sizeof(MachInst) + sizeof(MachInst));
476 DPRINTF(MipsPRA, "ResetFault::invoke : PC set to %x", tc->readPC());
477#endif
478
479 // Set Coprocessor 1 (Floating Point) To Usable
480 StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS);
481 status.cu.cu1 = 1;
482 tc->setMiscReg(MISCREG_STATUS, status);
483}
484
485void
486ReservedInstructionFault::invoke(ThreadContext *tc, StaticInstPtr inst)
487{
488#if FULL_SYSTEM
489 DPRINTF(MipsPRA, "%s encountered.\n", name());
490 setExceptionState(tc, 0x0A);
491 Addr HandlerBase;
492 // Offset 0x180 - General Exception Vector
493 HandlerBase = vect() + tc->readMiscRegNoEffect(MISCREG_EBASE);
494 setHandlerPC(HandlerBase, tc);
495#else
496 panic("%s encountered.\n", name());
497#endif
498}
499
500void
501ThreadFault::invoke(ThreadContext *tc, StaticInstPtr inst)
502{
503 DPRINTF(MipsPRA, "%s encountered.\n", name());
504 panic("%s encountered.\n", name());
505}
506
507void
508DspStateDisabledFault::invoke(ThreadContext *tc, StaticInstPtr inst)
509{
510 DPRINTF(MipsPRA, "%s encountered.\n", name());
511 panic("%s encountered.\n", name());
512}
513
514void
515CoprocessorUnusableFault::invoke(ThreadContext *tc, StaticInstPtr inst)
516{
517#if FULL_SYSTEM
518 DPRINTF(MipsPRA, "%s encountered.\n", name());
519 setExceptionState(tc, 0xb);
520 // The ID of the coprocessor causing the exception is stored in
521 // CoprocessorUnusableFault::coProcID
522 CauseReg cause = tc->readMiscReg(MISCREG_CAUSE);
523 cause.ce = coProcID;
524 tc->setMiscRegNoEffect(MISCREG_CAUSE, cause);
525
526 Addr HandlerBase;
527 // Offset 0x180 - General Exception Vector
528 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
529 setHandlerPC(HandlerBase, tc);
530
531#else
532 warn("%s (CP%d) encountered.\n", name(), coProcID);
533#endif
534}
535
536} // namespace MipsISA
537
153{
154 // modify SRS Ctl - Save CSS, put ESS into CSS
155 StatusReg status = tc->readMiscReg(MISCREG_STATUS);
156 if (status.exl != 1 && status.bev != 1) {
157 // SRS Ctl is modified only if Status_EXL and Status_BEV are not set
158 SRSCtlReg srsCtl = tc->readMiscReg(MISCREG_SRSCTL);
159 srsCtl.pss = srsCtl.css;
160 srsCtl.css = srsCtl.ess;
161 tc->setMiscRegNoEffect(MISCREG_SRSCTL, srsCtl);
162 }
163
164 // set EXL bit (don't care if it is already set!)
165 status.exl = 1;
166 tc->setMiscRegNoEffect(MISCREG_STATUS, status);
167
168 // write EPC
169 // CHECK ME or FIXME or FIX ME or POSSIBLE HACK
170 // Check to see if the exception occurred in the branch delay slot
171 DPRINTF(MipsPRA, "PC: %x, NextPC: %x, NNPC: %x\n",
172 tc->readPC(), tc->readNextPC(), tc->readNextNPC());
173 int bd = 0;
174 if (tc->readPC() + sizeof(MachInst) != tc->readNextPC()) {
175 tc->setMiscRegNoEffect(MISCREG_EPC, tc->readPC() - sizeof(MachInst));
176 // In the branch delay slot? set CAUSE_31
177 bd = 1;
178 } else {
179 tc->setMiscRegNoEffect(MISCREG_EPC, tc->readPC());
180 // In the branch delay slot? reset CAUSE_31
181 bd = 0;
182 }
183
184 // Set Cause_EXCCODE field
185 CauseReg cause = tc->readMiscReg(MISCREG_CAUSE);
186 cause.excCode = excCode;
187 cause.bd = bd;
188 cause.ce = 0;
189 tc->setMiscRegNoEffect(MISCREG_CAUSE, cause);
190}
191
192void
193ArithmeticFault::invoke(ThreadContext *tc, StaticInstPtr inst)
194{
195 DPRINTF(MipsPRA, "%s encountered.\n", name());
196 setExceptionState(tc, 0xC);
197
198 // Set new PC
199 Addr HandlerBase;
200 StatusReg status = tc->readMiscReg(MISCREG_STATUS);
201 // Here, the handler is dependent on BEV, which is not modified by
202 // setExceptionState()
203 if (!status.bev) {
204 // See MIPS ARM Vol 3, Revision 2, Page 38
205 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
206 } else {
207 HandlerBase = 0xBFC00200;
208 }
209 setHandlerPC(HandlerBase, tc);
210}
211
212void
213StoreAddressErrorFault::invoke(ThreadContext *tc, StaticInstPtr inst)
214{
215 DPRINTF(MipsPRA, "%s encountered.\n", name());
216 setExceptionState(tc, 0x5);
217 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
218
219 // Set new PC
220 Addr HandlerBase;
221 // Offset 0x180 - General Exception Vector
222 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
223 setHandlerPC(HandlerBase, tc);
224}
225
226void
227TrapFault::invoke(ThreadContext *tc, StaticInstPtr inst)
228{
229 DPRINTF(MipsPRA, "%s encountered.\n", name());
230 setExceptionState(tc, 0xD);
231
232 // Set new PC
233 Addr HandlerBase;
234 // Offset 0x180 - General Exception Vector
235 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
236 setHandlerPC(HandlerBase, tc);
237}
238
239void
240BreakpointFault::invoke(ThreadContext *tc, StaticInstPtr inst)
241{
242 setExceptionState(tc, 0x9);
243
244 // Set new PC
245 Addr HandlerBase;
246 // Offset 0x180 - General Exception Vector
247 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
248 setHandlerPC(HandlerBase, tc);
249}
250
251void
252DtbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst)
253{
254 DPRINTF(MipsPRA, "%s encountered.\n", name());
255
256 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
257 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
258 entryHi.asid = entryHiAsid;
259 entryHi.vpn2 = entryHiVPN2;
260 entryHi.vpn2x = entryHiVPN2X;
261 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
262
263 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
264 context.badVPN2 = contextBadVPN2;
265 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
266 setExceptionState(tc, 0x3);
267
268
269 // Set new PC
270 Addr HandlerBase;
271 // Offset 0x180 - General Exception Vector
272 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
273 setHandlerPC(HandlerBase, tc);
274}
275
276void
277AddressErrorFault::invoke(ThreadContext *tc, StaticInstPtr inst)
278{
279 DPRINTF(MipsPRA, "%s encountered.\n", name());
280 setExceptionState(tc, 0x4);
281 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
282
283 // Set new PC
284 Addr HandlerBase;
285 // Offset 0x180 - General Exception Vector
286 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
287 setHandlerPC(HandlerBase, tc);
288}
289
290void
291ItbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst)
292{
293 DPRINTF(MipsPRA, "%s encountered.\n", name());
294 setExceptionState(tc, 0x2);
295 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
296 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
297 entryHi.asid = entryHiAsid;
298 entryHi.vpn2 = entryHiVPN2;
299 entryHi.vpn2x = entryHiVPN2X;
300 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
301
302 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
303 context.badVPN2 = contextBadVPN2;
304 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
305
306
307 // Set new PC
308 Addr HandlerBase;
309 // Offset 0x180 - General Exception Vector
310 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
311 setHandlerPC(HandlerBase,tc);
312 DPRINTF(MipsPRA, "Exception Handler At: %x , EPC set to %x\n",
313 HandlerBase, tc->readMiscReg(MISCREG_EPC));
314}
315
316void
317ItbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst)
318{
319 DPRINTF(MipsPRA, "%s encountered (%x).\n", name(), MISCREG_BADVADDR);
320 Addr HandlerBase;
321 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
322 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
323 entryHi.asid = entryHiAsid;
324 entryHi.vpn2 = entryHiVPN2;
325 entryHi.vpn2x = entryHiVPN2X;
326 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
327 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
328 context.badVPN2 = contextBadVPN2;
329 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
330
331 StatusReg status = tc->readMiscReg(MISCREG_STATUS);
332 // Since handler depends on EXL bit, must check EXL bit before setting it!!
333 // See MIPS ARM Vol 3, Revision 2, Page 38
334 if (status.exl == 1) {
335 // Offset 0x180 - General Exception Vector
336 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
337 } else {
338 // Offset 0x000
339 HandlerBase = tc->readMiscReg(MISCREG_EBASE);
340 }
341
342 setExceptionState(tc, 0x2);
343 setHandlerPC(HandlerBase, tc);
344}
345
346void
347DtbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst)
348{
349 // Set new PC
350 DPRINTF(MipsPRA, "%s encountered.\n", name());
351 Addr HandlerBase;
352 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
353 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
354 entryHi.asid = entryHiAsid;
355 entryHi.vpn2 = entryHiVPN2;
356 entryHi.vpn2x = entryHiVPN2X;
357 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
358
359 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
360 context.badVPN2 = contextBadVPN2;
361 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
362
363 StatusReg status = tc->readMiscReg(MISCREG_STATUS);
364 // Since handler depends on EXL bit, must check EXL bit before setting it!!
365 // See MIPS ARM Vol 3, Revision 2, Page 38
366 if (status.exl) {
367 // Offset 0x180 - General Exception Vector
368 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
369 } else {
370 // Offset 0x000
371 HandlerBase = tc->readMiscReg(MISCREG_EBASE);
372 }
373
374 setExceptionState(tc, 0x3);
375
376 setHandlerPC(HandlerBase, tc);
377}
378
379void
380TLBModifiedFault::invoke(ThreadContext *tc, StaticInstPtr inst)
381{
382 DPRINTF(MipsPRA, "%s encountered.\n", name());
383 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
384 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
385 entryHi.asid = entryHiAsid;
386 entryHi.vpn2 = entryHiVPN2;
387 entryHi.vpn2x = entryHiVPN2X;
388 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
389
390 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
391 context.badVPN2 = contextBadVPN2;
392 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
393
394 // Set new PC
395 Addr HandlerBase;
396 // Offset 0x180 - General Exception Vector
397 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
398 setExceptionState(tc, 0x1);
399 setHandlerPC(HandlerBase, tc);
400
401}
402
403void
404SystemCallFault::invoke(ThreadContext *tc, StaticInstPtr inst)
405{
406 DPRINTF(MipsPRA, "%s encountered.\n", name());
407 setExceptionState(tc, 0x8);
408
409 // Set new PC
410 Addr HandlerBase;
411 // Offset 0x180 - General Exception Vector
412 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
413 setHandlerPC(HandlerBase, tc);
414}
415
416void
417InterruptFault::invoke(ThreadContext *tc, StaticInstPtr inst)
418{
419#if FULL_SYSTEM
420 DPRINTF(MipsPRA, "%s encountered.\n", name());
421 setExceptionState(tc, 0x0A);
422 Addr HandlerBase;
423
424 CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE);
425 if (cause.iv) {
426 // Offset 200 for release 2
427 HandlerBase = 0x20 + vect() + tc->readMiscRegNoEffect(MISCREG_EBASE);
428 } else {
429 //Ofset at 180 for release 1
430 HandlerBase = vect() + tc->readMiscRegNoEffect(MISCREG_EBASE);
431 }
432
433 setHandlerPC(HandlerBase, tc);
434#endif
435}
436
437#endif // FULL_SYSTEM
438
439void
440ResetFault::invoke(ThreadContext *tc, StaticInstPtr inst)
441{
442#if FULL_SYSTEM
443 DPRINTF(MipsPRA, "%s encountered.\n", name());
444 /* All reset activity must be invoked from here */
445 tc->setPC(vect());
446 tc->setNextPC(vect() + sizeof(MachInst));
447 tc->setNextNPC(vect() + sizeof(MachInst) + sizeof(MachInst));
448 DPRINTF(MipsPRA, "ResetFault::invoke : PC set to %x", tc->readPC());
449#endif
450
451 // Set Coprocessor 1 (Floating Point) To Usable
452 StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS);
453 status.cu.cu1 = 1;
454 tc->setMiscReg(MISCREG_STATUS, status);
455}
456
457void
458ReservedInstructionFault::invoke(ThreadContext *tc, StaticInstPtr inst)
459{
460#if FULL_SYSTEM
461 DPRINTF(MipsPRA, "%s encountered.\n", name());
462 setExceptionState(tc, 0x0A);
463 Addr HandlerBase;
464 // Offset 0x180 - General Exception Vector
465 HandlerBase = vect() + tc->readMiscRegNoEffect(MISCREG_EBASE);
466 setHandlerPC(HandlerBase, tc);
467#else
468 panic("%s encountered.\n", name());
469#endif
470}
471
472void
473ThreadFault::invoke(ThreadContext *tc, StaticInstPtr inst)
474{
475 DPRINTF(MipsPRA, "%s encountered.\n", name());
476 panic("%s encountered.\n", name());
477}
478
479void
480DspStateDisabledFault::invoke(ThreadContext *tc, StaticInstPtr inst)
481{
482 DPRINTF(MipsPRA, "%s encountered.\n", name());
483 panic("%s encountered.\n", name());
484}
485
486void
487CoprocessorUnusableFault::invoke(ThreadContext *tc, StaticInstPtr inst)
488{
489#if FULL_SYSTEM
490 DPRINTF(MipsPRA, "%s encountered.\n", name());
491 setExceptionState(tc, 0xb);
492 // The ID of the coprocessor causing the exception is stored in
493 // CoprocessorUnusableFault::coProcID
494 CauseReg cause = tc->readMiscReg(MISCREG_CAUSE);
495 cause.ce = coProcID;
496 tc->setMiscRegNoEffect(MISCREG_CAUSE, cause);
497
498 Addr HandlerBase;
499 // Offset 0x180 - General Exception Vector
500 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
501 setHandlerPC(HandlerBase, tc);
502
503#else
504 warn("%s (CP%d) encountered.\n", name(), coProcID);
505#endif
506}
507
508} // namespace MipsISA
509