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 "cpu/thread_context.hh"
36 #include "cpu/base.hh"
37 #include "base/trace.hh"
38 #include "arch/mips/pra_constants.hh"
40 #include "sim/process.hh"
41 #include "mem/page_table.hh"
47 FaultName
MachineCheckFault::_name
= "Machine Check";
48 FaultVect
MachineCheckFault::_vect
= 0x0401;
49 FaultStat
MachineCheckFault::_count
;
51 FaultName
AlignmentFault::_name
= "Alignment";
52 FaultVect
AlignmentFault::_vect
= 0x0301;
53 FaultStat
AlignmentFault::_count
;
55 FaultName
ResetFault::_name
= "Reset Fault";
57 FaultVect
ResetFault::_vect
= 0xBFC00000;
59 FaultVect
ResetFault::_vect
= 0x001;
61 FaultStat
ResetFault::_count
;
63 FaultName
AddressErrorFault::_name
= "Address Error";
64 FaultVect
AddressErrorFault::_vect
= 0x0180;
65 FaultStat
AddressErrorFault::_count
;
67 FaultName
StoreAddressErrorFault::_name
= "Store Address Error";
68 FaultVect
StoreAddressErrorFault::_vect
= 0x0180;
69 FaultStat
StoreAddressErrorFault::_count
;
72 FaultName
SystemCallFault::_name
= "Syscall";
73 FaultVect
SystemCallFault::_vect
= 0x0180;
74 FaultStat
SystemCallFault::_count
;
76 FaultName
CoprocessorUnusableFault::_name
= "Coprocessor Unusable Fault";
77 FaultVect
CoprocessorUnusableFault::_vect
= 0x180;
78 FaultStat
CoprocessorUnusableFault::_count
;
80 FaultName
ReservedInstructionFault::_name
= "Reserved Instruction Fault";
81 FaultVect
ReservedInstructionFault::_vect
= 0x0180;
82 FaultStat
ReservedInstructionFault::_count
;
84 FaultName
ThreadFault::_name
= "Thread Fault";
85 FaultVect
ThreadFault::_vect
= 0x00F1;
86 FaultStat
ThreadFault::_count
;
88 FaultName
ArithmeticFault::_name
= "Arithmetic Overflow Exception";
89 FaultVect
ArithmeticFault::_vect
= 0x180;
90 FaultStat
ArithmeticFault::_count
;
92 FaultName
UnimplementedOpcodeFault::_name
= "opdec";
93 FaultVect
UnimplementedOpcodeFault::_vect
= 0x0481;
94 FaultStat
UnimplementedOpcodeFault::_count
;
96 FaultName
InterruptFault::_name
= "interrupt";
97 FaultVect
InterruptFault::_vect
= 0x0180;
98 FaultStat
InterruptFault::_count
;
100 FaultName
TrapFault::_name
= "Trap";
101 FaultVect
TrapFault::_vect
= 0x0180;
102 FaultStat
TrapFault::_count
;
104 FaultName
BreakpointFault::_name
= "Breakpoint";
105 FaultVect
BreakpointFault::_vect
= 0x0180;
106 FaultStat
BreakpointFault::_count
;
108 FaultName
ItbInvalidFault::_name
= "Invalid TLB Entry Exception (I-Fetch/LW)";
109 FaultVect
ItbInvalidFault::_vect
= 0x0180;
110 FaultStat
ItbInvalidFault::_count
;
112 FaultName
ItbPageFault::_name
= "itbmiss";
113 FaultVect
ItbPageFault::_vect
= 0x0181;
114 FaultStat
ItbPageFault::_count
;
116 FaultName
ItbMissFault::_name
= "itbmiss";
117 FaultVect
ItbMissFault::_vect
= 0x0181;
118 FaultStat
ItbMissFault::_count
;
120 FaultName
ItbAcvFault::_name
= "iaccvio";
121 FaultVect
ItbAcvFault::_vect
= 0x0081;
122 FaultStat
ItbAcvFault::_count
;
124 FaultName
ItbRefillFault::_name
= "TLB Refill Exception (I-Fetch/LW)";
125 FaultVect
ItbRefillFault::_vect
= 0x0180;
126 FaultStat
ItbRefillFault::_count
;
128 FaultName
NDtbMissFault::_name
= "dtb_miss_single";
129 FaultVect
NDtbMissFault::_vect
= 0x0201;
130 FaultStat
NDtbMissFault::_count
;
132 FaultName
PDtbMissFault::_name
= "dtb_miss_double";
133 FaultVect
PDtbMissFault::_vect
= 0x0281;
134 FaultStat
PDtbMissFault::_count
;
136 FaultName
DtbPageFault::_name
= "dfault";
137 FaultVect
DtbPageFault::_vect
= 0x0381;
138 FaultStat
DtbPageFault::_count
;
140 FaultName
DtbAcvFault::_name
= "dfault";
141 FaultVect
DtbAcvFault::_vect
= 0x0381;
142 FaultStat
DtbAcvFault::_count
;
144 FaultName
DtbInvalidFault::_name
= "Invalid TLB Entry Exception (Store)";
145 FaultVect
DtbInvalidFault::_vect
= 0x0180;
146 FaultStat
DtbInvalidFault::_count
;
148 FaultName
DtbRefillFault::_name
= "TLB Refill Exception (Store)";
149 FaultVect
DtbRefillFault::_vect
= 0x0180;
150 FaultStat
DtbRefillFault::_count
;
152 FaultName
TLBModifiedFault::_name
= "TLB Modified Exception";
153 FaultVect
TLBModifiedFault::_vect
= 0x0180;
154 FaultStat
TLBModifiedFault::_count
;
156 FaultName
FloatEnableFault::_name
= "float_enable_fault";
157 FaultVect
FloatEnableFault::_vect
= 0x0581;
158 FaultStat
FloatEnableFault::_count
;
160 FaultName
IntegerOverflowFault::_name
= "Integer Overflow Fault";
161 FaultVect
IntegerOverflowFault::_vect
= 0x0501;
162 FaultStat
IntegerOverflowFault::_count
;
164 FaultName
DspStateDisabledFault::_name
= "DSP Disabled Fault";
165 FaultVect
DspStateDisabledFault::_vect
= 0x001a;
166 FaultStat
DspStateDisabledFault::_count
;
170 MipsFault::setHandlerPC(Addr HandlerBase
, ThreadContext
*tc
)
172 tc
->setPC(HandlerBase
);
173 tc
->setNextPC(HandlerBase
+ sizeof(MachInst
));
174 tc
->setNextNPC(HandlerBase
+ 2 * sizeof(MachInst
));
178 MipsFault::setExceptionState(ThreadContext
*tc
, uint8_t excCode
)
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
);
190 // set EXL bit (don't care if it is already set!)
192 tc
->setMiscRegNoEffect(MISCREG_STATUS
, status
);
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());
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
205 tc
->setMiscRegNoEffect(MISCREG_EPC
, tc
->readPC());
206 // In the branch delay slot? reset CAUSE_31
210 // Set Cause_EXCCODE field
211 CauseReg cause
= tc
->readMiscReg(MISCREG_CAUSE
);
212 cause
.excCode
= excCode
;
215 tc
->setMiscRegNoEffect(MISCREG_CAUSE
, cause
);
219 ArithmeticFault::invoke(ThreadContext
*tc
)
221 DPRINTF(MipsPRA
, "%s encountered.\n", name());
222 setExceptionState(tc
, 0xC);
226 StatusReg status
= tc
->readMiscReg(MISCREG_STATUS
);
227 // Here, the handler is dependent on BEV, which is not modified by
228 // setExceptionState()
230 // See MIPS ARM Vol 3, Revision 2, Page 38
231 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
233 HandlerBase
= 0xBFC00200;
235 setHandlerPC(HandlerBase
, tc
);
239 StoreAddressErrorFault::invoke(ThreadContext
*tc
)
241 DPRINTF(MipsPRA
, "%s encountered.\n", name());
242 setExceptionState(tc
, 0x5);
243 tc
->setMiscRegNoEffect(MISCREG_BADVADDR
, badVAddr
);
247 // Offset 0x180 - General Exception Vector
248 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
249 setHandlerPC(HandlerBase
, tc
);
253 TrapFault::invoke(ThreadContext
*tc
)
255 DPRINTF(MipsPRA
, "%s encountered.\n", name());
256 setExceptionState(tc
, 0xD);
260 // Offset 0x180 - General Exception Vector
261 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
262 setHandlerPC(HandlerBase
, tc
);
266 BreakpointFault::invoke(ThreadContext
*tc
)
268 setExceptionState(tc
, 0x9);
272 // Offset 0x180 - General Exception Vector
273 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
274 setHandlerPC(HandlerBase
, tc
);
278 DtbInvalidFault::invoke(ThreadContext
*tc
)
280 DPRINTF(MipsPRA
, "%s encountered.\n", name());
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
);
289 ContextReg context
= tc
->readMiscReg(MISCREG_CONTEXT
);
290 context
.badVPN2
= contextBadVPN2
;
291 tc
->setMiscRegNoEffect(MISCREG_CONTEXT
, context
);
292 setExceptionState(tc
, 0x3);
297 // Offset 0x180 - General Exception Vector
298 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
299 setHandlerPC(HandlerBase
, tc
);
303 AddressErrorFault::invoke(ThreadContext
*tc
)
305 DPRINTF(MipsPRA
, "%s encountered.\n", name());
306 setExceptionState(tc
, 0x4);
307 tc
->setMiscRegNoEffect(MISCREG_BADVADDR
, badVAddr
);
311 // Offset 0x180 - General Exception Vector
312 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
313 setHandlerPC(HandlerBase
, tc
);
317 ItbInvalidFault::invoke(ThreadContext
*tc
)
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
);
328 ContextReg context
= tc
->readMiscReg(MISCREG_CONTEXT
);
329 context
.badVPN2
= contextBadVPN2
;
330 tc
->setMiscRegNoEffect(MISCREG_CONTEXT
, context
);
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
));
343 ItbRefillFault::invoke(ThreadContext
*tc
)
345 DPRINTF(MipsPRA
, "%s encountered (%x).\n", name(), MISCREG_BADVADDR
);
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
);
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
);
365 HandlerBase
= tc
->readMiscReg(MISCREG_EBASE
);
368 setExceptionState(tc
, 0x2);
369 setHandlerPC(HandlerBase
, tc
);
373 DtbRefillFault::invoke(ThreadContext
*tc
)
376 DPRINTF(MipsPRA
, "%s encountered.\n", name());
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
);
385 ContextReg context
= tc
->readMiscReg(MISCREG_CONTEXT
);
386 context
.badVPN2
= contextBadVPN2
;
387 tc
->setMiscRegNoEffect(MISCREG_CONTEXT
, context
);
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
393 // Offset 0x180 - General Exception Vector
394 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
397 HandlerBase
= tc
->readMiscReg(MISCREG_EBASE
);
400 setExceptionState(tc
, 0x3);
402 setHandlerPC(HandlerBase
, tc
);
406 TLBModifiedFault::invoke(ThreadContext
*tc
)
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
);
416 ContextReg context
= tc
->readMiscReg(MISCREG_CONTEXT
);
417 context
.badVPN2
= contextBadVPN2
;
418 tc
->setMiscRegNoEffect(MISCREG_CONTEXT
, context
);
422 // Offset 0x180 - General Exception Vector
423 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
424 setExceptionState(tc
, 0x1);
425 setHandlerPC(HandlerBase
, tc
);
430 SystemCallFault::invoke(ThreadContext
*tc
)
432 DPRINTF(MipsPRA
, "%s encountered.\n", name());
433 setExceptionState(tc
, 0x8);
437 // Offset 0x180 - General Exception Vector
438 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
439 setHandlerPC(HandlerBase
, tc
);
443 InterruptFault::invoke(ThreadContext
*tc
)
446 DPRINTF(MipsPRA
, "%s encountered.\n", name());
447 setExceptionState(tc
, 0x0A);
450 CauseReg cause
= tc
->readMiscRegNoEffect(MISCREG_CAUSE
);
452 // Offset 200 for release 2
453 HandlerBase
= 0x20 + vect() + tc
->readMiscRegNoEffect(MISCREG_EBASE
);
455 //Ofset at 180 for release 1
456 HandlerBase
= vect() + tc
->readMiscRegNoEffect(MISCREG_EBASE
);
459 setHandlerPC(HandlerBase
, tc
);
463 #endif // FULL_SYSTEM
466 ResetFault::invoke(ThreadContext
*tc
)
469 DPRINTF(MipsPRA
, "%s encountered.\n", name());
470 /* All reset activity must be invoked from here */
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());
477 // Set Coprocessor 1 (Floating Point) To Usable
478 StatusReg status
= tc
->readMiscRegNoEffect(MISCREG_STATUS
);
480 tc
->setMiscReg(MISCREG_STATUS
, status
);
484 ReservedInstructionFault::invoke(ThreadContext
*tc
)
487 DPRINTF(MipsPRA
, "%s encountered.\n", name());
488 setExceptionState(tc
, 0x0A);
490 // Offset 0x180 - General Exception Vector
491 HandlerBase
= vect() + tc
->readMiscRegNoEffect(MISCREG_EBASE
);
492 setHandlerPC(HandlerBase
, tc
);
494 panic("%s encountered.\n", name());
499 ThreadFault::invoke(ThreadContext
*tc
)
501 DPRINTF(MipsPRA
, "%s encountered.\n", name());
502 panic("%s encountered.\n", name());
506 DspStateDisabledFault::invoke(ThreadContext
*tc
)
508 DPRINTF(MipsPRA
, "%s encountered.\n", name());
509 panic("%s encountered.\n", name());
513 CoprocessorUnusableFault::invoke(ThreadContext
*tc
)
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
);
522 tc
->setMiscRegNoEffect(MISCREG_CAUSE
, cause
);
525 // Offset 0x180 - General Exception Vector
526 HandlerBase
= vect() + tc
->readMiscReg(MISCREG_EBASE
);
527 setHandlerPC(HandlerBase
, tc
);
530 warn("%s (CP%d) encountered.\n", name(), coProcID
);
534 } // namespace MipsISA