faults.cc revision 7652
14166Sgblack@eecs.umich.edu/*
24166Sgblack@eecs.umich.edu * Copyright (c) 2010 ARM Limited
34166Sgblack@eecs.umich.edu * All rights reserved
44166Sgblack@eecs.umich.edu *
54166Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall
64166Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual
74166Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating
84166Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software
94166Sgblack@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
104166Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
114166Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
124166Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form.
134166Sgblack@eecs.umich.edu *
144166Sgblack@eecs.umich.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan
154166Sgblack@eecs.umich.edu * Copyright (c) 2007-2008 The Florida State University
164166Sgblack@eecs.umich.edu * All rights reserved.
174166Sgblack@eecs.umich.edu *
184166Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
194166Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
204166Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
214166Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
224166Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
234166Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
244166Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
254166Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
264166Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
274166Sgblack@eecs.umich.edu * this software without specific prior written permission.
284166Sgblack@eecs.umich.edu *
294166Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
304166Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
314166Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
324166Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
334166Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
344166Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
354166Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
364166Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
374166Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
384166Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
394166Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
404166Sgblack@eecs.umich.edu *
414166Sgblack@eecs.umich.edu * Authors: Ali Saidi
424166Sgblack@eecs.umich.edu *          Gabe Black
434166Sgblack@eecs.umich.edu */
444166Sgblack@eecs.umich.edu
454166Sgblack@eecs.umich.edu#include "arch/arm/faults.hh"
464166Sgblack@eecs.umich.edu#include "cpu/thread_context.hh"
474166Sgblack@eecs.umich.edu#include "cpu/base.hh"
484166Sgblack@eecs.umich.edu#include "base/trace.hh"
494166Sgblack@eecs.umich.edu
504166Sgblack@eecs.umich.edunamespace ArmISA
514166Sgblack@eecs.umich.edu{
524166Sgblack@eecs.umich.edu
534166Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals =
544166Sgblack@eecs.umich.edu    {"reset", 0x00, MODE_SVC, 0, 0, true, true};
554166Sgblack@eecs.umich.edu
564166Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals =
574166Sgblack@eecs.umich.edu    {"Undefined Instruction", 0x04, MODE_UNDEFINED, 4 ,2, false, false} ;
584166Sgblack@eecs.umich.edu
594166Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals =
604166Sgblack@eecs.umich.edu    {"Supervisor Call", 0x08, MODE_SVC, 4, 2, false, false};
614166Sgblack@eecs.umich.edu
624759Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals =
634166Sgblack@eecs.umich.edu    {"Prefetch Abort", 0x0C, MODE_ABORT, 4, 4, true, false};
644166Sgblack@eecs.umich.edu
654166Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals =
664166Sgblack@eecs.umich.edu    {"Data Abort", 0x10, MODE_ABORT, 8, 8, true, false};
674166Sgblack@eecs.umich.edu
684166Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals =
694166Sgblack@eecs.umich.edu    {"IRQ", 0x18, MODE_IRQ, 4, 4, true, false};
704166Sgblack@eecs.umich.edu
714166Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals =
724166Sgblack@eecs.umich.edu    {"FIQ", 0x1C, MODE_FIQ, 4, 4, true, true};
734166Sgblack@eecs.umich.edu
744166Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<FlushPipe>::vals =
754166Sgblack@eecs.umich.edu    {"Pipe Flush", 0x00, MODE_SVC, 0, 0, true, true}; // some dummy values
764166Sgblack@eecs.umich.edu
774166Sgblack@eecs.umich.eduAddr
784166Sgblack@eecs.umich.eduArmFault::getVector(ThreadContext *tc)
794166Sgblack@eecs.umich.edu{
804166Sgblack@eecs.umich.edu    // ARM ARM B1-3
814166Sgblack@eecs.umich.edu
824166Sgblack@eecs.umich.edu    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
834166Sgblack@eecs.umich.edu
844166Sgblack@eecs.umich.edu    // panic if SCTLR.VE because I have no idea what to do with vectored
854166Sgblack@eecs.umich.edu    // interrupts
864166Sgblack@eecs.umich.edu    assert(!sctlr.ve);
874166Sgblack@eecs.umich.edu
884166Sgblack@eecs.umich.edu    if (!sctlr.v)
894166Sgblack@eecs.umich.edu        return offset();
904166Sgblack@eecs.umich.edu    return offset() + HighVecs;
914166Sgblack@eecs.umich.edu
924166Sgblack@eecs.umich.edu}
934166Sgblack@eecs.umich.edu
944166Sgblack@eecs.umich.edu#if FULL_SYSTEM
954166Sgblack@eecs.umich.edu
964759Sgblack@eecs.umich.eduvoid
974759Sgblack@eecs.umich.eduArmFault::invoke(ThreadContext *tc)
984759Sgblack@eecs.umich.edu{
994166Sgblack@eecs.umich.edu    // ARM ARM B1.6.3
1005960Sgblack@eecs.umich.edu    FaultBase::invoke(tc);
1015960Sgblack@eecs.umich.edu    countStat()++;
1025960Sgblack@eecs.umich.edu
1035960Sgblack@eecs.umich.edu    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
1045960Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
1055960Sgblack@eecs.umich.edu    CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR) |
1065960Sgblack@eecs.umich.edu                      tc->readIntReg(INTREG_CONDCODES);
1075960Sgblack@eecs.umich.edu
1085960Sgblack@eecs.umich.edu
1095960Sgblack@eecs.umich.edu    cpsr.mode = nextMode();
1105960Sgblack@eecs.umich.edu    cpsr.it1 = cpsr.it2 = 0;
1115960Sgblack@eecs.umich.edu    cpsr.j = 0;
1125960Sgblack@eecs.umich.edu
1135960Sgblack@eecs.umich.edu    cpsr.t = sctlr.te;
1145960Sgblack@eecs.umich.edu    cpsr.a = cpsr.a | abortDisable();
1155960Sgblack@eecs.umich.edu    cpsr.f = cpsr.f | fiqDisable();
1165960Sgblack@eecs.umich.edu    cpsr.i = 1;
1175960Sgblack@eecs.umich.edu    cpsr.e = sctlr.ee;
1185960Sgblack@eecs.umich.edu    tc->setMiscReg(MISCREG_CPSR, cpsr);
1195960Sgblack@eecs.umich.edu    tc->setIntReg(INTREG_LR, tc->readPC() +
1205960Sgblack@eecs.umich.edu            (saved_cpsr.t ? thumbPcOffset() : armPcOffset()));
1215960Sgblack@eecs.umich.edu
1225960Sgblack@eecs.umich.edu    switch (nextMode()) {
1235960Sgblack@eecs.umich.edu      case MODE_FIQ:
1245960Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
1255960Sgblack@eecs.umich.edu        break;
1265960Sgblack@eecs.umich.edu      case MODE_IRQ:
1275960Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
1285960Sgblack@eecs.umich.edu        break;
1295960Sgblack@eecs.umich.edu      case MODE_SVC:
1305960Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
1315960Sgblack@eecs.umich.edu        break;
1325960Sgblack@eecs.umich.edu      case MODE_UNDEFINED:
1335960Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
1345960Sgblack@eecs.umich.edu        break;
1355960Sgblack@eecs.umich.edu      case MODE_ABORT:
1365960Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
1375960Sgblack@eecs.umich.edu        break;
1385960Sgblack@eecs.umich.edu      default:
139        panic("unknown Mode\n");
140    }
141
142    Addr pc M5_VAR_USED = tc->readPC();
143    Addr newPc = getVector(tc) | (sctlr.te ? (ULL(1) << PcTBitShift) : 0);
144    DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n",
145            name(), cpsr, pc, tc->readIntReg(INTREG_LR), newPc);
146    tc->setPC(newPc);
147    tc->setNextPC(newPc + cpsr.t ? 2 : 4 );
148    tc->setMicroPC(0);
149    tc->setNextMicroPC(1);
150}
151
152void
153Reset::invoke(ThreadContext *tc)
154{
155    tc->getCpuPtr()->clearInterrupts();
156    tc->clearArchRegs();
157    ArmFault::invoke(tc);
158}
159
160#else
161
162void
163UndefinedInstruction::invoke(ThreadContext *tc)
164{
165    // If the mnemonic isn't defined this has to be an unknown instruction.
166    assert(unknown || mnemonic != NULL);
167    if (disabled) {
168        panic("Attempted to execute disabled instruction "
169                "'%s' (inst 0x%08x)", mnemonic, machInst);
170    } else if (unknown) {
171        panic("Attempted to execute unknown instruction (inst 0x%08x)",
172              machInst);
173    } else {
174        panic("Attempted to execute unimplemented instruction "
175                "'%s' (inst 0x%08x)", mnemonic, machInst);
176    }
177}
178
179void
180SupervisorCall::invoke(ThreadContext *tc)
181{
182    // As of now, there isn't a 32 bit thumb version of this instruction.
183    assert(!machInst.bigThumb);
184    uint32_t callNum;
185    if (machInst.thumb) {
186        callNum = bits(machInst, 7, 0);
187    } else {
188        callNum = bits(machInst, 23, 0);
189    }
190    if (callNum == 0) {
191        callNum = tc->readIntReg(INTREG_R7);
192    }
193    tc->syscall(callNum);
194
195    // Advance the PC since that won't happen automatically.
196    tc->setPC(tc->readNextPC());
197    tc->setNextPC(tc->readNextNPC());
198    tc->setMicroPC(0);
199    tc->setNextMicroPC(1);
200}
201
202#endif // FULL_SYSTEM
203
204template<class T>
205void
206AbortFault<T>::invoke(ThreadContext *tc)
207{
208    ArmFaultVals<T>::invoke(tc);
209    FSR fsr = 0;
210    fsr.fsLow = bits(status, 3, 0);
211    fsr.fsHigh = bits(status, 4);
212    fsr.domain = domain;
213    fsr.wnr = (write ? 1 : 0);
214    fsr.ext = 0;
215    tc->setMiscReg(T::FsrIndex, fsr);
216    tc->setMiscReg(T::FarIndex, faultAddr);
217}
218
219void
220FlushPipe::invoke(ThreadContext *tc) {
221    DPRINTF(Faults, "Invoking FlushPipe Fault\n");
222
223    // Set the PC to the next instruction of the faulting instruction.
224    // Net effect is simply squashing all instructions behind and
225    // start refetching from the next instruction.
226    tc->setPC(tc->readNextPC());
227    tc->setNextPC(tc->readNextNPC());
228    tc->setMicroPC(0);
229    tc->setNextMicroPC(1);
230}
231
232template void AbortFault<PrefetchAbort>::invoke(ThreadContext *tc);
233template void AbortFault<DataAbort>::invoke(ThreadContext *tc);
234
235// return via SUBS pc, lr, xxx; rfe, movs, ldm
236
237} // namespace ArmISA
238