2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * Copyright (c) 2007 MIPS Technologies, Inc.
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.
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.
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"
41 #include "mem/page_table.hh"
42 #include "sim/process.hh"
48 FaultName
MachineCheckFault::_name
= "Machine Check";
49 FaultVect
MachineCheckFault::_vect
= 0x0401;
50 FaultStat
MachineCheckFault::_count
;
52 FaultName
AlignmentFault::_name
= "Alignment";
53 FaultVect
AlignmentFault::_vect
= 0x0301;
54 FaultStat
AlignmentFault::_count
;
56 FaultName
ResetFault::_name
= "Reset Fault";
58 FaultVect
ResetFault::_vect
= 0xBFC00000;
60 FaultVect
ResetFault::_vect
= 0x001;
62 FaultStat
ResetFault::_count
;
64 FaultName
AddressErrorFault::_name
= "Address Error";
65 FaultVect
AddressErrorFault::_vect
= 0x0180;
66 FaultStat
AddressErrorFault::_count
;
68 FaultName
StoreAddressErrorFault::_name
= "Store Address Error";
69 FaultVect
StoreAddressErrorFault::_vect
= 0x0180;
70 FaultStat
StoreAddressErrorFault::_count
;
73 FaultName
SystemCallFault::_name
= "Syscall";
74 FaultVect
SystemCallFault::_vect
= 0x0180;
75 FaultStat
SystemCallFault::_count
;
77 FaultName
CoprocessorUnusableFault::_name
= "Coprocessor Unusable Fault";
78 FaultVect
CoprocessorUnusableFault::_vect
= 0x180;
79 FaultStat
CoprocessorUnusableFault::_count
;
81 FaultName
ReservedInstructionFault::_name
= "Reserved Instruction Fault";
82 FaultVect
ReservedInstructionFault::_vect
= 0x0180;
83 FaultStat
ReservedInstructionFault::_count
;
85 FaultName
ThreadFault::_name
= "Thread Fault";
86 FaultVect
ThreadFault::_vect
= 0x00F1;
87 FaultStat
ThreadFault::_count
;
89 FaultName
ArithmeticFault::_name
= "Arithmetic Overflow Exception";
90 FaultVect
ArithmeticFault::_vect
= 0x180;
91 FaultStat
ArithmeticFault::_count
;
93 FaultName
UnimplementedOpcodeFault::_name
= "opdec";
94 FaultVect
UnimplementedOpcodeFault::_vect
= 0x0481;
95 FaultStat
UnimplementedOpcodeFault::_count
;
97 FaultName
InterruptFault::_name
= "interrupt";
98 FaultVect
InterruptFault::_vect
= 0x0180;
99 FaultStat
InterruptFault::_count
;
101 FaultName
TrapFault::_name
= "Trap";
102 FaultVect
TrapFault::_vect
= 0x0180;
103 FaultStat
TrapFault::_count
;
105 FaultName
BreakpointFault::_name
= "Breakpoint";
106 FaultVect
BreakpointFault::_vect
= 0x0180;
107 FaultStat
BreakpointFault::_count
;
109 FaultName
ItbInvalidFault::_name
= "Invalid TLB Entry Exception (I-Fetch/LW)";
110 FaultVect
ItbInvalidFault::_vect
= 0x0180;
111 FaultStat
ItbInvalidFault::_count
;
113 FaultName
ItbPageFault::_name
= "itbmiss";
114 FaultVect
ItbPageFault::_vect
= 0x0181;
115 FaultStat
ItbPageFault::_count
;
117 FaultName
ItbMissFault::_name
= "itbmiss";
118 FaultVect
ItbMissFault::_vect
= 0x0181;
119 FaultStat
ItbMissFault::_count
;
121 FaultName
ItbAcvFault::_name
= "iaccvio";
122 FaultVect
ItbAcvFault::_vect
= 0x0081;
123 FaultStat
ItbAcvFault::_count
;
125 FaultName
ItbRefillFault::_name
= "TLB Refill Exception (I-Fetch/LW)";
126 FaultVect
ItbRefillFault::_vect
= 0x0180;
127 FaultStat
ItbRefillFault::_count
;
129 FaultName
NDtbMissFault::_name
= "dtb_miss_single";
130 FaultVect
NDtbMissFault::_vect
= 0x0201;
131 FaultStat
NDtbMissFault::_count
;
133 FaultName
PDtbMissFault::_name
= "dtb_miss_double";
134 FaultVect
PDtbMissFault::_vect
= 0x0281;
135 FaultStat
PDtbMissFault::_count
;
137 FaultName
DtbPageFault::_name
= "dfault";
138 FaultVect
DtbPageFault::_vect
= 0x0381;
139 FaultStat
DtbPageFault::_count
;
141 FaultName
DtbAcvFault::_name
= "dfault";
142 FaultVect
DtbAcvFault::_vect
= 0x0381;
143 FaultStat
DtbAcvFault::_count
;
145 FaultName
DtbInvalidFault::_name
= "Invalid TLB Entry Exception (Store)";
146 FaultVect
DtbInvalidFault::_vect
= 0x0180;
147 FaultStat
DtbInvalidFault::_count
;
149 FaultName
DtbRefillFault::_name
= "TLB Refill Exception (Store)";
150 FaultVect
DtbRefillFault::_vect
= 0x0180;
151 FaultStat
DtbRefillFault::_count
;
153 FaultName
TLBModifiedFault::_name
= "TLB Modified Exception";
154 FaultVect
TLBModifiedFault::_vect
= 0x0180;
155 FaultStat
TLBModifiedFault::_count
;
157 FaultName
FloatEnableFault::_name
= "float_enable_fault";
158 FaultVect
FloatEnableFault::_vect
= 0x0581;
159 FaultStat
FloatEnableFault::_count
;
161 FaultName
IntegerOverflowFault::_name
= "Integer Overflow Fault";
162 FaultVect
IntegerOverflowFault::_vect
= 0x0501;
163 FaultStat
IntegerOverflowFault::_count
;
165 FaultName
DspStateDisabledFault::_name
= "DSP Disabled Fault";
166 FaultVect
DspStateDisabledFault::_vect
= 0x001a;
167 FaultStat
DspStateDisabledFault::_count
;
171 MipsFault::setHandlerPC(Addr HandlerBase
, ThreadContext
*tc
)
173 tc
->setPC(HandlerBase
);
174 tc
->setNextPC(HandlerBase
+ sizeof(MachInst
));
175 tc
->setNextNPC(HandlerBase
+ 2 * sizeof(MachInst
));
179 MipsFault::setExceptionState(ThreadContext
*tc
, uint8_t excCode
)
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
);
191 // set EXL bit (don't care if it is already set!)
193 tc
->setMiscRegNoEffect(MISCREG_STATUS
, status
);
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());
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
206 tc
->setMiscRegNoEffect(MISCREG_EPC
, tc
->readPC());
207 // In the branch delay slot? reset CAUSE_31
211 // Set Cause_EXCCODE field
212 CauseReg cause
= tc
->readMiscReg(MISCREG_CAUSE
);
213 cause
.excCode
= excCode
;
216 tc
->setMiscRegNoEffect(MISCREG_CAUSE
, cause
);
220 ArithmeticFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
222 DPRINTF(MipsPRA
, "%s encountered.\n", name());
223 setExceptionState(tc
, 0xC);
227 StatusReg status
= tc
->readMiscReg(MISCREG_STATUS
);
228 // Here, the handler is dependent on BEV, which is not modified by
229 // setExceptionState()
231 // See MIPS ARM Vol 3, Revision 2, Page 38
232 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
234 HandlerBase
= 0xBFC00200;
236 setHandlerPC(HandlerBase
, tc
);
240 StoreAddressErrorFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
242 DPRINTF(MipsPRA
, "%s encountered.\n", name());
243 setExceptionState(tc
, 0x5);
244 tc
->setMiscRegNoEffect(MISCREG_BADVADDR
, badVAddr
);
248 // Offset 0x180 - General Exception Vector
249 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
250 setHandlerPC(HandlerBase
, tc
);
254 TrapFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
256 DPRINTF(MipsPRA
, "%s encountered.\n", name());
257 setExceptionState(tc
, 0xD);
261 // Offset 0x180 - General Exception Vector
262 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
263 setHandlerPC(HandlerBase
, tc
);
267 BreakpointFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
269 setExceptionState(tc
, 0x9);
273 // Offset 0x180 - General Exception Vector
274 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
275 setHandlerPC(HandlerBase
, tc
);
279 DtbInvalidFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
281 DPRINTF(MipsPRA
, "%s encountered.\n", name());
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
);
290 ContextReg context
= tc
->readMiscReg(MISCREG_CONTEXT
);
291 context
.badVPN2
= contextBadVPN2
;
292 tc
->setMiscRegNoEffect(MISCREG_CONTEXT
, context
);
293 setExceptionState(tc
, 0x3);
298 // Offset 0x180 - General Exception Vector
299 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
300 setHandlerPC(HandlerBase
, tc
);
304 AddressErrorFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
306 DPRINTF(MipsPRA
, "%s encountered.\n", name());
307 setExceptionState(tc
, 0x4);
308 tc
->setMiscRegNoEffect(MISCREG_BADVADDR
, badVAddr
);
312 // Offset 0x180 - General Exception Vector
313 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
314 setHandlerPC(HandlerBase
, tc
);
318 ItbInvalidFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
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
);
329 ContextReg context
= tc
->readMiscReg(MISCREG_CONTEXT
);
330 context
.badVPN2
= contextBadVPN2
;
331 tc
->setMiscRegNoEffect(MISCREG_CONTEXT
, context
);
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
));
344 ItbRefillFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
346 DPRINTF(MipsPRA
, "%s encountered (%x).\n", name(), MISCREG_BADVADDR
);
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
);
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
);
366 HandlerBase
= tc
->readMiscReg(MISCREG_EBASE
);
369 setExceptionState(tc
, 0x2);
370 setHandlerPC(HandlerBase
, tc
);
374 DtbRefillFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
377 DPRINTF(MipsPRA
, "%s encountered.\n", name());
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
);
386 ContextReg context
= tc
->readMiscReg(MISCREG_CONTEXT
);
387 context
.badVPN2
= contextBadVPN2
;
388 tc
->setMiscRegNoEffect(MISCREG_CONTEXT
, context
);
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
394 // Offset 0x180 - General Exception Vector
395 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
398 HandlerBase
= tc
->readMiscReg(MISCREG_EBASE
);
401 setExceptionState(tc
, 0x3);
403 setHandlerPC(HandlerBase
, tc
);
407 TLBModifiedFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
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
);
417 ContextReg context
= tc
->readMiscReg(MISCREG_CONTEXT
);
418 context
.badVPN2
= contextBadVPN2
;
419 tc
->setMiscRegNoEffect(MISCREG_CONTEXT
, context
);
423 // Offset 0x180 - General Exception Vector
424 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
425 setExceptionState(tc
, 0x1);
426 setHandlerPC(HandlerBase
, tc
);
431 SystemCallFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
433 DPRINTF(MipsPRA
, "%s encountered.\n", name());
434 setExceptionState(tc
, 0x8);
438 // Offset 0x180 - General Exception Vector
439 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
440 setHandlerPC(HandlerBase
, tc
);
444 InterruptFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
447 DPRINTF(MipsPRA
, "%s encountered.\n", name());
448 setExceptionState(tc
, 0x0A);
451 CauseReg cause
= tc
->readMiscRegNoEffect(MISCREG_CAUSE
);
453 // Offset 200 for release 2
454 HandlerBase
= 0x20 + vect() + tc
->readMiscRegNoEffect(MISCREG_EBASE
);
456 //Ofset at 180 for release 1
457 HandlerBase
= vect() + tc
->readMiscRegNoEffect(MISCREG_EBASE
);
460 setHandlerPC(HandlerBase
, tc
);
464 #endif // FULL_SYSTEM
467 ResetFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
470 DPRINTF(MipsPRA
, "%s encountered.\n", name());
471 /* All reset activity must be invoked from here */
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());
478 // Set Coprocessor 1 (Floating Point) To Usable
479 StatusReg status
= tc
->readMiscRegNoEffect(MISCREG_STATUS
);
481 tc
->setMiscReg(MISCREG_STATUS
, status
);
485 ReservedInstructionFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
488 DPRINTF(MipsPRA
, "%s encountered.\n", name());
489 setExceptionState(tc
, 0x0A);
491 // Offset 0x180 - General Exception Vector
492 HandlerBase
= vect() + tc
->readMiscRegNoEffect(MISCREG_EBASE
);
493 setHandlerPC(HandlerBase
, tc
);
495 panic("%s encountered.\n", name());
500 ThreadFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
502 DPRINTF(MipsPRA
, "%s encountered.\n", name());
503 panic("%s encountered.\n", name());
507 DspStateDisabledFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
509 DPRINTF(MipsPRA
, "%s encountered.\n", name());
510 panic("%s encountered.\n", name());
514 CoprocessorUnusableFault::invoke(ThreadContext
*tc
, StaticInstPtr inst
)
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
);
523 tc
->setMiscRegNoEffect(MISCREG_CAUSE
, cause
);
526 // Offset 0x180 - General Exception Vector
527 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
528 setHandlerPC(HandlerBase
, tc
);
531 warn("%s (CP%d) encountered.\n", name(), coProcID
);
535 } // namespace MipsISA