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