faults.cc revision 8063
12SN/A/*
21762SN/A * Copyright (c) 2010 ARM Limited
32SN/A * All rights reserved
42SN/A *
52SN/A * The license below extends only to copyright in the software and shall
62SN/A * not be construed as granting a license to any other intellectual
72SN/A * property including but not limited to intellectual property relating
82SN/A * to a hardware implementation of the functionality of the software
92SN/A * licensed hereunder.  You may use the software subject to the license
102SN/A * terms below provided that you ensure that this notice is replicated
112SN/A * unmodified and in its entirety in all distributions of the software,
122SN/A * modified or unmodified, in source code or in binary form.
132SN/A *
142SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
152SN/A * Copyright (c) 2007-2008 The Florida State University
162SN/A * All rights reserved.
172SN/A *
182SN/A * Redistribution and use in source and binary forms, with or without
192SN/A * modification, are permitted provided that the following conditions are
202SN/A * met: redistributions of source code must retain the above copyright
212SN/A * notice, this list of conditions and the following disclaimer;
222SN/A * redistributions in binary form must reproduce the above copyright
232SN/A * notice, this list of conditions and the following disclaimer in the
242SN/A * documentation and/or other materials provided with the distribution;
252SN/A * neither the name of the copyright holders nor the names of its
262SN/A * contributors may be used to endorse or promote products derived from
272665SN/A * this software without specific prior written permission.
282665SN/A *
292665SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
302SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
322SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
332SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
341298SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
351298SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
361259SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
382SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39146SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40146SN/A *
417632SBrad.Beckmann@amd.com * Authors: Ali Saidi
423348SN/A *          Gabe Black
433348SN/A */
443348SN/A
453348SN/A#include "arch/arm/faults.hh"
4656SN/A#include "cpu/thread_context.hh"
47695SN/A#include "cpu/base.hh"
482SN/A#include "base/trace.hh"
492SN/A
502SN/Anamespace ArmISA
511298SN/A{
521298SN/A
533187SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals =
543349SN/A    {"reset", 0x00, MODE_SVC, 0, 0, true, true};
553187SN/A
564898SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals =
574898SN/A    {"Undefined Instruction", 0x04, MODE_UNDEFINED, 4 ,2, false, false} ;
584898SN/A
594898SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals =
604898SN/A    {"Supervisor Call", 0x08, MODE_SVC, 4, 2, false, false};
614898SN/A
624898SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals =
633187SN/A    {"Prefetch Abort", 0x0C, MODE_ABORT, 4, 4, true, false};
643187SN/A
653187SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals =
663187SN/A    {"Data Abort", 0x10, MODE_ABORT, 8, 8, true, false};
673349SN/A
683187SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals =
694895SN/A    {"IRQ", 0x18, MODE_IRQ, 4, 4, true, false};
704895SN/A
714895SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals =
723187SN/A    {"FIQ", 0x1C, MODE_FIQ, 4, 4, true, true};
733187SN/A
743187SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<FlushPipe>::vals =
753187SN/A    {"Pipe Flush", 0x00, MODE_SVC, 0, 0, true, true}; // some dummy values
763349SN/A
773187SN/AAddr
783204SN/AArmFault::getVector(ThreadContext *tc)
793340SN/A{
803340SN/A    // ARM ARM B1-3
813262SN/A
823204SN/A    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
833187SN/A
843187SN/A    // panic if SCTLR.VE because I have no idea what to do with vectored
853187SN/A    // interrupts
863187SN/A    assert(!sctlr.ve);
873187SN/A
883647SN/A    if (!sctlr.v)
893647SN/A        return offset();
903647SN/A    return offset() + HighVecs;
913647SN/A
923647SN/A}
933187SN/A
943647SN/A#if FULL_SYSTEM
953187SN/A
963187SN/Avoid
973187SN/AArmFault::invoke(ThreadContext *tc, StaticInstPtr inst)
983187SN/A{
993187SN/A    // ARM ARM B1.6.3
1003187SN/A    FaultBase::invoke(tc);
1013187SN/A    countStat()++;
1023187SN/A
1033187SN/A    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
1043187SN/A    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
1053262SN/A    CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR) |
1063349SN/A                      tc->readIntReg(INTREG_CONDCODES);
1073262SN/A    Addr curPc M5_VAR_USED = tc->pcState().pc();
1083262SN/A
1093262SN/A
1103262SN/A    cpsr.mode = nextMode();
1113262SN/A    cpsr.it1 = cpsr.it2 = 0;
1127544SN/A    cpsr.j = 0;
1137544SN/A
1147544SN/A    cpsr.t = sctlr.te;
1157544SN/A    cpsr.a = cpsr.a | abortDisable();
1167544SN/A    cpsr.f = cpsr.f | fiqDisable();
1177544SN/A    cpsr.i = 1;
1187544SN/A    cpsr.e = sctlr.ee;
1197544SN/A    tc->setMiscReg(MISCREG_CPSR, cpsr);
1203262SN/A    tc->setIntReg(INTREG_LR, curPc +
1213262SN/A            (saved_cpsr.t ? thumbPcOffset() : armPcOffset()));
1227544SN/A
1237544SN/A    switch (nextMode()) {
1247544SN/A      case MODE_FIQ:
1257544SN/A        tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
1263262SN/A        break;
1273262SN/A      case MODE_IRQ:
1283262SN/A        tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
1293262SN/A        break;
1305034SN/A      case MODE_SVC:
1315034SN/A        tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
1322SN/A        break;
1333187SN/A      case MODE_UNDEFINED:
1343187SN/A        tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
1353187SN/A        break;
1363187SN/A      case MODE_ABORT:
1373187SN/A        tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
1385034SN/A        break;
1395034SN/A      default:
1405034SN/A        panic("unknown Mode\n");
1415034SN/A    }
1427544SN/A
1435034SN/A    Addr newPc = getVector(tc);
1445034SN/A    DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n",
1455034SN/A            name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc);
1465034SN/A    PCState pc(newPc);
1475034SN/A    pc.thumb(cpsr.t);
1485034SN/A    pc.nextThumb(pc.thumb());
1492SN/A    pc.jazelle(cpsr.j);
1507544SN/A    pc.nextJazelle(pc.jazelle());
1512SN/A    tc->pcState(pc);
1522SN/A}
1532SN/A
1543187SN/Avoid
1552SN/AReset::invoke(ThreadContext *tc, StaticInstPtr inst)
1562SN/A{
1573647SN/A    tc->getCpuPtr()->clearInterrupts();
1583647SN/A    tc->clearArchRegs();
1593647SN/A    ArmFault::invoke(tc);
1607544SN/A}
1617544SN/A
1623187SN/A#else
1635034SN/A
1642SN/Avoid
1652SN/AUndefinedInstruction::invoke(ThreadContext *tc, StaticInstPtr inst)
1662SN/A{
1672SN/A    // If the mnemonic isn't defined this has to be an unknown instruction.
1682SN/A    assert(unknown || mnemonic != NULL);
1692SN/A    if (disabled) {
1702SN/A        panic("Attempted to execute disabled instruction "
1715606SN/A                "'%s' (inst 0x%08x)", mnemonic, machInst);
1721298SN/A    } else if (unknown) {
1733187SN/A        panic("Attempted to execute unknown instruction (inst 0x%08x)",
1747544SN/A              machInst);
1753187SN/A    } else {
1763187SN/A        panic("Attempted to execute unimplemented instruction "
1773187SN/A                "'%s' (inst 0x%08x)", mnemonic, machInst);
1783187SN/A    }
1793187SN/A}
1803187SN/A
1813187SN/Avoid
1823187SN/ASupervisorCall::invoke(ThreadContext *tc, StaticInstPtr inst)
1833187SN/A{
1843187SN/A    // As of now, there isn't a 32 bit thumb version of this instruction.
1853187SN/A    assert(!machInst.bigThumb);
1863187SN/A    uint32_t callNum;
1873187SN/A    callNum = tc->readIntReg(INTREG_R7);
1883187SN/A    tc->syscall(callNum);
1893187SN/A
1903187SN/A    // Advance the PC since that won't happen automatically.
1913187SN/A    PCState pc = tc->pcState();
1923187SN/A    assert(inst);
1933187SN/A    inst->advancePC(pc);
1943187SN/A    tc->pcState(pc);
1953187SN/A}
1964579SN/A
1974579SN/A#endif // FULL_SYSTEM
1982SN/A
1992SN/Atemplate<class T>
2002SN/Avoid
2012SN/AAbortFault<T>::invoke(ThreadContext *tc, StaticInstPtr inst)
2023349SN/A{
2032SN/A    ArmFaultVals<T>::invoke(tc);
2044628SN/A    FSR fsr = 0;
2054628SN/A    fsr.fsLow = bits(status, 3, 0);
2067544SN/A    fsr.fsHigh = bits(status, 4);
2077544SN/A    fsr.domain = domain;
2087544SN/A    fsr.wnr = (write ? 1 : 0);
2097544SN/A    fsr.ext = 0;
2104628SN/A    tc->setMiscReg(T::FsrIndex, fsr);
2114628SN/A    tc->setMiscReg(T::FarIndex, faultAddr);
2124628SN/A}
2134628SN/A
2143187SN/Avoid
2153187SN/AFlushPipe::invoke(ThreadContext *tc, StaticInstPtr inst) {
2163187SN/A    DPRINTF(Faults, "Invoking FlushPipe Fault\n");
2173187SN/A
2183187SN/A    // Set the PC to the next instruction of the faulting instruction.
2193187SN/A    // Net effect is simply squashing all instructions behind and
2201298SN/A    // start refetching from the next instruction.
2214628SN/A    PCState pc = tc->pcState();
2224628SN/A    assert(inst);
2231298SN/A    inst->advancePC(pc);
2241298SN/A    tc->pcState(pc);
2251298SN/A}
2265319SN/A
2273187SN/Atemplate void AbortFault<PrefetchAbort>::invoke(ThreadContext *tc,
2284626SN/A                                                StaticInstPtr inst);
2294626SN/Atemplate void AbortFault<DataAbort>::invoke(ThreadContext *tc,
2304626SN/A                                            StaticInstPtr inst);
2314626SN/A
2322SN/A// return via SUBS pc, lr, xxx; rfe, movs, ldm
2332SN/A
2342SN/A} // namespace ArmISA
235695SN/A