faults.cc revision 8577:37dbd858c367
1955SN/A/*
2955SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
35871Snate@binkert.org * Copyright (c) 2007 MIPS Technologies, Inc.
41762SN/A * All rights reserved.
5955SN/A *
6955SN/A * Redistribution and use in source and binary forms, with or without
7955SN/A * modification, are permitted provided that the following conditions are
8955SN/A * met: redistributions of source code must retain the above copyright
9955SN/A * notice, this list of conditions and the following disclaimer;
10955SN/A * redistributions in binary form must reproduce the above copyright
11955SN/A * notice, this list of conditions and the following disclaimer in the
12955SN/A * documentation and/or other materials provided with the distribution;
13955SN/A * neither the name of the copyright holders nor the names of its
14955SN/A * contributors may be used to endorse or promote products derived from
15955SN/A * this software without specific prior written permission.
16955SN/A *
17955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28955SN/A *
292665Ssaidi@eecs.umich.edu * Authors: Gabe Black
302665Ssaidi@eecs.umich.edu *          Korey Sewell
315863Snate@binkert.org *          Jaidev Patwardhan
32955SN/A */
33955SN/A
34955SN/A#include "arch/mips/faults.hh"
35955SN/A#include "arch/mips/pra_constants.hh"
36955SN/A#include "base/trace.hh"
372632Sstever@eecs.umich.edu#include "cpu/base.hh"
382632Sstever@eecs.umich.edu#include "cpu/thread_context.hh"
392632Sstever@eecs.umich.edu#include "debug/MipsPRA.hh"
402632Sstever@eecs.umich.edu
41955SN/A#if !FULL_SYSTEM
422632Sstever@eecs.umich.edu#include "mem/page_table.hh"
432632Sstever@eecs.umich.edu#include "sim/process.hh"
442761Sstever@eecs.umich.edu#endif
452632Sstever@eecs.umich.edu
462632Sstever@eecs.umich.edunamespace MipsISA
472632Sstever@eecs.umich.edu{
482761Sstever@eecs.umich.edu
492761Sstever@eecs.umich.edutypedef MipsFaultBase::FaultVals FaultVals;
502761Sstever@eecs.umich.edu
512632Sstever@eecs.umich.edutemplate <> FaultVals MipsFault<MachineCheckFault>::vals =
522632Sstever@eecs.umich.edu    { "Machine Check", 0x0401 };
532761Sstever@eecs.umich.edu
542761Sstever@eecs.umich.edutemplate <> FaultVals MipsFault<ResetFault>::vals =
552761Sstever@eecs.umich.edu#if  FULL_SYSTEM
562761Sstever@eecs.umich.edu    { "Reset Fault", 0xBFC00000};
572761Sstever@eecs.umich.edu#else
582632Sstever@eecs.umich.edu    { "Reset Fault", 0x001};
592632Sstever@eecs.umich.edu#endif
602632Sstever@eecs.umich.edu
612632Sstever@eecs.umich.edutemplate <> FaultVals MipsFault<AddressErrorFault>::vals =
622632Sstever@eecs.umich.edu    { "Address Error", 0x0180 };
632632Sstever@eecs.umich.edu
642632Sstever@eecs.umich.edutemplate <> FaultVals MipsFault<SystemCallFault>::vals =
65955SN/A    { "Syscall", 0x0180 };
66955SN/A
67955SN/Atemplate <> FaultVals MipsFault<CoprocessorUnusableFault>::vals =
685863Snate@binkert.org    { "Coprocessor Unusable Fault", 0x180 };
695863Snate@binkert.org
705863Snate@binkert.orgtemplate <> FaultVals MipsFault<ReservedInstructionFault>::vals =
715863Snate@binkert.org    { "Reserved Instruction Fault", 0x0180 };
725863Snate@binkert.org
735863Snate@binkert.orgtemplate <> FaultVals MipsFault<ThreadFault>::vals =
745863Snate@binkert.org    { "Thread Fault", 0x00F1 };
755863Snate@binkert.org
765863Snate@binkert.orgtemplate <> FaultVals MipsFault<IntegerOverflowFault>::vals =
775863Snate@binkert.org    { "Integer Overflow Exception", 0x180 };
785863Snate@binkert.org
795863Snate@binkert.orgtemplate <> FaultVals MipsFault<InterruptFault>::vals =
805863Snate@binkert.org    { "interrupt", 0x0180 };
815863Snate@binkert.org
825863Snate@binkert.orgtemplate <> FaultVals MipsFault<TrapFault>::vals =
835863Snate@binkert.org    { "Trap", 0x0180 };
845863Snate@binkert.org
855863Snate@binkert.orgtemplate <> FaultVals MipsFault<BreakpointFault>::vals =
865863Snate@binkert.org    { "Breakpoint", 0x0180 };
875863Snate@binkert.org
885863Snate@binkert.orgtemplate <> FaultVals MipsFault<TlbInvalidFault>::vals =
895863Snate@binkert.org    { "Invalid TLB Entry Exception", 0x0180 };
905863Snate@binkert.org
915863Snate@binkert.orgtemplate <> FaultVals MipsFault<TlbRefillFault>::vals =
925863Snate@binkert.org    { "TLB Refill Exception", 0x0180 };
935863Snate@binkert.org
945863Snate@binkert.orgtemplate <> FaultVals MipsFault<TlbModifiedFault>::vals =
955863Snate@binkert.org    { "TLB Modified Exception", 0x0180 };
965863Snate@binkert.org
975863Snate@binkert.orgtemplate <> FaultVals MipsFault<DspStateDisabledFault>::vals =
985863Snate@binkert.org    { "DSP Disabled Fault", 0x001a };
996654Snate@binkert.org
100955SN/Avoid
1015396Ssaidi@eecs.umich.eduMipsFaultBase::setExceptionState(ThreadContext *tc, uint8_t excCode)
1025863Snate@binkert.org{
1035863Snate@binkert.org    // modify SRS Ctl - Save CSS, put ESS into CSS
1044202Sbinkertn@umich.edu    StatusReg status = tc->readMiscReg(MISCREG_STATUS);
1055863Snate@binkert.org    if (status.exl != 1 && status.bev != 1) {
1065863Snate@binkert.org        // SRS Ctl is modified only if Status_EXL and Status_BEV are not set
1075863Snate@binkert.org        SRSCtlReg srsCtl = tc->readMiscReg(MISCREG_SRSCTL);
1085863Snate@binkert.org        srsCtl.pss = srsCtl.css;
109955SN/A        srsCtl.css = srsCtl.ess;
1106654Snate@binkert.org        tc->setMiscRegNoEffect(MISCREG_SRSCTL, srsCtl);
1115273Sstever@gmail.com    }
1125871Snate@binkert.org
1135273Sstever@gmail.com    // set EXL bit (don't care if it is already set!)
1146655Snate@binkert.org    status.exl = 1;
1156655Snate@binkert.org    tc->setMiscRegNoEffect(MISCREG_STATUS, status);
1166655Snate@binkert.org
1176655Snate@binkert.org    // write EPC
1186655Snate@binkert.org    PCState pc = tc->pcState();
1196655Snate@binkert.org    DPRINTF(MipsPRA, "PC: %s\n", pc);
1205871Snate@binkert.org    bool delay_slot = pc.pc() + sizeof(MachInst) != pc.npc();
1216654Snate@binkert.org    tc->setMiscRegNoEffect(MISCREG_EPC,
1225396Ssaidi@eecs.umich.edu            pc.pc() - delay_slot ? sizeof(MachInst) : 0);
1235871Snate@binkert.org
1245871Snate@binkert.org    // Set Cause_EXCCODE field
1256121Snate@binkert.org    CauseReg cause = tc->readMiscReg(MISCREG_CAUSE);
1265871Snate@binkert.org    cause.excCode = excCode;
1275871Snate@binkert.org    cause.bd = delay_slot ? 1 : 0;
1286003Snate@binkert.org    cause.ce = 0;
1296655Snate@binkert.org    tc->setMiscRegNoEffect(MISCREG_CAUSE, cause);
130955SN/A}
1315871Snate@binkert.org
1325871Snate@binkert.org#if FULL_SYSTEM
1335871Snate@binkert.org
1345871Snate@binkert.orgvoid
135955SN/AIntegerOverflowFault::invoke(ThreadContext *tc, StaticInstPtr inst)
1366121Snate@binkert.org{
1376121Snate@binkert.org    DPRINTF(MipsPRA, "%s encountered.\n", name());
1386121Snate@binkert.org    setExceptionState(tc, 0xC);
1391533SN/A
1406655Snate@binkert.org    // Set new PC
1416655Snate@binkert.org    StatusReg status = tc->readMiscReg(MISCREG_STATUS);
1426655Snate@binkert.org    if (!status.bev) {
1436655Snate@binkert.org        // See MIPS ARM Vol 3, Revision 2, Page 38
1445871Snate@binkert.org        tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE));
1455871Snate@binkert.org    } else {
1465863Snate@binkert.org        tc->pcState(0xBFC00200);
1475871Snate@binkert.org    }
1485871Snate@binkert.org}
1495871Snate@binkert.org
1505871Snate@binkert.orgvoid
1515871Snate@binkert.orgTrapFault::invoke(ThreadContext *tc, StaticInstPtr inst)
1525863Snate@binkert.org{
1536121Snate@binkert.org    DPRINTF(MipsPRA, "%s encountered.\n", name());
1545863Snate@binkert.org    setExceptionState(tc, 0xD);
1555871Snate@binkert.org
1564678Snate@binkert.org    tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE));
1574678Snate@binkert.org}
1584678Snate@binkert.org
1594678Snate@binkert.orgvoid
1604678Snate@binkert.orgBreakpointFault::invoke(ThreadContext *tc, StaticInstPtr inst)
1614678Snate@binkert.org{
1624678Snate@binkert.org    setExceptionState(tc, 0x9);
1634678Snate@binkert.org
1644678Snate@binkert.org    tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE));
1654678Snate@binkert.org}
1664678Snate@binkert.org
1674678Snate@binkert.orgvoid
1686121Snate@binkert.orgAddressErrorFault::invoke(ThreadContext *tc, StaticInstPtr inst)
1694678Snate@binkert.org{
1705871Snate@binkert.org    DPRINTF(MipsPRA, "%s encountered.\n", name());
1715871Snate@binkert.org    setExceptionState(tc, store ? 0x5 : 0x4);
1725871Snate@binkert.org    tc->setMiscRegNoEffect(MISCREG_BADVADDR, vaddr);
1735871Snate@binkert.org
1745871Snate@binkert.org    tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE));
1755871Snate@binkert.org}
1765871Snate@binkert.org
1775871Snate@binkert.orgvoid
1785871Snate@binkert.orgTlbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst)
1795871Snate@binkert.org{
1805871Snate@binkert.org    setTlbExceptionState(tc, store ? 0x3 : 0x2);
1815871Snate@binkert.org    tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE));
1825871Snate@binkert.org}
1835990Ssaidi@eecs.umich.edu
1845871Snate@binkert.orgvoid
1855871Snate@binkert.orgTlbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst)
1865871Snate@binkert.org{
1874678Snate@binkert.org    // Since handler depends on EXL bit, must check EXL bit before setting it!!
1886654Snate@binkert.org    StatusReg status = tc->readMiscReg(MISCREG_STATUS);
1895871Snate@binkert.org
1905871Snate@binkert.org    setTlbExceptionState(tc, store ? 0x3 : 0x2);
1915871Snate@binkert.org
1925871Snate@binkert.org    // See MIPS ARM Vol 3, Revision 2, Page 38
1935871Snate@binkert.org    if (status.exl == 1) {
1945871Snate@binkert.org        tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE));
1955871Snate@binkert.org    } else {
1965871Snate@binkert.org        tc->pcState(tc->readMiscReg(MISCREG_EBASE));
1975871Snate@binkert.org    }
1984678Snate@binkert.org}
1995871Snate@binkert.org
2004678Snate@binkert.orgvoid
2015871Snate@binkert.orgTlbModifiedFault::invoke(ThreadContext *tc, StaticInstPtr inst)
2025871Snate@binkert.org{
2035871Snate@binkert.org    setTlbExceptionState(tc, 0x1);
2045871Snate@binkert.org
2055871Snate@binkert.org    tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE));
2065871Snate@binkert.org}
2075871Snate@binkert.org
2085871Snate@binkert.orgvoid
2095871Snate@binkert.orgSystemCallFault::invoke(ThreadContext *tc, StaticInstPtr inst)
2106121Snate@binkert.org{
2116121Snate@binkert.org    DPRINTF(MipsPRA, "%s encountered.\n", name());
2125863Snate@binkert.org    setExceptionState(tc, 0x8);
213955SN/A
214955SN/A    tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE));
2152632Sstever@eecs.umich.edu}
2162632Sstever@eecs.umich.edu
217955SN/Avoid
218955SN/AInterruptFault::invoke(ThreadContext *tc, StaticInstPtr inst)
219955SN/A{
220955SN/A    DPRINTF(MipsPRA, "%s encountered.\n", name());
2215863Snate@binkert.org    setExceptionState(tc, 0x0A);
222955SN/A
2232632Sstever@eecs.umich.edu    CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE);
2242632Sstever@eecs.umich.edu    if (cause.iv) {
2252632Sstever@eecs.umich.edu        // Offset 200 for release 2
2262632Sstever@eecs.umich.edu        tc->pcState(0x20 + vect() + tc->readMiscRegNoEffect(MISCREG_EBASE));
2272632Sstever@eecs.umich.edu    } else {
2282632Sstever@eecs.umich.edu        //Ofset at 180 for release 1
2292632Sstever@eecs.umich.edu        tc->pcState(vect() + tc->readMiscRegNoEffect(MISCREG_EBASE));
2302632Sstever@eecs.umich.edu    }
2312632Sstever@eecs.umich.edu}
2322632Sstever@eecs.umich.edu
2332632Sstever@eecs.umich.edu#endif // FULL_SYSTEM
2342632Sstever@eecs.umich.edu
2352632Sstever@eecs.umich.eduvoid
2363718Sstever@eecs.umich.eduResetFault::invoke(ThreadContext *tc, StaticInstPtr inst)
2373718Sstever@eecs.umich.edu{
2383718Sstever@eecs.umich.edu#if FULL_SYSTEM
2393718Sstever@eecs.umich.edu    DPRINTF(MipsPRA, "%s encountered.\n", name());
2403718Sstever@eecs.umich.edu    /* All reset activity must be invoked from here */
2415863Snate@binkert.org    tc->pcState(vect());
2425863Snate@binkert.org    DPRINTF(MipsPRA, "ResetFault::invoke : PC set to %x", tc->readPC());
2433718Sstever@eecs.umich.edu#endif
2443718Sstever@eecs.umich.edu
2456121Snate@binkert.org    // Set Coprocessor 1 (Floating Point) To Usable
2465863Snate@binkert.org    StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS);
2473718Sstever@eecs.umich.edu    status.cu.cu1 = 1;
2483718Sstever@eecs.umich.edu    tc->setMiscReg(MISCREG_STATUS, status);
2492634Sstever@eecs.umich.edu}
2502634Sstever@eecs.umich.edu
2515863Snate@binkert.orgvoid
2522638Sstever@eecs.umich.eduReservedInstructionFault::invoke(ThreadContext *tc, StaticInstPtr inst)
2532632Sstever@eecs.umich.edu{
2542632Sstever@eecs.umich.edu#if  FULL_SYSTEM
2552632Sstever@eecs.umich.edu    DPRINTF(MipsPRA, "%s encountered.\n", name());
2562632Sstever@eecs.umich.edu    setExceptionState(tc, 0x0A);
2572632Sstever@eecs.umich.edu    tc->pcState(vect() + tc->readMiscRegNoEffect(MISCREG_EBASE));
2582632Sstever@eecs.umich.edu#else
2591858SN/A    panic("%s encountered.\n", name());
2603716Sstever@eecs.umich.edu#endif
2612638Sstever@eecs.umich.edu}
2622638Sstever@eecs.umich.edu
2632638Sstever@eecs.umich.eduvoid
2642638Sstever@eecs.umich.eduThreadFault::invoke(ThreadContext *tc, StaticInstPtr inst)
2652638Sstever@eecs.umich.edu{
2662638Sstever@eecs.umich.edu    DPRINTF(MipsPRA, "%s encountered.\n", name());
2672638Sstever@eecs.umich.edu    panic("%s encountered.\n", name());
2685863Snate@binkert.org}
2695863Snate@binkert.org
2705863Snate@binkert.orgvoid
271955SN/ADspStateDisabledFault::invoke(ThreadContext *tc, StaticInstPtr inst)
2725341Sstever@gmail.com{
2735341Sstever@gmail.com    DPRINTF(MipsPRA, "%s encountered.\n", name());
2745863Snate@binkert.org    panic("%s encountered.\n", name());
2755341Sstever@gmail.com}
2766121Snate@binkert.org
2774494Ssaidi@eecs.umich.eduvoid
2786121Snate@binkert.orgCoprocessorUnusableFault::invoke(ThreadContext *tc, StaticInstPtr inst)
2791105SN/A{
2802667Sstever@eecs.umich.edu#if FULL_SYSTEM
2812667Sstever@eecs.umich.edu    DPRINTF(MipsPRA, "%s encountered.\n", name());
2822667Sstever@eecs.umich.edu    setExceptionState(tc, 0xb);
2832667Sstever@eecs.umich.edu    // The ID of the coprocessor causing the exception is stored in
2846121Snate@binkert.org    // CoprocessorUnusableFault::coProcID
2852667Sstever@eecs.umich.edu    CauseReg cause = tc->readMiscReg(MISCREG_CAUSE);
2865341Sstever@gmail.com    cause.ce = coProcID;
2875863Snate@binkert.org    tc->setMiscRegNoEffect(MISCREG_CAUSE, cause);
2885341Sstever@gmail.com    tc->pcState(vect() + tc->readMiscReg(MISCREG_EBASE));
2895341Sstever@gmail.com#else
2905341Sstever@gmail.com    warn("%s (CP%d) encountered.\n", name(), coProcID);
2915863Snate@binkert.org#endif
2925341Sstever@gmail.com}
2935341Sstever@gmail.com
2945341Sstever@gmail.com} // namespace MipsISA
2955863Snate@binkert.org
2965341Sstever@gmail.com