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