faults.cc revision 6383:31c067ae3331
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
44namespace MipsISA
45{
46
47FaultName MachineCheckFault::_name = "Machine Check";
48FaultVect MachineCheckFault::_vect = 0x0401;
49FaultStat MachineCheckFault::_count;
50
51FaultName AlignmentFault::_name = "Alignment";
52FaultVect AlignmentFault::_vect = 0x0301;
53FaultStat AlignmentFault::_count;
54
55FaultName ResetFault::_name = "Reset Fault";
56#if  FULL_SYSTEM
57FaultVect ResetFault::_vect = 0xBFC00000;
58#else
59FaultVect ResetFault::_vect = 0x001;
60#endif
61FaultStat ResetFault::_count;
62
63FaultName AddressErrorFault::_name = "Address Error";
64FaultVect AddressErrorFault::_vect = 0x0180;
65FaultStat AddressErrorFault::_count;
66
67FaultName StoreAddressErrorFault::_name = "Store Address Error";
68FaultVect StoreAddressErrorFault::_vect = 0x0180;
69FaultStat StoreAddressErrorFault::_count;
70
71
72FaultName SystemCallFault::_name = "Syscall";
73FaultVect SystemCallFault::_vect = 0x0180;
74FaultStat SystemCallFault::_count;
75
76FaultName CoprocessorUnusableFault::_name = "Coprocessor Unusable Fault";
77FaultVect CoprocessorUnusableFault::_vect = 0x180;
78FaultStat CoprocessorUnusableFault::_count;
79
80FaultName ReservedInstructionFault::_name = "Reserved Instruction Fault";
81FaultVect ReservedInstructionFault::_vect = 0x0180;
82FaultStat ReservedInstructionFault::_count;
83
84FaultName ThreadFault::_name = "Thread Fault";
85FaultVect ThreadFault::_vect = 0x00F1;
86FaultStat ThreadFault::_count;
87
88FaultName ArithmeticFault::_name = "Arithmetic Overflow Exception";
89FaultVect ArithmeticFault::_vect = 0x180;
90FaultStat ArithmeticFault::_count;
91
92FaultName UnimplementedOpcodeFault::_name = "opdec";
93FaultVect UnimplementedOpcodeFault::_vect = 0x0481;
94FaultStat UnimplementedOpcodeFault::_count;
95
96FaultName InterruptFault::_name = "interrupt";
97FaultVect InterruptFault::_vect = 0x0180;
98FaultStat InterruptFault::_count;
99
100FaultName TrapFault::_name = "Trap";
101FaultVect TrapFault::_vect = 0x0180;
102FaultStat TrapFault::_count;
103
104FaultName BreakpointFault::_name = "Breakpoint";
105FaultVect BreakpointFault::_vect = 0x0180;
106FaultStat BreakpointFault::_count;
107
108FaultName ItbInvalidFault::_name = "Invalid TLB Entry Exception (I-Fetch/LW)";
109FaultVect ItbInvalidFault::_vect = 0x0180;
110FaultStat ItbInvalidFault::_count;
111
112FaultName ItbPageFault::_name = "itbmiss";
113FaultVect ItbPageFault::_vect = 0x0181;
114FaultStat ItbPageFault::_count;
115
116FaultName ItbMissFault::_name = "itbmiss";
117FaultVect ItbMissFault::_vect = 0x0181;
118FaultStat ItbMissFault::_count;
119
120FaultName ItbAcvFault::_name = "iaccvio";
121FaultVect ItbAcvFault::_vect = 0x0081;
122FaultStat ItbAcvFault::_count;
123
124FaultName ItbRefillFault::_name = "TLB Refill Exception (I-Fetch/LW)";
125FaultVect ItbRefillFault::_vect = 0x0180;
126FaultStat ItbRefillFault::_count;
127
128FaultName NDtbMissFault::_name = "dtb_miss_single";
129FaultVect NDtbMissFault::_vect = 0x0201;
130FaultStat NDtbMissFault::_count;
131
132FaultName PDtbMissFault::_name = "dtb_miss_double";
133FaultVect PDtbMissFault::_vect = 0x0281;
134FaultStat PDtbMissFault::_count;
135
136FaultName DtbPageFault::_name = "dfault";
137FaultVect DtbPageFault::_vect = 0x0381;
138FaultStat DtbPageFault::_count;
139
140FaultName DtbAcvFault::_name = "dfault";
141FaultVect DtbAcvFault::_vect = 0x0381;
142FaultStat DtbAcvFault::_count;
143
144FaultName DtbInvalidFault::_name = "Invalid TLB Entry Exception (Store)";
145FaultVect DtbInvalidFault::_vect = 0x0180;
146FaultStat DtbInvalidFault::_count;
147
148FaultName DtbRefillFault::_name = "TLB Refill Exception (Store)";
149FaultVect DtbRefillFault::_vect = 0x0180;
150FaultStat DtbRefillFault::_count;
151
152FaultName TLBModifiedFault::_name = "TLB Modified Exception";
153FaultVect TLBModifiedFault::_vect = 0x0180;
154FaultStat TLBModifiedFault::_count;
155
156FaultName FloatEnableFault::_name = "float_enable_fault";
157FaultVect FloatEnableFault::_vect = 0x0581;
158FaultStat FloatEnableFault::_count;
159
160FaultName IntegerOverflowFault::_name = "Integer Overflow Fault";
161FaultVect IntegerOverflowFault::_vect = 0x0501;
162FaultStat IntegerOverflowFault::_count;
163
164FaultName DspStateDisabledFault::_name = "DSP Disabled Fault";
165FaultVect DspStateDisabledFault::_vect = 0x001a;
166FaultStat DspStateDisabledFault::_count;
167
168#if FULL_SYSTEM
169void
170MipsFault::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
177void
178MipsFault::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
218void
219ArithmeticFault::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
238void
239StoreAddressErrorFault::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
252void
253TrapFault::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
265void
266BreakpointFault::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
277void
278DtbInvalidFault::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
302void
303AddressErrorFault::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
316void
317ItbInvalidFault::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
342void
343ItbRefillFault::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
372void
373DtbRefillFault::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
405void
406TLBModifiedFault::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
429void
430SystemCallFault::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
442void
443InterruptFault::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
465void
466ResetFault::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
483void
484ReservedInstructionFault::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
498void
499ThreadFault::invoke(ThreadContext *tc)
500{
501    DPRINTF(MipsPRA, "%s encountered.\n", name());
502    panic("%s encountered.\n", name());
503}
504
505void
506DspStateDisabledFault::invoke(ThreadContext *tc)
507{
508    DPRINTF(MipsPRA, "%s encountered.\n", name());
509    panic("%s encountered.\n", name());
510}
511
512void
513CoprocessorUnusableFault::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
536