Deleted Added
sdiff udiff text old ( 8232:b28d06a175be ) new ( 8566:812d279f7b51 )
full compact
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;
52
53FaultName AlignmentFault::_name = "Alignment";
54FaultVect AlignmentFault::_vect = 0x0301;
55FaultStat AlignmentFault::_count;
56
57FaultName ResetFault::_name = "Reset Fault";
58#if FULL_SYSTEM
59FaultVect ResetFault::_vect = 0xBFC00000;
60#else
61FaultVect ResetFault::_vect = 0x001;
62#endif
63FaultStat ResetFault::_count;
64
65FaultName AddressErrorFault::_name = "Address Error";
66FaultVect AddressErrorFault::_vect = 0x0180;
67FaultStat AddressErrorFault::_count;
68
69FaultName StoreAddressErrorFault::_name = "Store Address Error";
70FaultVect StoreAddressErrorFault::_vect = 0x0180;
71FaultStat StoreAddressErrorFault::_count;
72
73
74FaultName SystemCallFault::_name = "Syscall";
75FaultVect SystemCallFault::_vect = 0x0180;
76FaultStat SystemCallFault::_count;
77
78FaultName CoprocessorUnusableFault::_name = "Coprocessor Unusable Fault";
79FaultVect CoprocessorUnusableFault::_vect = 0x180;
80FaultStat CoprocessorUnusableFault::_count;
81
82FaultName ReservedInstructionFault::_name = "Reserved Instruction Fault";
83FaultVect ReservedInstructionFault::_vect = 0x0180;
84FaultStat ReservedInstructionFault::_count;
85
86FaultName ThreadFault::_name = "Thread Fault";
87FaultVect ThreadFault::_vect = 0x00F1;
88FaultStat ThreadFault::_count;
89
90FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception";
91FaultVect ArithmeticFault::_vect = 0x180;
92FaultStat ArithmeticFault::_count;
93
94FaultName UnimplementedOpcodeFault::_name = "opdec";
95FaultVect UnimplementedOpcodeFault::_vect = 0x0481;
96FaultStat UnimplementedOpcodeFault::_count;
97
98FaultName InterruptFault::_name = "interrupt";
99FaultVect InterruptFault::_vect = 0x0180;
100FaultStat InterruptFault::_count;
101
102FaultName TrapFault::_name = "Trap";
103FaultVect TrapFault::_vect = 0x0180;
104FaultStat TrapFault::_count;
105
106FaultName BreakpointFault::_name = "Breakpoint";
107FaultVect BreakpointFault::_vect = 0x0180;
108FaultStat BreakpointFault::_count;
109
110FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)";
111FaultVect ItbInvalidFault::_vect = 0x0180;
112FaultStat ItbInvalidFault::_count;
113
114FaultName ItbPageFault::_name = "itbmiss";
115FaultVect ItbPageFault::_vect = 0x0181;
116FaultStat ItbPageFault::_count;
117
118FaultName ItbMissFault::_name = "itbmiss";
119FaultVect ItbMissFault::_vect = 0x0181;
120FaultStat ItbMissFault::_count;
121
122FaultName ItbAcvFault::_name = "iaccvio";
123FaultVect ItbAcvFault::_vect = 0x0081;
124FaultStat ItbAcvFault::_count;
125
126FaultName ItbRefillFault::_name = "TLB Refill Exception (I-Fetch/LW)";
127FaultVect ItbRefillFault::_vect = 0x0180;
128FaultStat ItbRefillFault::_count;
129
130FaultName NDtbMissFault::_name = "dtb_miss_single";
131FaultVect NDtbMissFault::_vect = 0x0201;
132FaultStat NDtbMissFault::_count;
133
134FaultName PDtbMissFault::_name = "dtb_miss_double";
135FaultVect PDtbMissFault::_vect = 0x0281;
136FaultStat PDtbMissFault::_count;
137
138FaultName DtbPageFault::_name = "dfault";
139FaultVect DtbPageFault::_vect = 0x0381;
140FaultStat DtbPageFault::_count;
141
142FaultName DtbAcvFault::_name = "dfault";
143FaultVect DtbAcvFault::_vect = 0x0381;
144FaultStat DtbAcvFault::_count;
145
146FaultName DtbInvalidFault::_name = "Invalid TLB Entry Exception (Store)";
147FaultVect DtbInvalidFault::_vect = 0x0180;
148FaultStat DtbInvalidFault::_count;
149
150FaultName DtbRefillFault::_name = "TLB Refill Exception (Store)";
151FaultVect DtbRefillFault::_vect = 0x0180;
152FaultStat DtbRefillFault::_count;
153
154FaultName TLBModifiedFault::_name = "TLB Modified Exception";
155FaultVect TLBModifiedFault::_vect = 0x0180;
156FaultStat TLBModifiedFault::_count;
157
158FaultName FloatEnableFault::_name = "float_enable_fault";
159FaultVect FloatEnableFault::_vect = 0x0581;
160FaultStat FloatEnableFault::_count;
161
162FaultName IntegerOverflowFault::_name = "Integer Overflow Fault";
163FaultVect IntegerOverflowFault::_vect = 0x0501;
164FaultStat IntegerOverflowFault::_count;
165
166FaultName DspStateDisabledFault::_name = "DSP Disabled Fault";
167FaultVect DspStateDisabledFault::_vect = 0x001a;
168FaultStat DspStateDisabledFault::_count;
169
170#if FULL_SYSTEM
171void
172MipsFault::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
180MipsFault::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