faults.cc revision 8574:16a168a366d8
11736SN/A/*
27778Sgblack@eecs.umich.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan
31736SN/A * Copyright (c) 2007 MIPS Technologies, Inc.
41736SN/A * All rights reserved.
51736SN/A *
61736SN/A * Redistribution and use in source and binary forms, with or without
71736SN/A * modification, are permitted provided that the following conditions are
81736SN/A * met: redistributions of source code must retain the above copyright
91736SN/A * notice, this list of conditions and the following disclaimer;
101736SN/A * redistributions in binary form must reproduce the above copyright
111736SN/A * notice, this list of conditions and the following disclaimer in the
121736SN/A * documentation and/or other materials provided with the distribution;
131736SN/A * neither the name of the copyright holders nor the names of its
141736SN/A * contributors may be used to endorse or promote products derived from
151736SN/A * this software without specific prior written permission.
161736SN/A *
171736SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
181736SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
191736SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
201736SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
211736SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
221736SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
231736SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
241736SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
251736SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
261736SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272665SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282665SN/A *
297778Sgblack@eecs.umich.edu * Authors: Gabe Black
301736SN/A *          Korey Sewell
311519SN/A *          Jaidev Patwardhan
321519SN/A */
331519SN/A
341519SN/A#include "arch/mips/faults.hh"
351519SN/A#include "arch/mips/pra_constants.hh"
361519SN/A#include "base/trace.hh"
371519SN/A#include "cpu/base.hh"
381519SN/A#include "cpu/thread_context.hh"
391519SN/A#include "debug/MipsPRA.hh"
401519SN/A
411519SN/A#if !FULL_SYSTEM
421519SN/A#include "mem/page_table.hh"
431519SN/A#include "sim/process.hh"
441519SN/A#endif
451519SN/A
461519SN/Anamespace MipsISA
471519SN/A{
481519SN/A
491519SN/Atypedef MipsFaultBase::FaultVals FaultVals;
501519SN/A
511519SN/Atemplate <> FaultVals MipsFault<MachineCheckFault>::vals =
521519SN/A    { "Machine Check", 0x0401 };
531519SN/A
541519SN/Atemplate <> FaultVals MipsFault<ResetFault>::vals =
551606SN/A#if  FULL_SYSTEM
561519SN/A    { "Reset Fault", 0xBFC00000};
571606SN/A#else
581606SN/A    { "Reset Fault", 0x001};
591606SN/A#endif
601606SN/A
611519SN/Atemplate <> FaultVals MipsFault<AddressErrorFault>::vals =
621606SN/A    { "Address Error", 0x0180 };
631519SN/A
641606SN/Atemplate <> FaultVals MipsFault<SystemCallFault>::vals =
651519SN/A    { "Syscall", 0x0180 };
661606SN/A
671519SN/Atemplate <> FaultVals MipsFault<CoprocessorUnusableFault>::vals =
681606SN/A    { "Coprocessor Unusable Fault", 0x180 };
691519SN/A
701606SN/Atemplate <> FaultVals MipsFault<ReservedInstructionFault>::vals =
711519SN/A    { "Reserved Instruction Fault", 0x0180 };
721606SN/A
731519SN/Atemplate <> FaultVals MipsFault<ThreadFault>::vals =
741606SN/A    { "Thread Fault", 0x00F1 };
751519SN/A
761606SN/Atemplate <> FaultVals MipsFault<IntegerOverflowFault>::vals =
771519SN/A    { "Integer Overflow Exception", 0x180 };
781606SN/A
791519SN/Atemplate <> FaultVals MipsFault<InterruptFault>::vals =
801606SN/A    { "interrupt", 0x0180 };
811519SN/A
821606SN/Atemplate <> FaultVals MipsFault<TrapFault>::vals =
831519SN/A    { "Trap", 0x0180 };
841606SN/A
851519SN/Atemplate <> FaultVals MipsFault<BreakpointFault>::vals =
861606SN/A    { "Breakpoint", 0x0180 };
871519SN/A
881606SN/Atemplate <> FaultVals MipsFault<TlbInvalidFault>::vals =
891519SN/A    { "Invalid TLB Entry Exception", 0x0180 };
901606SN/A
911519SN/Atemplate <> FaultVals MipsFault<TlbRefillFault>::vals =
921606SN/A    { "TLB Refill Exception", 0x0180 };
931519SN/A
941606SN/Atemplate <> FaultVals MipsFault<TLBModifiedFault>::vals =
951606SN/A    { "TLB Modified Exception", 0x0180 };
961606SN/A
971606SN/Atemplate <> FaultVals MipsFault<DspStateDisabledFault>::vals =
981944SN/A    { "DSP Disabled Fault", 0x001a };
991606SN/A
1001606SN/Avoid
1011519SN/AMipsFaultBase::setExceptionState(ThreadContext *tc, uint8_t excCode)
1021606SN/A{
1031606SN/A    // modify SRS Ctl - Save CSS, put ESS into CSS
1041858SN/A    StatusReg status = tc->readMiscReg(MISCREG_STATUS);
1051858SN/A    if (status.exl != 1 && status.bev != 1) {
1061858SN/A        // SRS Ctl is modified only if Status_EXL and Status_BEV are not set
1071858SN/A        SRSCtlReg srsCtl = tc->readMiscReg(MISCREG_SRSCTL);
1081858SN/A        srsCtl.pss = srsCtl.css;
1091606SN/A        srsCtl.css = srsCtl.ess;
1101606SN/A        tc->setMiscRegNoEffect(MISCREG_SRSCTL, srsCtl);
1111606SN/A    }
1121606SN/A
1131606SN/A    // set EXL bit (don't care if it is already set!)
1141858SN/A    status.exl = 1;
1151858SN/A    tc->setMiscRegNoEffect(MISCREG_STATUS, status);
1161858SN/A
1171858SN/A    // write EPC
1181519SN/A    PCState pc = tc->pcState();
1191589SN/A    DPRINTF(MipsPRA, "PC: %s\n", pc);
1201519SN/A    bool delay_slot = pc.pc() + sizeof(MachInst) != pc.npc();
1211606SN/A    tc->setMiscRegNoEffect(MISCREG_EPC,
1221606SN/A            pc.pc() - delay_slot ? sizeof(MachInst) : 0);
1231606SN/A
1241606SN/A    // Set Cause_EXCCODE field
1251519SN/A    CauseReg cause = tc->readMiscReg(MISCREG_CAUSE);
1261606SN/A    cause.excCode = excCode;
1271519SN/A    cause.bd = delay_slot ? 1 : 0;
1281606SN/A    cause.ce = 0;
1291519SN/A    tc->setMiscRegNoEffect(MISCREG_CAUSE, cause);
1301606SN/A}
1311519SN/A
1321606SN/A#if FULL_SYSTEM
1331519SN/Avoid
1341606SN/AMipsFaultBase::setHandlerPC(Addr HandlerBase, ThreadContext *tc)
1351519SN/A{
1361589SN/A    tc->setPC(HandlerBase);
1371519SN/A    tc->setNextPC(HandlerBase + sizeof(MachInst));
1381606SN/A    tc->setNextNPC(HandlerBase + 2 * sizeof(MachInst));
1391606SN/A}
1401606SN/A
1411606SN/Avoid
1421519SN/AIntegerOverflowFault::invoke(ThreadContext *tc, StaticInstPtr inst)
1431606SN/A{
1441519SN/A    DPRINTF(MipsPRA, "%s encountered.\n", name());
1451606SN/A    setExceptionState(tc, 0xC);
1461519SN/A
1471606SN/A    // Set new PC
1481519SN/A    Addr HandlerBase;
1491606SN/A    StatusReg status = tc->readMiscReg(MISCREG_STATUS);
1501519SN/A    // Here, the handler is dependent on BEV, which is not modified by
1511606SN/A    // setExceptionState()
1521606SN/A    if (!status.bev) {
1534167SN/A        // See MIPS ARM Vol 3, Revision 2, Page 38
1541606SN/A        HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
1551606SN/A    } else {
1561606SN/A        HandlerBase = 0xBFC00200;
1571606SN/A    }
1581606SN/A    setHandlerPC(HandlerBase, tc);
1591606SN/A}
1601606SN/A
1611606SN/Avoid
1621606SN/ATrapFault::invoke(ThreadContext *tc, StaticInstPtr inst)
1631606SN/A{
1641606SN/A    DPRINTF(MipsPRA, "%s encountered.\n", name());
1651606SN/A    setExceptionState(tc, 0xD);
1661606SN/A
1671606SN/A    // Set new PC
1681606SN/A    Addr HandlerBase;
1691606SN/A    // Offset 0x180 - General Exception Vector
1701606SN/A    HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
1711606SN/A    setHandlerPC(HandlerBase, tc);
1721606SN/A}
1731606SN/A
1741606SN/Avoid
1754167SN/ABreakpointFault::invoke(ThreadContext *tc, StaticInstPtr inst)
1764167SN/A{
1774167SN/A    setExceptionState(tc, 0x9);
1784167SN/A
1794167SN/A    // Set new PC
1804167SN/A    Addr HandlerBase;
1814167SN/A    // Offset 0x180 - General Exception Vector
1824167SN/A    HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
1834167SN/A    setHandlerPC(HandlerBase, tc);
1844167SN/A}
1854167SN/A
1864167SN/Avoid
1874167SN/ATlbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst)
1884167SN/A{
1894167SN/A    DPRINTF(MipsPRA, "%s encountered.\n", name());
1904167SN/A    setExceptionState(tc, store ? 0x3 : 0x2);
1914167SN/A
1924167SN/A    tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
1934167SN/A    EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
1944167SN/A    entryHi.asid = entryHiAsid;
1954167SN/A    entryHi.vpn2 = entryHiVPN2;
1961519SN/A    entryHi.vpn2x = entryHiVPN2X;
1971589SN/A    tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
1981519SN/A
1991606SN/A    ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
2001606SN/A    context.badVPN2 = contextBadVPN2;
2011606SN/A    tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
2021627SN/A
2031519SN/A    // Set new PC
2041627SN/A    Addr HandlerBase;
2051519SN/A    // Offset 0x180 - General Exception Vector
2061627SN/A    HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
2071519SN/A    setHandlerPC(HandlerBase, tc);
2081627SN/A}
2091519SN/A
2101627SN/Avoid
2111519SN/AAddressErrorFault::invoke(ThreadContext *tc, StaticInstPtr inst)
2121606SN/A{
2131519SN/A    DPRINTF(MipsPRA, "%s encountered.\n", name());
2141606SN/A    setExceptionState(tc, store ? 0x5 : 0x4);
2151519SN/A    tc->setMiscRegNoEffect(MISCREG_BADVADDR, vaddr);
2161589SN/A
2171519SN/A    // Set new PC
2181606SN/A    Addr HandlerBase;
2191606SN/A    // Offset 0x180 - General Exception Vector
2201606SN/A    HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
2211606SN/A    setHandlerPC(HandlerBase, tc);
2221519SN/A}
2231606SN/A
2241519SN/Avoid
2251606SN/ATlbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst)
2261519SN/A{
2271606SN/A    DPRINTF(MipsPRA, "%s encountered (%x).\n", name(), MISCREG_BADVADDR);
2281519SN/A    setExceptionState(tc, store ? 0x3 : 0x2);
2291606SN/A
2301519SN/A    Addr HandlerBase;
2311606SN/A    tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
2321519SN/A    EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
2331606SN/A    entryHi.asid = entryHiAsid;
2341519SN/A    entryHi.vpn2 = entryHiVPN2;
2351589SN/A    entryHi.vpn2x = entryHiVPN2X;
2361519SN/A    tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
2371606SN/A    ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
2381606SN/A    context.badVPN2 = contextBadVPN2;
2391606SN/A    tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
2401944SN/A
2411519SN/A    StatusReg status = tc->readMiscReg(MISCREG_STATUS);
2421944SN/A    // Since handler depends on EXL bit, must check EXL bit before setting it!!
2431519SN/A    // See MIPS ARM Vol 3, Revision 2, Page 38
2441944SN/A    if (status.exl == 1) {
2451519SN/A        // Offset 0x180 - General Exception Vector
2461944SN/A        HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
2471519SN/A    } else {
2481944SN/A        // Offset 0x000
2491519SN/A        HandlerBase = tc->readMiscReg(MISCREG_EBASE);
2501944SN/A    }
2511519SN/A    setHandlerPC(HandlerBase, tc);
2521606SN/A}
2537777Sgblack@eecs.umich.edu
2547777Sgblack@eecs.umich.eduvoid
2557777Sgblack@eecs.umich.eduTLBModifiedFault::invoke(ThreadContext *tc, StaticInstPtr inst)
2567777Sgblack@eecs.umich.edu{
2577777Sgblack@eecs.umich.edu    DPRINTF(MipsPRA, "%s encountered.\n", name());
2587777Sgblack@eecs.umich.edu    tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr);
2597777Sgblack@eecs.umich.edu    EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI);
2607777Sgblack@eecs.umich.edu    entryHi.asid = entryHiAsid;
2617777Sgblack@eecs.umich.edu    entryHi.vpn2 = entryHiVPN2;
2627777Sgblack@eecs.umich.edu    entryHi.vpn2x = entryHiVPN2X;
2637777Sgblack@eecs.umich.edu    tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi);
2647777Sgblack@eecs.umich.edu
2657777Sgblack@eecs.umich.edu    ContextReg context = tc->readMiscReg(MISCREG_CONTEXT);
2667777Sgblack@eecs.umich.edu    context.badVPN2 = contextBadVPN2;
2677777Sgblack@eecs.umich.edu    tc->setMiscRegNoEffect(MISCREG_CONTEXT, context);
2687777Sgblack@eecs.umich.edu
2697777Sgblack@eecs.umich.edu    // Set new PC
2707777Sgblack@eecs.umich.edu    Addr HandlerBase;
2717777Sgblack@eecs.umich.edu    // Offset 0x180 - General Exception Vector
2727777Sgblack@eecs.umich.edu    HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
2737777Sgblack@eecs.umich.edu    setExceptionState(tc, 0x1);
2747777Sgblack@eecs.umich.edu    setHandlerPC(HandlerBase, tc);
2757777Sgblack@eecs.umich.edu
2767777Sgblack@eecs.umich.edu}
2777777Sgblack@eecs.umich.edu
2787777Sgblack@eecs.umich.eduvoid
2797777Sgblack@eecs.umich.eduSystemCallFault::invoke(ThreadContext *tc, StaticInstPtr inst)
2807777Sgblack@eecs.umich.edu{
2817777Sgblack@eecs.umich.edu    DPRINTF(MipsPRA, "%s encountered.\n", name());
2827777Sgblack@eecs.umich.edu    setExceptionState(tc, 0x8);
2837777Sgblack@eecs.umich.edu
2847777Sgblack@eecs.umich.edu    // Set new PC
2857777Sgblack@eecs.umich.edu    Addr HandlerBase;
2867777Sgblack@eecs.umich.edu    // Offset 0x180 - General Exception Vector
2877777Sgblack@eecs.umich.edu    HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
2887777Sgblack@eecs.umich.edu    setHandlerPC(HandlerBase, tc);
2897777Sgblack@eecs.umich.edu}
2907777Sgblack@eecs.umich.edu
2917777Sgblack@eecs.umich.eduvoid
2927777Sgblack@eecs.umich.eduInterruptFault::invoke(ThreadContext *tc, StaticInstPtr inst)
2937777Sgblack@eecs.umich.edu{
2947777Sgblack@eecs.umich.edu#if  FULL_SYSTEM
2957777Sgblack@eecs.umich.edu    DPRINTF(MipsPRA, "%s encountered.\n", name());
2967777Sgblack@eecs.umich.edu    setExceptionState(tc, 0x0A);
2977777Sgblack@eecs.umich.edu    Addr HandlerBase;
2987777Sgblack@eecs.umich.edu
2997777Sgblack@eecs.umich.edu    CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE);
3007777Sgblack@eecs.umich.edu    if (cause.iv) {
3017777Sgblack@eecs.umich.edu        // Offset 200 for release 2
3029827Sakash.bagdia@arm.com        HandlerBase = 0x20 + vect() + tc->readMiscRegNoEffect(MISCREG_EBASE);
3039827Sakash.bagdia@arm.com    } else {
3049827Sakash.bagdia@arm.com        //Ofset at 180 for release 1
3059827Sakash.bagdia@arm.com        HandlerBase = vect() + tc->readMiscRegNoEffect(MISCREG_EBASE);
3069827Sakash.bagdia@arm.com    }
3079827Sakash.bagdia@arm.com
3089827Sakash.bagdia@arm.com    setHandlerPC(HandlerBase, tc);
3099827Sakash.bagdia@arm.com#endif
3109827Sakash.bagdia@arm.com}
3119827Sakash.bagdia@arm.com
3129827Sakash.bagdia@arm.com#endif // FULL_SYSTEM
3139827Sakash.bagdia@arm.com
31410427Sandreas.hansson@arm.comvoid
31510427Sandreas.hansson@arm.comResetFault::invoke(ThreadContext *tc, StaticInstPtr inst)
31610427Sandreas.hansson@arm.com{
31710427Sandreas.hansson@arm.com#if FULL_SYSTEM
31810427Sandreas.hansson@arm.com    DPRINTF(MipsPRA, "%s encountered.\n", name());
31910427Sandreas.hansson@arm.com    /* All reset activity must be invoked from here */
32010427Sandreas.hansson@arm.com    tc->setPC(vect());
32110427Sandreas.hansson@arm.com    tc->setNextPC(vect() + sizeof(MachInst));
322    tc->setNextNPC(vect() + sizeof(MachInst) + sizeof(MachInst));
323    DPRINTF(MipsPRA, "ResetFault::invoke : PC set to %x", tc->readPC());
324#endif
325
326    // Set Coprocessor 1 (Floating Point) To Usable
327    StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS);
328    status.cu.cu1 = 1;
329    tc->setMiscReg(MISCREG_STATUS, status);
330}
331
332void
333ReservedInstructionFault::invoke(ThreadContext *tc, StaticInstPtr inst)
334{
335#if  FULL_SYSTEM
336    DPRINTF(MipsPRA, "%s encountered.\n", name());
337    setExceptionState(tc, 0x0A);
338    Addr HandlerBase;
339    // Offset 0x180 - General Exception Vector
340    HandlerBase = vect() + tc->readMiscRegNoEffect(MISCREG_EBASE);
341    setHandlerPC(HandlerBase, tc);
342#else
343    panic("%s encountered.\n", name());
344#endif
345}
346
347void
348ThreadFault::invoke(ThreadContext *tc, StaticInstPtr inst)
349{
350    DPRINTF(MipsPRA, "%s encountered.\n", name());
351    panic("%s encountered.\n", name());
352}
353
354void
355DspStateDisabledFault::invoke(ThreadContext *tc, StaticInstPtr inst)
356{
357    DPRINTF(MipsPRA, "%s encountered.\n", name());
358    panic("%s encountered.\n", name());
359}
360
361void
362CoprocessorUnusableFault::invoke(ThreadContext *tc, StaticInstPtr inst)
363{
364#if FULL_SYSTEM
365    DPRINTF(MipsPRA, "%s encountered.\n", name());
366    setExceptionState(tc, 0xb);
367    // The ID of the coprocessor causing the exception is stored in
368    // CoprocessorUnusableFault::coProcID
369    CauseReg cause = tc->readMiscReg(MISCREG_CAUSE);
370    cause.ce = coProcID;
371    tc->setMiscRegNoEffect(MISCREG_CAUSE, cause);
372
373    Addr HandlerBase;
374    // Offset 0x180 - General Exception Vector
375    HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE);
376    setHandlerPC(HandlerBase, tc);
377
378#else
379    warn("%s (CP%d) encountered.\n", name(), coProcID);
380#endif
381}
382
383} // namespace MipsISA
384
385