faults.cc revision 13896:5a827a65bd1d
1/*
2 * Copyright (c) 2010, 2012-2014, 2016-2018 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2003-2005 The Regents of The University of Michigan
15 * Copyright (c) 2007-2008 The Florida State University
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Ali Saidi
42 *          Gabe Black
43 *          Giacomo Gabrielli
44 *          Thomas Grocutt
45 */
46
47#include "arch/arm/faults.hh"
48
49#include "arch/arm/insts/static_inst.hh"
50#include "arch/arm/system.hh"
51#include "arch/arm/utility.hh"
52#include "base/compiler.hh"
53#include "base/trace.hh"
54#include "cpu/base.hh"
55#include "cpu/thread_context.hh"
56#include "debug/Faults.hh"
57#include "sim/full_system.hh"
58
59namespace ArmISA
60{
61
62uint8_t ArmFault::shortDescFaultSources[] = {
63    0x01,  // AlignmentFault
64    0x04,  // InstructionCacheMaintenance
65    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
66    0x0c,  // SynchExtAbtOnTranslTableWalkL1
67    0x0e,  // SynchExtAbtOnTranslTableWalkL2
68    0xff,  // SynchExtAbtOnTranslTableWalkL3 (INVALID)
69    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
70    0x1c,  // SynchPtyErrOnTranslTableWalkL1
71    0x1e,  // SynchPtyErrOnTranslTableWalkL2
72    0xff,  // SynchPtyErrOnTranslTableWalkL3 (INVALID)
73    0xff,  // TranslationL0 (INVALID)
74    0x05,  // TranslationL1
75    0x07,  // TranslationL2
76    0xff,  // TranslationL3 (INVALID)
77    0xff,  // AccessFlagL0 (INVALID)
78    0x03,  // AccessFlagL1
79    0x06,  // AccessFlagL2
80    0xff,  // AccessFlagL3 (INVALID)
81    0xff,  // DomainL0 (INVALID)
82    0x09,  // DomainL1
83    0x0b,  // DomainL2
84    0xff,  // DomainL3 (INVALID)
85    0xff,  // PermissionL0 (INVALID)
86    0x0d,  // PermissionL1
87    0x0f,  // PermissionL2
88    0xff,  // PermissionL3 (INVALID)
89    0x02,  // DebugEvent
90    0x08,  // SynchronousExternalAbort
91    0x10,  // TLBConflictAbort
92    0x19,  // SynchPtyErrOnMemoryAccess
93    0x16,  // AsynchronousExternalAbort
94    0x18,  // AsynchPtyErrOnMemoryAccess
95    0xff,  // AddressSizeL0 (INVALID)
96    0xff,  // AddressSizeL1 (INVALID)
97    0xff,  // AddressSizeL2 (INVALID)
98    0xff,  // AddressSizeL3 (INVALID)
99    0x40,  // PrefetchTLBMiss
100    0x80   // PrefetchUncacheable
101};
102
103static_assert(sizeof(ArmFault::shortDescFaultSources) ==
104              ArmFault::NumFaultSources,
105              "Invalid size of ArmFault::shortDescFaultSources[]");
106
107uint8_t ArmFault::longDescFaultSources[] = {
108    0x21,  // AlignmentFault
109    0xff,  // InstructionCacheMaintenance (INVALID)
110    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
111    0x15,  // SynchExtAbtOnTranslTableWalkL1
112    0x16,  // SynchExtAbtOnTranslTableWalkL2
113    0x17,  // SynchExtAbtOnTranslTableWalkL3
114    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
115    0x1d,  // SynchPtyErrOnTranslTableWalkL1
116    0x1e,  // SynchPtyErrOnTranslTableWalkL2
117    0x1f,  // SynchPtyErrOnTranslTableWalkL3
118    0xff,  // TranslationL0 (INVALID)
119    0x05,  // TranslationL1
120    0x06,  // TranslationL2
121    0x07,  // TranslationL3
122    0xff,  // AccessFlagL0 (INVALID)
123    0x09,  // AccessFlagL1
124    0x0a,  // AccessFlagL2
125    0x0b,  // AccessFlagL3
126    0xff,  // DomainL0 (INVALID)
127    0x3d,  // DomainL1
128    0x3e,  // DomainL2
129    0xff,  // DomainL3 (RESERVED)
130    0xff,  // PermissionL0 (INVALID)
131    0x0d,  // PermissionL1
132    0x0e,  // PermissionL2
133    0x0f,  // PermissionL3
134    0x22,  // DebugEvent
135    0x10,  // SynchronousExternalAbort
136    0x30,  // TLBConflictAbort
137    0x18,  // SynchPtyErrOnMemoryAccess
138    0x11,  // AsynchronousExternalAbort
139    0x19,  // AsynchPtyErrOnMemoryAccess
140    0xff,  // AddressSizeL0 (INVALID)
141    0xff,  // AddressSizeL1 (INVALID)
142    0xff,  // AddressSizeL2 (INVALID)
143    0xff,  // AddressSizeL3 (INVALID)
144    0x40,  // PrefetchTLBMiss
145    0x80   // PrefetchUncacheable
146};
147
148static_assert(sizeof(ArmFault::longDescFaultSources) ==
149              ArmFault::NumFaultSources,
150              "Invalid size of ArmFault::longDescFaultSources[]");
151
152uint8_t ArmFault::aarch64FaultSources[] = {
153    0x21,  // AlignmentFault
154    0xff,  // InstructionCacheMaintenance (INVALID)
155    0x14,  // SynchExtAbtOnTranslTableWalkL0
156    0x15,  // SynchExtAbtOnTranslTableWalkL1
157    0x16,  // SynchExtAbtOnTranslTableWalkL2
158    0x17,  // SynchExtAbtOnTranslTableWalkL3
159    0x1c,  // SynchPtyErrOnTranslTableWalkL0
160    0x1d,  // SynchPtyErrOnTranslTableWalkL1
161    0x1e,  // SynchPtyErrOnTranslTableWalkL2
162    0x1f,  // SynchPtyErrOnTranslTableWalkL3
163    0x04,  // TranslationL0
164    0x05,  // TranslationL1
165    0x06,  // TranslationL2
166    0x07,  // TranslationL3
167    0x08,  // AccessFlagL0
168    0x09,  // AccessFlagL1
169    0x0a,  // AccessFlagL2
170    0x0b,  // AccessFlagL3
171    // @todo: Section & Page Domain Fault in AArch64?
172    0xff,  // DomainL0 (INVALID)
173    0xff,  // DomainL1 (INVALID)
174    0xff,  // DomainL2 (INVALID)
175    0xff,  // DomainL3 (INVALID)
176    0x0c,  // PermissionL0
177    0x0d,  // PermissionL1
178    0x0e,  // PermissionL2
179    0x0f,  // PermissionL3
180    0x22,  // DebugEvent
181    0x10,  // SynchronousExternalAbort
182    0x30,  // TLBConflictAbort
183    0x18,  // SynchPtyErrOnMemoryAccess
184    0xff,  // AsynchronousExternalAbort (INVALID)
185    0xff,  // AsynchPtyErrOnMemoryAccess (INVALID)
186    0x00,  // AddressSizeL0
187    0x01,  // AddressSizeL1
188    0x02,  // AddressSizeL2
189    0x03,  // AddressSizeL3
190    0x40,  // PrefetchTLBMiss
191    0x80   // PrefetchUncacheable
192};
193
194static_assert(sizeof(ArmFault::aarch64FaultSources) ==
195              ArmFault::NumFaultSources,
196              "Invalid size of ArmFault::aarch64FaultSources[]");
197
198// Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode,
199//         {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap,
200//         {A, F} disable, class, stat
201template<> ArmFault::FaultVals ArmFaultVals<Reset>::vals(
202    // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED
203    // location in AArch64)
204    "Reset",                 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
205    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN
206);
207template<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals(
208    "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
209    4, 2, 0, 0, true,  false, false, EC_UNKNOWN
210);
211template<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals(
212    "Supervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
213    4, 2, 4, 2, true,  false, false, EC_SVC_TO_HYP
214);
215template<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals(
216    "Secure Monitor Call",   0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON,
217    4, 4, 4, 4, false, true,  true,  EC_SMC_TO_HYP
218);
219template<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals(
220    "Hypervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
221    4, 4, 4, 4, true,  false, false, EC_HVC
222);
223template<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals(
224    "Prefetch Abort",        0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
225    4, 4, 0, 0, true,  true,  false, EC_PREFETCH_ABORT_TO_HYP
226);
227template<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals(
228    "Data Abort",            0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
229    8, 8, 0, 0, true,  true,  false, EC_DATA_ABORT_TO_HYP
230);
231template<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals(
232    "Virtual Data Abort",    0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
233    8, 8, 0, 0, true,  true,  false, EC_INVALID
234);
235template<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals(
236    // @todo: double check these values
237    "Hypervisor Trap",       0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
238    0, 0, 0, 0, false, false, false, EC_UNKNOWN
239);
240template<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals(
241    "Secure Monitor Trap",   0x004, 0x000, 0x200, 0x400, 0x600, MODE_MON,
242    4, 2, 0, 0, false, false, false, EC_UNKNOWN
243);
244template<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals(
245    "IRQ",                   0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
246    4, 4, 0, 0, false, true,  false, EC_UNKNOWN
247);
248template<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals(
249    "Virtual IRQ",           0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
250    4, 4, 0, 0, false, true,  false, EC_INVALID
251);
252template<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals(
253    "FIQ",                   0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
254    4, 4, 0, 0, false, true,  true,  EC_UNKNOWN
255);
256template<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals(
257    "Virtual FIQ",           0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
258    4, 4, 0, 0, false, true,  true,  EC_INVALID
259);
260template<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals(
261    "Illegal Inst Set State Fault",   0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
262    4, 2, 0, 0, true, false, false, EC_ILLEGAL_INST
263);
264template<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals(
265    // Some dummy values (SupervisorTrap is AArch64-only)
266    "Supervisor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
267    0, 0, 0, 0, false, false, false, EC_UNKNOWN
268);
269template<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals(
270    // Some dummy values (PCAlignmentFault is AArch64-only)
271    "PC Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
272    0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT
273);
274template<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals(
275    // Some dummy values (SPAlignmentFault is AArch64-only)
276    "SP Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
277    0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT
278);
279template<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals(
280    // Some dummy values (SError is AArch64-only)
281    "SError",                0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC,
282    0, 0, 0, 0, false, true,  true,  EC_SERROR
283);
284template<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals(
285    // Some dummy values (SoftwareBreakpoint is AArch64-only)
286    "Software Breakpoint",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
287    0, 0, 0, 0, true, false, false,  EC_SOFTWARE_BREAKPOINT
288);
289template<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals(
290    // Some dummy values
291    "ArmSev Flush",          0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
292    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN
293);
294
295Addr
296ArmFault::getVector(ThreadContext *tc)
297{
298    Addr base;
299
300    // Check for invalid modes
301    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
302    assert(ArmSystem::haveSecurity(tc) || cpsr.mode != MODE_MON);
303    assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
304
305    switch (cpsr.mode)
306    {
307      case MODE_MON:
308        base = tc->readMiscReg(MISCREG_MVBAR);
309        break;
310      case MODE_HYP:
311        base = tc->readMiscReg(MISCREG_HVBAR);
312        break;
313      default:
314        SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
315        if (sctlr.v) {
316            base = HighVecs;
317        } else {
318            base = ArmSystem::haveSecurity(tc) ?
319                tc->readMiscReg(MISCREG_VBAR) : 0;
320        }
321        break;
322    }
323
324    return base + offset(tc);
325}
326
327Addr
328ArmFault::getVector64(ThreadContext *tc)
329{
330    Addr vbar;
331    switch (toEL) {
332      case EL3:
333        assert(ArmSystem::haveSecurity(tc));
334        vbar = tc->readMiscReg(MISCREG_VBAR_EL3);
335        break;
336      case EL2:
337        assert(ArmSystem::haveVirtualization(tc));
338        vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
339        break;
340      case EL1:
341        vbar = tc->readMiscReg(MISCREG_VBAR_EL1);
342        break;
343      default:
344        panic("Invalid target exception level");
345        break;
346    }
347    return vbar + offset64(tc);
348}
349
350MiscRegIndex
351ArmFault::getSyndromeReg64() const
352{
353    switch (toEL) {
354      case EL1:
355        return MISCREG_ESR_EL1;
356      case EL2:
357        return MISCREG_ESR_EL2;
358      case EL3:
359        return MISCREG_ESR_EL3;
360      default:
361        panic("Invalid exception level");
362        break;
363    }
364}
365
366MiscRegIndex
367ArmFault::getFaultAddrReg64() const
368{
369    switch (toEL) {
370      case EL1:
371        return MISCREG_FAR_EL1;
372      case EL2:
373        return MISCREG_FAR_EL2;
374      case EL3:
375        return MISCREG_FAR_EL3;
376      default:
377        panic("Invalid exception level");
378        break;
379    }
380}
381
382void
383ArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
384{
385    uint32_t value;
386    uint32_t exc_class = (uint32_t) ec(tc);
387    uint32_t issVal = iss();
388
389    assert(!from64 || ArmSystem::highestELIs64(tc));
390
391    value = exc_class << 26;
392
393    // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24,
394    // 0x25) for which the ISS information is not valid (ARMv7).
395    // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not
396    // valid it is treated as RES1.
397    if (to64) {
398        value |= 1 << 25;
399    } else if ((bits(exc_class, 5, 3) != 4) ||
400               (bits(exc_class, 2) && bits(issVal, 24))) {
401        if (!machInst.thumb || machInst.bigThumb)
402            value |= 1 << 25;
403    }
404    // Condition code valid for EC[5:4] nonzero
405    if (!from64 && ((bits(exc_class, 5, 4) == 0) &&
406                    (bits(exc_class, 3, 0) != 0))) {
407        if (!machInst.thumb) {
408            uint32_t      cond;
409            ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode;
410            // If its on unconditional instruction report with a cond code of
411            // 0xE, ie the unconditional code
412            cond  = (condCode == COND_UC) ? COND_AL : condCode;
413            value |= cond << 20;
414            value |= 1    << 24;
415        }
416        value |= bits(issVal, 19, 0);
417    } else {
418        value |= issVal;
419    }
420    tc->setMiscReg(syndrome_reg, value);
421}
422
423void
424ArmFault::update(ThreadContext *tc)
425{
426    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
427
428    // Determine source exception level and mode
429    fromMode = (OperatingMode) (uint8_t) cpsr.mode;
430    fromEL = opModeToEL(fromMode);
431    if (opModeIs64(fromMode))
432        from64 = true;
433
434    // Determine target exception level (aarch64) or target execution
435    // mode (aarch32).
436    if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc)) {
437        toMode = MODE_MON;
438        toEL = EL3;
439    } else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc)) {
440        toMode = MODE_HYP;
441        toEL = EL2;
442        hypRouted = true;
443    } else {
444        toMode = nextMode();
445        toEL = opModeToEL(toMode);
446    }
447
448    if (fromEL > toEL)
449        toEL = fromEL;
450
451    to64 = ELIs64(tc, toEL);
452
453    // The fault specific informations have been updated; it is
454    // now possible to use them inside the fault.
455    faultUpdated = true;
456}
457
458void
459ArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
460{
461
462    // Update fault state informations, like the starting mode (aarch32)
463    // or EL (aarch64) and the ending mode or EL.
464    // From the update function we are also evaluating if the fault must
465    // be handled in AArch64 mode (to64).
466    update(tc);
467
468    if (to64) {
469        // Invoke exception handler in AArch64 state
470        invoke64(tc, inst);
471        return;
472    }
473
474    // ARMv7 (ARM ARM issue C B1.9)
475
476    bool have_security       = ArmSystem::haveSecurity(tc);
477
478    FaultBase::invoke(tc);
479    if (!FullSystem)
480        return;
481    countStat()++;
482
483    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
484    SCR scr = tc->readMiscReg(MISCREG_SCR);
485    CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR);
486    saved_cpsr.nz = tc->readCCReg(CCREG_NZ);
487    saved_cpsr.c = tc->readCCReg(CCREG_C);
488    saved_cpsr.v = tc->readCCReg(CCREG_V);
489    saved_cpsr.ge = tc->readCCReg(CCREG_GE);
490
491    Addr curPc M5_VAR_USED = tc->pcState().pc();
492    ITSTATE it = tc->pcState().itstate();
493    saved_cpsr.it2 = it.top6;
494    saved_cpsr.it1 = it.bottom2;
495
496    // if we have a valid instruction then use it to annotate this fault with
497    // extra information. This is used to generate the correct fault syndrome
498    // information
499    ArmStaticInst *arm_inst M5_VAR_USED = instrAnnotate(inst);
500
501    // Ensure Secure state if initially in Monitor mode
502    if (have_security && saved_cpsr.mode == MODE_MON) {
503        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
504        if (scr.ns) {
505            scr.ns = 0;
506            tc->setMiscRegNoEffect(MISCREG_SCR, scr);
507        }
508    }
509
510    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
511    cpsr.mode = toMode;
512
513    // some bits are set differently if we have been routed to hyp mode
514    if (cpsr.mode == MODE_HYP) {
515        SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR);
516        cpsr.t = hsctlr.te;
517        cpsr.e = hsctlr.ee;
518        if (!scr.ea)  {cpsr.a = 1;}
519        if (!scr.fiq) {cpsr.f = 1;}
520        if (!scr.irq) {cpsr.i = 1;}
521    } else if (cpsr.mode == MODE_MON) {
522        // Special case handling when entering monitor mode
523        cpsr.t = sctlr.te;
524        cpsr.e = sctlr.ee;
525        cpsr.a = 1;
526        cpsr.f = 1;
527        cpsr.i = 1;
528    } else {
529        cpsr.t = sctlr.te;
530        cpsr.e = sctlr.ee;
531
532        // The *Disable functions are virtual and different per fault
533        cpsr.a = cpsr.a | abortDisable(tc);
534        cpsr.f = cpsr.f | fiqDisable(tc);
535        cpsr.i = 1;
536    }
537    cpsr.it1 = cpsr.it2 = 0;
538    cpsr.j = 0;
539    tc->setMiscReg(MISCREG_CPSR, cpsr);
540
541    // Make sure mailbox sets to one always
542    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
543
544    // Clear the exclusive monitor
545    tc->setMiscReg(MISCREG_LOCKFLAG, 0);
546
547    if (cpsr.mode == MODE_HYP) {
548        tc->setMiscReg(MISCREG_ELR_HYP, curPc +
549                (saved_cpsr.t ? thumbPcOffset(true)  : armPcOffset(true)));
550    } else {
551        tc->setIntReg(INTREG_LR, curPc +
552                (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false)));
553    }
554
555    switch (cpsr.mode) {
556      case MODE_FIQ:
557        tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
558        break;
559      case MODE_IRQ:
560        tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
561        break;
562      case MODE_SVC:
563        tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
564        break;
565      case MODE_MON:
566        assert(have_security);
567        tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr);
568        break;
569      case MODE_ABORT:
570        tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
571        break;
572      case MODE_UNDEFINED:
573        tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
574        if (ec(tc) != EC_UNKNOWN)
575            setSyndrome(tc, MISCREG_HSR);
576        break;
577      case MODE_HYP:
578        assert(ArmSystem::haveVirtualization(tc));
579        tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr);
580        setSyndrome(tc, MISCREG_HSR);
581        break;
582      default:
583        panic("unknown Mode\n");
584    }
585
586    Addr newPc = getVector(tc);
587    DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x "
588            "%s\n", name(), cpsr, curPc, tc->readIntReg(INTREG_LR),
589            newPc, arm_inst ? csprintf("inst: %#x", arm_inst->encoding()) :
590            std::string());
591    PCState pc(newPc);
592    pc.thumb(cpsr.t);
593    pc.nextThumb(pc.thumb());
594    pc.jazelle(cpsr.j);
595    pc.nextJazelle(pc.jazelle());
596    pc.aarch64(!cpsr.width);
597    pc.nextAArch64(!cpsr.width);
598    pc.illegalExec(false);
599    tc->pcState(pc);
600}
601
602void
603ArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
604{
605    // Determine actual misc. register indices for ELR_ELx and SPSR_ELx
606    MiscRegIndex elr_idx, spsr_idx;
607    switch (toEL) {
608      case EL1:
609        elr_idx = MISCREG_ELR_EL1;
610        spsr_idx = MISCREG_SPSR_EL1;
611        break;
612      case EL2:
613        assert(ArmSystem::haveVirtualization(tc));
614        elr_idx = MISCREG_ELR_EL2;
615        spsr_idx = MISCREG_SPSR_EL2;
616        break;
617      case EL3:
618        assert(ArmSystem::haveSecurity(tc));
619        elr_idx = MISCREG_ELR_EL3;
620        spsr_idx = MISCREG_SPSR_EL3;
621        break;
622      default:
623        panic("Invalid target exception level");
624        break;
625    }
626
627    // Save process state into SPSR_ELx
628    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
629    CPSR spsr = cpsr;
630    spsr.nz = tc->readCCReg(CCREG_NZ);
631    spsr.c = tc->readCCReg(CCREG_C);
632    spsr.v = tc->readCCReg(CCREG_V);
633    if (from64) {
634        // Force some bitfields to 0
635        spsr.q = 0;
636        spsr.it1 = 0;
637        spsr.j = 0;
638        spsr.res0_23_22 = 0;
639        spsr.ge = 0;
640        spsr.it2 = 0;
641        spsr.t = 0;
642    } else {
643        spsr.ge = tc->readCCReg(CCREG_GE);
644        ITSTATE it = tc->pcState().itstate();
645        spsr.it2 = it.top6;
646        spsr.it1 = it.bottom2;
647        // Force some bitfields to 0
648        spsr.res0_23_22 = 0;
649        spsr.ss = 0;
650    }
651    tc->setMiscReg(spsr_idx, spsr);
652
653    // Save preferred return address into ELR_ELx
654    Addr curr_pc = tc->pcState().pc();
655    Addr ret_addr = curr_pc;
656    if (from64)
657        ret_addr += armPcElrOffset();
658    else
659        ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset();
660    tc->setMiscReg(elr_idx, ret_addr);
661
662    Addr vec_address = getVector64(tc);
663
664    // Update process state
665    OperatingMode64 mode = 0;
666    mode.spX = 1;
667    mode.el = toEL;
668    mode.width = 0;
669    cpsr.mode = mode;
670    cpsr.daif = 0xf;
671    cpsr.il = 0;
672    cpsr.ss = 0;
673    tc->setMiscReg(MISCREG_CPSR, cpsr);
674
675    // If we have a valid instruction then use it to annotate this fault with
676    // extra information. This is used to generate the correct fault syndrome
677    // information
678    ArmStaticInst *arm_inst M5_VAR_USED = instrAnnotate(inst);
679
680    // Set PC to start of exception handler
681    Addr new_pc = purifyTaggedAddr(vec_address, tc, toEL);
682    DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x "
683            "elr:%#x newVec: %#x %s\n", name(), cpsr, curr_pc, ret_addr,
684            new_pc, arm_inst ? csprintf("inst: %#x", arm_inst->encoding()) :
685            std::string());
686    PCState pc(new_pc);
687    pc.aarch64(!cpsr.width);
688    pc.nextAArch64(!cpsr.width);
689    pc.illegalExec(false);
690    tc->pcState(pc);
691
692    // Save exception syndrome
693    if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ))
694        setSyndrome(tc, getSyndromeReg64());
695}
696
697ArmStaticInst *
698ArmFault::instrAnnotate(const StaticInstPtr &inst)
699{
700    if (inst) {
701        auto arm_inst = static_cast<ArmStaticInst *>(inst.get());
702        arm_inst->annotateFault(this);
703        return arm_inst;
704    } else {
705        return nullptr;
706    }
707}
708
709Addr
710Reset::getVector(ThreadContext *tc)
711{
712    Addr base;
713
714    // Check for invalid modes
715    CPSR M5_VAR_USED cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
716    assert(ArmSystem::haveSecurity(tc) || cpsr.mode != MODE_MON);
717    assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
718
719    // RVBAR is aliased (implemented as) MVBAR in gem5, since the two
720    // are mutually exclusive; there is no need to check here for
721    // which register to use since they hold the same value
722    base = tc->readMiscReg(MISCREG_MVBAR);
723
724    return base + offset(tc);
725}
726
727void
728Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
729{
730    if (FullSystem) {
731        tc->getCpuPtr()->clearInterrupts(tc->threadId());
732        tc->clearArchRegs();
733    }
734    if (!ArmSystem::highestELIs64(tc)) {
735        ArmFault::invoke(tc, inst);
736        tc->setMiscReg(MISCREG_VMPIDR,
737                       getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc));
738
739        // Unless we have SMC code to get us there, boot in HYP!
740        if (ArmSystem::haveVirtualization(tc) &&
741            !ArmSystem::haveSecurity(tc)) {
742            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
743            cpsr.mode = MODE_HYP;
744            tc->setMiscReg(MISCREG_CPSR, cpsr);
745        }
746    } else {
747        // Advance the PC to the IMPLEMENTATION DEFINED reset value
748        PCState pc = ArmSystem::resetAddr(tc);
749        pc.aarch64(true);
750        pc.nextAArch64(true);
751        tc->pcState(pc);
752    }
753}
754
755void
756UndefinedInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
757{
758    if (FullSystem) {
759        ArmFault::invoke(tc, inst);
760        return;
761    }
762
763    // If the mnemonic isn't defined this has to be an unknown instruction.
764    assert(unknown || mnemonic != NULL);
765    auto arm_inst = static_cast<ArmStaticInst *>(inst.get());
766    if (disabled) {
767        panic("Attempted to execute disabled instruction "
768                "'%s' (inst 0x%08x)", mnemonic, arm_inst->encoding());
769    } else if (unknown) {
770        panic("Attempted to execute unknown instruction (inst 0x%08x)",
771              arm_inst->encoding());
772    } else {
773        panic("Attempted to execute unimplemented instruction "
774                "'%s' (inst 0x%08x)", mnemonic, arm_inst->encoding());
775    }
776}
777
778bool
779UndefinedInstruction::routeToHyp(ThreadContext *tc) const
780{
781    bool toHyp;
782
783    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
784    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
785    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
786
787    // if in Hyp mode then stay in Hyp mode
788    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
789    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
790    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
791    return toHyp;
792}
793
794uint32_t
795UndefinedInstruction::iss() const
796{
797
798    // If UndefinedInstruction is routed to hypervisor, iss field is 0.
799    if (hypRouted) {
800        return 0;
801    }
802
803    if (overrideEc == EC_INVALID)
804        return issRaw;
805
806    uint32_t new_iss = 0;
807    uint32_t op0, op1, op2, CRn, CRm, Rt, dir;
808
809    dir = bits(machInst, 21, 21);
810    op0 = bits(machInst, 20, 19);
811    op1 = bits(machInst, 18, 16);
812    CRn = bits(machInst, 15, 12);
813    CRm = bits(machInst, 11, 8);
814    op2 = bits(machInst, 7, 5);
815    Rt = bits(machInst, 4, 0);
816
817    new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 |
818            Rt << 5 | CRm << 1 | dir;
819
820    return new_iss;
821}
822
823void
824SupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
825{
826    if (FullSystem) {
827        ArmFault::invoke(tc, inst);
828        return;
829    }
830
831    // As of now, there isn't a 32 bit thumb version of this instruction.
832    assert(!machInst.bigThumb);
833    uint32_t callNum;
834    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
835    OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
836    if (opModeIs64(mode))
837        callNum = tc->readIntReg(INTREG_X8);
838    else
839        callNum = tc->readIntReg(INTREG_R7);
840    Fault fault;
841    tc->syscall(callNum, &fault);
842
843    // Advance the PC since that won't happen automatically.
844    PCState pc = tc->pcState();
845    assert(inst);
846    inst->advancePC(pc);
847    tc->pcState(pc);
848}
849
850bool
851SupervisorCall::routeToHyp(ThreadContext *tc) const
852{
853    bool toHyp;
854
855    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
856    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
857    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
858
859    // if in Hyp mode then stay in Hyp mode
860    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
861    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
862    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
863    return toHyp;
864}
865
866ExceptionClass
867SupervisorCall::ec(ThreadContext *tc) const
868{
869    return (overrideEc != EC_INVALID) ? overrideEc :
870        (from64 ? EC_SVC_64 : vals.ec);
871}
872
873uint32_t
874SupervisorCall::iss() const
875{
876    // Even if we have a 24 bit imm from an arm32 instruction then we only use
877    // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC).
878    return issRaw & 0xFFFF;
879}
880
881uint32_t
882SecureMonitorCall::iss() const
883{
884    if (from64)
885        return bits(machInst, 20, 5);
886    return 0;
887}
888
889ExceptionClass
890UndefinedInstruction::ec(ThreadContext *tc) const
891{
892    // If UndefinedInstruction is routed to hypervisor,
893    // HSR.EC field is 0.
894    if (hypRouted)
895        return EC_UNKNOWN;
896    else
897        return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
898}
899
900
901HypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) :
902        ArmFaultVals<HypervisorCall>(_machInst, _imm)
903{}
904
905ExceptionClass
906HypervisorCall::ec(ThreadContext *tc) const
907{
908    return from64 ? EC_HVC_64 : vals.ec;
909}
910
911ExceptionClass
912HypervisorTrap::ec(ThreadContext *tc) const
913{
914    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
915}
916
917template<class T>
918FaultOffset
919ArmFaultVals<T>::offset(ThreadContext *tc)
920{
921    bool isHypTrap = false;
922
923    // Normally we just use the exception vector from the table at the top if
924    // this file, however if this exception has caused a transition to hype
925    // mode, and its an exception type that would only do this if it has been
926    // trapped then we use the hyp trap vector instead of the normal vector
927    if (vals.hypTrappable) {
928        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
929        if (cpsr.mode == MODE_HYP) {
930            CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
931            isHypTrap = spsr.mode != MODE_HYP;
932        }
933    }
934    return isHypTrap ? 0x14 : vals.offset;
935}
936
937template<class T>
938FaultOffset
939ArmFaultVals<T>::offset64(ThreadContext *tc)
940{
941    if (toEL == fromEL) {
942        if (opModeIsT(fromMode))
943            return vals.currELTOffset;
944        return vals.currELHOffset;
945    } else {
946        bool lower_32 = false;
947        if (toEL == EL3) {
948            if (!inSecureState(tc) && ArmSystem::haveEL(tc, EL2))
949                lower_32 = ELIs32(tc, EL2);
950            else
951                lower_32 = ELIs32(tc, EL1);
952        } else {
953            lower_32 = ELIs32(tc, static_cast<ExceptionLevel>(toEL - 1));
954        }
955
956        if (lower_32)
957            return vals.lowerEL32Offset;
958        return vals.lowerEL64Offset;
959    }
960}
961
962// void
963// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx)
964// {
965//     ESR esr = 0;
966//     esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32;
967//     esr.il = !machInst.thumb;
968//     if (machInst.aarch64)
969//         esr.imm16 = bits(machInst.instBits, 20, 5);
970//     else if (machInst.thumb)
971//         esr.imm16 = bits(machInst.instBits, 7, 0);
972//     else
973//         esr.imm16 = bits(machInst.instBits, 15, 0);
974//     tc->setMiscReg(esr_idx, esr);
975// }
976
977void
978SecureMonitorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
979{
980    if (FullSystem) {
981        ArmFault::invoke(tc, inst);
982        return;
983    }
984}
985
986ExceptionClass
987SecureMonitorCall::ec(ThreadContext *tc) const
988{
989    return (from64 ? EC_SMC_64 : vals.ec);
990}
991
992bool
993SupervisorTrap::routeToHyp(ThreadContext *tc) const
994{
995    bool toHyp = false;
996
997    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
998    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
999    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1000
1001    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
1002    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.el == EL0);
1003    return toHyp;
1004}
1005
1006uint32_t
1007SupervisorTrap::iss() const
1008{
1009    // If SupervisorTrap is routed to hypervisor, iss field is 0.
1010    if (hypRouted) {
1011        return 0;
1012    }
1013    return issRaw;
1014}
1015
1016ExceptionClass
1017SupervisorTrap::ec(ThreadContext *tc) const
1018{
1019    if (hypRouted)
1020        return EC_UNKNOWN;
1021    else
1022        return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
1023}
1024
1025ExceptionClass
1026SecureMonitorTrap::ec(ThreadContext *tc) const
1027{
1028    return (overrideEc != EC_INVALID) ? overrideEc :
1029        (from64 ? EC_SMC_64 : vals.ec);
1030}
1031
1032template<class T>
1033void
1034AbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
1035{
1036    if (tranMethod == ArmFault::UnknownTran) {
1037        tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran
1038                                             : ArmFault::VmsaTran;
1039
1040        if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) {
1041            // See ARM ARM B3-1416
1042            bool override_LPAE = false;
1043            TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S);
1044            TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS);
1045            if (ttbcr_s.eae) {
1046                override_LPAE = true;
1047            } else {
1048                // Unimplemented code option, not seen in testing.  May need
1049                // extension according to the manual exceprt above.
1050                DPRINTF(Faults, "Warning: Incomplete translation method "
1051                        "override detected.\n");
1052            }
1053            if (override_LPAE)
1054                tranMethod = ArmFault::LpaeTran;
1055        }
1056    }
1057
1058    if (source == ArmFault::AsynchronousExternalAbort) {
1059        tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
1060    }
1061    // Get effective fault source encoding
1062    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
1063
1064    // source must be determined BEFORE invoking generic routines which will
1065    // try to set hsr etc. and are based upon source!
1066    ArmFaultVals<T>::invoke(tc, inst);
1067
1068    if (!this->to64) {  // AArch32
1069        FSR  fsr  = getFsr(tc);
1070        if (cpsr.mode == MODE_HYP) {
1071            tc->setMiscReg(T::HFarIndex, faultAddr);
1072        } else if (stage2) {
1073            tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf);
1074            tc->setMiscReg(T::HFarIndex,  OVAddr);
1075        } else {
1076            tc->setMiscReg(T::FsrIndex, fsr);
1077            tc->setMiscReg(T::FarIndex, faultAddr);
1078        }
1079        DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\
1080                "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod);
1081    } else {  // AArch64
1082        // Set the FAR register.  Nothing else to do if we are in AArch64 state
1083        // because the syndrome register has already been set inside invoke64()
1084        if (stage2) {
1085            // stage 2 fault, set HPFAR_EL2 to the faulting IPA
1086            // and FAR_EL2 to the Original VA
1087            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr);
1088            tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
1089
1090            DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
1091                    OVAddr, faultAddr);
1092        } else {
1093            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
1094        }
1095    }
1096}
1097
1098template<class T>
1099void
1100AbortFault<T>::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
1101{
1102    srcEncoded = getFaultStatusCode(tc);
1103    if (srcEncoded == ArmFault::FaultSourceInvalid) {
1104        panic("Invalid fault source\n");
1105    }
1106    ArmFault::setSyndrome(tc, syndrome_reg);
1107}
1108
1109template<class T>
1110uint8_t
1111AbortFault<T>::getFaultStatusCode(ThreadContext *tc) const
1112{
1113
1114    panic_if(!this->faultUpdated,
1115             "Trying to use un-updated ArmFault internal variables\n");
1116
1117    uint8_t fsc = 0;
1118
1119    if (!this->to64) {
1120        // AArch32
1121        assert(tranMethod != ArmFault::UnknownTran);
1122        if (tranMethod == ArmFault::LpaeTran) {
1123            fsc = ArmFault::longDescFaultSources[source];
1124        } else {
1125            fsc = ArmFault::shortDescFaultSources[source];
1126        }
1127    } else {
1128        // AArch64
1129        fsc = ArmFault::aarch64FaultSources[source];
1130    }
1131
1132    return fsc;
1133}
1134
1135template<class T>
1136FSR
1137AbortFault<T>::getFsr(ThreadContext *tc) const
1138{
1139    FSR fsr = 0;
1140
1141    auto fsc = getFaultStatusCode(tc);
1142
1143    // AArch32
1144    assert(tranMethod != ArmFault::UnknownTran);
1145    if (tranMethod == ArmFault::LpaeTran) {
1146        fsr.status = fsc;
1147        fsr.lpae   = 1;
1148    } else {
1149        fsr.fsLow  = bits(fsc, 3, 0);
1150        fsr.fsHigh = bits(fsc, 4);
1151        fsr.domain = static_cast<uint8_t>(domain);
1152    }
1153
1154    fsr.wnr = (write ? 1 : 0);
1155    fsr.ext = 0;
1156
1157    return fsr;
1158}
1159
1160template<class T>
1161bool
1162AbortFault<T>::abortDisable(ThreadContext *tc)
1163{
1164    if (ArmSystem::haveSecurity(tc)) {
1165        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1166        return (!scr.ns || scr.aw);
1167    }
1168    return true;
1169}
1170
1171template<class T>
1172void
1173AbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val)
1174{
1175    switch (id)
1176    {
1177      case ArmFault::S1PTW:
1178        s1ptw = val;
1179        break;
1180      case ArmFault::OVA:
1181        OVAddr = val;
1182        break;
1183
1184      // Just ignore unknown ID's
1185      default:
1186        break;
1187    }
1188}
1189
1190template<class T>
1191uint32_t
1192AbortFault<T>::iss() const
1193{
1194    uint32_t val;
1195
1196    val  = srcEncoded & 0x3F;
1197    val |= write << 6;
1198    val |= s1ptw << 7;
1199    return (val);
1200}
1201
1202template<class T>
1203bool
1204AbortFault<T>::isMMUFault() const
1205{
1206    // NOTE: Not relying on LL information being aligned to lowest bits here
1207    return
1208         (source == ArmFault::AlignmentFault)     ||
1209        ((source >= ArmFault::TranslationLL) &&
1210         (source <  ArmFault::TranslationLL + 4)) ||
1211        ((source >= ArmFault::AccessFlagLL) &&
1212         (source <  ArmFault::AccessFlagLL + 4))  ||
1213        ((source >= ArmFault::DomainLL) &&
1214         (source <  ArmFault::DomainLL + 4))      ||
1215        ((source >= ArmFault::PermissionLL) &&
1216         (source <  ArmFault::PermissionLL + 4));
1217}
1218
1219ExceptionClass
1220PrefetchAbort::ec(ThreadContext *tc) const
1221{
1222    if (to64) {
1223        // AArch64
1224        if (toEL == fromEL)
1225            return EC_PREFETCH_ABORT_CURR_EL;
1226        else
1227            return EC_PREFETCH_ABORT_LOWER_EL;
1228    } else {
1229        // AArch32
1230        // Abort faults have different EC codes depending on whether
1231        // the fault originated within HYP mode, or not. So override
1232        // the method and add the extra adjustment of the EC value.
1233
1234        ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec;
1235
1236        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
1237        if (spsr.mode == MODE_HYP) {
1238            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
1239        }
1240        return ec;
1241    }
1242}
1243
1244bool
1245PrefetchAbort::routeToMonitor(ThreadContext *tc) const
1246{
1247    SCR scr = 0;
1248    if (from64)
1249        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1250    else
1251        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1252
1253    return scr.ea && !isMMUFault();
1254}
1255
1256bool
1257PrefetchAbort::routeToHyp(ThreadContext *tc) const
1258{
1259    bool toHyp;
1260
1261    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1262    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1263    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1264    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
1265
1266    // if in Hyp mode then stay in Hyp mode
1267    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
1268    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
1269    toHyp |= (stage2 ||
1270                ( (source ==               DebugEvent) && hdcr.tde && (cpsr.mode !=  MODE_HYP)) ||
1271                ( (source == SynchronousExternalAbort) && hcr.tge  && (cpsr.mode == MODE_USER))
1272             ) && !inSecureState(tc);
1273    return toHyp;
1274}
1275
1276ExceptionClass
1277DataAbort::ec(ThreadContext *tc) const
1278{
1279    if (to64) {
1280        // AArch64
1281        if (source == ArmFault::AsynchronousExternalAbort) {
1282            panic("Asynchronous External Abort should be handled with "
1283                    "SystemErrors (SErrors)!");
1284        }
1285        if (toEL == fromEL)
1286            return EC_DATA_ABORT_CURR_EL;
1287        else
1288            return EC_DATA_ABORT_LOWER_EL;
1289    } else {
1290        // AArch32
1291        // Abort faults have different EC codes depending on whether
1292        // the fault originated within HYP mode, or not. So override
1293        // the method and add the extra adjustment of the EC value.
1294
1295        ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec;
1296
1297        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
1298        if (spsr.mode == MODE_HYP) {
1299            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
1300        }
1301        return ec;
1302    }
1303}
1304
1305bool
1306DataAbort::routeToMonitor(ThreadContext *tc) const
1307{
1308    SCR scr = 0;
1309    if (from64)
1310        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1311    else
1312        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1313
1314    return scr.ea && !isMMUFault();
1315}
1316
1317bool
1318DataAbort::routeToHyp(ThreadContext *tc) const
1319{
1320    bool toHyp;
1321
1322    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1323    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1324    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1325    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
1326
1327    // if in Hyp mode then stay in Hyp mode
1328    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
1329    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
1330    toHyp |= (stage2 ||
1331                ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) ||
1332                                               ((source == DebugEvent) && hdcr.tde) )
1333                ) ||
1334                ( (cpsr.mode == MODE_USER) && hcr.tge &&
1335                  ((source == AlignmentFault)            ||
1336                   (source == SynchronousExternalAbort))
1337                )
1338             ) && !inSecureState(tc);
1339    return toHyp;
1340}
1341
1342uint32_t
1343DataAbort::iss() const
1344{
1345    uint32_t val;
1346
1347    // Add on the data abort specific fields to the generic abort ISS value
1348    val  = AbortFault<DataAbort>::iss();
1349    // ISS is valid if not caused by a stage 1 page table walk, and when taken
1350    // to AArch64 only when directed to EL2
1351    if (!s1ptw && (!to64 || toEL == EL2)) {
1352        val |= isv << 24;
1353        if (isv) {
1354            val |= sas << 22;
1355            val |= sse << 21;
1356            val |= srt << 16;
1357            // AArch64 only. These assignments are safe on AArch32 as well
1358            // because these vars are initialized to false
1359            val |= sf << 15;
1360            val |= ar << 14;
1361        }
1362    }
1363    return (val);
1364}
1365
1366void
1367DataAbort::annotate(AnnotationIDs id, uint64_t val)
1368{
1369    AbortFault<DataAbort>::annotate(id, val);
1370    switch (id)
1371    {
1372      case SAS:
1373        isv = true;
1374        sas = val;
1375        break;
1376      case SSE:
1377        isv = true;
1378        sse = val;
1379        break;
1380      case SRT:
1381        isv = true;
1382        srt = val;
1383        break;
1384      case SF:
1385        isv = true;
1386        sf  = val;
1387        break;
1388      case AR:
1389        isv = true;
1390        ar  = val;
1391        break;
1392      // Just ignore unknown ID's
1393      default:
1394        break;
1395    }
1396}
1397
1398void
1399VirtualDataAbort::invoke(ThreadContext *tc, const StaticInstPtr &inst)
1400{
1401    AbortFault<VirtualDataAbort>::invoke(tc, inst);
1402    HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
1403    hcr.va = 0;
1404    tc->setMiscRegNoEffect(MISCREG_HCR, hcr);
1405}
1406
1407bool
1408Interrupt::routeToMonitor(ThreadContext *tc) const
1409{
1410    assert(ArmSystem::haveSecurity(tc));
1411    SCR scr = 0;
1412    if (from64)
1413        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1414    else
1415        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1416    return scr.irq;
1417}
1418
1419bool
1420Interrupt::routeToHyp(ThreadContext *tc) const
1421{
1422    bool toHyp;
1423
1424    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1425    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1426    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1427    // Determine whether IRQs are routed to Hyp mode.
1428    toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) ||
1429            (cpsr.mode == MODE_HYP);
1430    return toHyp;
1431}
1432
1433bool
1434Interrupt::abortDisable(ThreadContext *tc)
1435{
1436    if (ArmSystem::haveSecurity(tc)) {
1437        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1438        return (!scr.ns || scr.aw);
1439    }
1440    return true;
1441}
1442
1443VirtualInterrupt::VirtualInterrupt()
1444{}
1445
1446bool
1447FastInterrupt::routeToMonitor(ThreadContext *tc) const
1448{
1449    assert(ArmSystem::haveSecurity(tc));
1450    SCR scr = 0;
1451    if (from64)
1452        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1453    else
1454        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1455    return scr.fiq;
1456}
1457
1458bool
1459FastInterrupt::routeToHyp(ThreadContext *tc) const
1460{
1461    bool toHyp;
1462
1463    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1464    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1465    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1466    // Determine whether IRQs are routed to Hyp mode.
1467    toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) ||
1468            (cpsr.mode == MODE_HYP);
1469    return toHyp;
1470}
1471
1472bool
1473FastInterrupt::abortDisable(ThreadContext *tc)
1474{
1475    if (ArmSystem::haveSecurity(tc)) {
1476        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1477        return (!scr.ns || scr.aw);
1478    }
1479    return true;
1480}
1481
1482bool
1483FastInterrupt::fiqDisable(ThreadContext *tc)
1484{
1485    if (ArmSystem::haveVirtualization(tc)) {
1486        return true;
1487    } else if (ArmSystem::haveSecurity(tc)) {
1488        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1489        return (!scr.ns || scr.fw);
1490    }
1491    return true;
1492}
1493
1494VirtualFastInterrupt::VirtualFastInterrupt()
1495{}
1496
1497void
1498PCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
1499{
1500    ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
1501    assert(from64);
1502    // Set the FAR
1503    tc->setMiscReg(getFaultAddrReg64(), faultPC);
1504}
1505
1506bool
1507PCAlignmentFault::routeToHyp(ThreadContext *tc) const
1508{
1509    bool toHyp = false;
1510
1511    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1512    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
1513    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1514
1515    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
1516    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.el == EL0);
1517    return toHyp;
1518}
1519
1520SPAlignmentFault::SPAlignmentFault()
1521{}
1522
1523SystemError::SystemError()
1524{}
1525
1526void
1527SystemError::invoke(ThreadContext *tc, const StaticInstPtr &inst)
1528{
1529    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
1530    ArmFault::invoke(tc, inst);
1531}
1532
1533bool
1534SystemError::routeToMonitor(ThreadContext *tc) const
1535{
1536    assert(ArmSystem::haveSecurity(tc));
1537    assert(from64);
1538    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1539    return scr.ea;
1540}
1541
1542bool
1543SystemError::routeToHyp(ThreadContext *tc) const
1544{
1545    bool toHyp;
1546    assert(from64);
1547
1548    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1549    HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1550
1551    toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) ||
1552            (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc));
1553    return toHyp;
1554}
1555
1556
1557SoftwareBreakpoint::SoftwareBreakpoint(ExtMachInst _mach_inst, uint32_t _iss)
1558    : ArmFaultVals<SoftwareBreakpoint>(_mach_inst, _iss)
1559{}
1560
1561bool
1562SoftwareBreakpoint::routeToHyp(ThreadContext *tc) const
1563{
1564    const bool have_el2 = ArmSystem::haveVirtualization(tc);
1565
1566    const HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
1567    const HDCR mdcr  = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
1568
1569    return have_el2 && !inSecureState(tc) && fromEL <= EL1 &&
1570        (hcr.tge || mdcr.tde);
1571}
1572
1573ExceptionClass
1574SoftwareBreakpoint::ec(ThreadContext *tc) const
1575{
1576    return from64 ? EC_SOFTWARE_BREAKPOINT_64 : vals.ec;
1577}
1578
1579void
1580ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
1581    DPRINTF(Faults, "Invoking ArmSev Fault\n");
1582    if (!FullSystem)
1583        return;
1584
1585    // Set sev_mailbox to 1, clear the pending interrupt from remote
1586    // SEV execution and let pipeline continue as pcState is still
1587    // valid.
1588    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
1589    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0);
1590}
1591
1592// Instantiate all the templates to make the linker happy
1593template class ArmFaultVals<Reset>;
1594template class ArmFaultVals<UndefinedInstruction>;
1595template class ArmFaultVals<SupervisorCall>;
1596template class ArmFaultVals<SecureMonitorCall>;
1597template class ArmFaultVals<HypervisorCall>;
1598template class ArmFaultVals<PrefetchAbort>;
1599template class ArmFaultVals<DataAbort>;
1600template class ArmFaultVals<VirtualDataAbort>;
1601template class ArmFaultVals<HypervisorTrap>;
1602template class ArmFaultVals<Interrupt>;
1603template class ArmFaultVals<VirtualInterrupt>;
1604template class ArmFaultVals<FastInterrupt>;
1605template class ArmFaultVals<VirtualFastInterrupt>;
1606template class ArmFaultVals<SupervisorTrap>;
1607template class ArmFaultVals<SecureMonitorTrap>;
1608template class ArmFaultVals<PCAlignmentFault>;
1609template class ArmFaultVals<SPAlignmentFault>;
1610template class ArmFaultVals<SystemError>;
1611template class ArmFaultVals<SoftwareBreakpoint>;
1612template class ArmFaultVals<ArmSev>;
1613template class AbortFault<PrefetchAbort>;
1614template class AbortFault<DataAbort>;
1615template class AbortFault<VirtualDataAbort>;
1616
1617
1618IllegalInstSetStateFault::IllegalInstSetStateFault()
1619{}
1620
1621
1622} // namespace ArmISA
1623