faults.cc revision 8232:b28d06a175be
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
538