faults.cc revision 14171
12221SN/A/*
22221SN/A * Copyright (c) 2010, 2012-2014, 2016-2019 ARM Limited
32221SN/A * All rights reserved
42221SN/A *
52221SN/A * The license below extends only to copyright in the software and shall
62221SN/A * not be construed as granting a license to any other intellectual
72221SN/A * property including but not limited to intellectual property relating
82221SN/A * to a hardware implementation of the functionality of the software
92221SN/A * licensed hereunder.  You may use the software subject to the license
102221SN/A * terms below provided that you ensure that this notice is replicated
112221SN/A * unmodified and in its entirety in all distributions of the software,
122221SN/A * modified or unmodified, in source code or in binary form.
132221SN/A *
142221SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
152221SN/A * Copyright (c) 2007-2008 The Florida State University
162221SN/A * All rights reserved.
172221SN/A *
182221SN/A * Redistribution and use in source and binary forms, with or without
192221SN/A * modification, are permitted provided that the following conditions are
202221SN/A * met: redistributions of source code must retain the above copyright
212221SN/A * notice, this list of conditions and the following disclaimer;
222221SN/A * redistributions in binary form must reproduce the above copyright
232221SN/A * notice, this list of conditions and the following disclaimer in the
242221SN/A * documentation and/or other materials provided with the distribution;
252221SN/A * neither the name of the copyright holders nor the names of its
262221SN/A * contributors may be used to endorse or promote products derived from
272665Ssaidi@eecs.umich.edu * this software without specific prior written permission.
282665Ssaidi@eecs.umich.edu *
292665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
302221SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312221SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
323415Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
333415Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342223SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
353415Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
363578Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
373415Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
383415Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
393523Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
403415Sgblack@eecs.umich.edu *
412680Sktlim@umich.edu * Authors: Ali Saidi
422800Ssaidi@eecs.umich.edu *          Gabe Black
433523Sgblack@eecs.umich.edu *          Giacomo Gabrielli
443415Sgblack@eecs.umich.edu *          Thomas Grocutt
452800Ssaidi@eecs.umich.edu */
462800Ssaidi@eecs.umich.edu
472221SN/A#include "arch/arm/faults.hh"
483415Sgblack@eecs.umich.edu
493415Sgblack@eecs.umich.edu#include "arch/arm/insts/static_inst.hh"
502223SN/A#include "arch/arm/system.hh"
512221SN/A#include "arch/arm/utility.hh"
522221SN/A#include "base/compiler.hh"
533573Sgblack@eecs.umich.edu#include "base/trace.hh"
543576Sgblack@eecs.umich.edu#include "cpu/base.hh"
553576Sgblack@eecs.umich.edu#include "cpu/thread_context.hh"
562221SN/A#include "debug/Faults.hh"
573573Sgblack@eecs.umich.edu#include "sim/full_system.hh"
583576Sgblack@eecs.umich.edu
593576Sgblack@eecs.umich.edunamespace ArmISA
602221SN/A{
613573Sgblack@eecs.umich.edu
623576Sgblack@eecs.umich.eduuint8_t ArmFault::shortDescFaultSources[] = {
633576Sgblack@eecs.umich.edu    0x01,  // AlignmentFault
642221SN/A    0x04,  // InstructionCacheMaintenance
653573Sgblack@eecs.umich.edu    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
663576Sgblack@eecs.umich.edu    0x0c,  // SynchExtAbtOnTranslTableWalkL1
673576Sgblack@eecs.umich.edu    0x0e,  // SynchExtAbtOnTranslTableWalkL2
682221SN/A    0xff,  // SynchExtAbtOnTranslTableWalkL3 (INVALID)
693573Sgblack@eecs.umich.edu    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
703576Sgblack@eecs.umich.edu    0x1c,  // SynchPtyErrOnTranslTableWalkL1
713576Sgblack@eecs.umich.edu    0x1e,  // SynchPtyErrOnTranslTableWalkL2
722221SN/A    0xff,  // SynchPtyErrOnTranslTableWalkL3 (INVALID)
733573Sgblack@eecs.umich.edu    0xff,  // TranslationL0 (INVALID)
743576Sgblack@eecs.umich.edu    0x05,  // TranslationL1
753576Sgblack@eecs.umich.edu    0x07,  // TranslationL2
762221SN/A    0xff,  // TranslationL3 (INVALID)
773573Sgblack@eecs.umich.edu    0xff,  // AccessFlagL0 (INVALID)
783576Sgblack@eecs.umich.edu    0x03,  // AccessFlagL1
793576Sgblack@eecs.umich.edu    0x06,  // AccessFlagL2
803576Sgblack@eecs.umich.edu    0xff,  // AccessFlagL3 (INVALID)
813576Sgblack@eecs.umich.edu    0xff,  // DomainL0 (INVALID)
823576Sgblack@eecs.umich.edu    0x09,  // DomainL1
833576Sgblack@eecs.umich.edu    0x0b,  // DomainL2
843576Sgblack@eecs.umich.edu    0xff,  // DomainL3 (INVALID)
852221SN/A    0xff,  // PermissionL0 (INVALID)
863573Sgblack@eecs.umich.edu    0x0d,  // PermissionL1
873576Sgblack@eecs.umich.edu    0x0f,  // PermissionL2
883576Sgblack@eecs.umich.edu    0xff,  // PermissionL3 (INVALID)
892221SN/A    0x02,  // DebugEvent
903573Sgblack@eecs.umich.edu    0x08,  // SynchronousExternalAbort
913576Sgblack@eecs.umich.edu    0x10,  // TLBConflictAbort
923576Sgblack@eecs.umich.edu    0x19,  // SynchPtyErrOnMemoryAccess
932221SN/A    0x16,  // AsynchronousExternalAbort
943573Sgblack@eecs.umich.edu    0x18,  // AsynchPtyErrOnMemoryAccess
953576Sgblack@eecs.umich.edu    0xff,  // AddressSizeL0 (INVALID)
963576Sgblack@eecs.umich.edu    0xff,  // AddressSizeL1 (INVALID)
973576Sgblack@eecs.umich.edu    0xff,  // AddressSizeL2 (INVALID)
983576Sgblack@eecs.umich.edu    0xff,  // AddressSizeL3 (INVALID)
993576Sgblack@eecs.umich.edu    0x40,  // PrefetchTLBMiss
1003576Sgblack@eecs.umich.edu    0x80   // PrefetchUncacheable
1013576Sgblack@eecs.umich.edu};
1023576Sgblack@eecs.umich.edu
1033576Sgblack@eecs.umich.edustatic_assert(sizeof(ArmFault::shortDescFaultSources) ==
1043576Sgblack@eecs.umich.edu              ArmFault::NumFaultSources,
1053576Sgblack@eecs.umich.edu              "Invalid size of ArmFault::shortDescFaultSources[]");
1063576Sgblack@eecs.umich.edu
1072221SN/Auint8_t ArmFault::longDescFaultSources[] = {
1083573Sgblack@eecs.umich.edu    0x21,  // AlignmentFault
1093576Sgblack@eecs.umich.edu    0xff,  // InstructionCacheMaintenance (INVALID)
1103576Sgblack@eecs.umich.edu    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
1112221SN/A    0x15,  // SynchExtAbtOnTranslTableWalkL1
1123573Sgblack@eecs.umich.edu    0x16,  // SynchExtAbtOnTranslTableWalkL2
1133576Sgblack@eecs.umich.edu    0x17,  // SynchExtAbtOnTranslTableWalkL3
1143576Sgblack@eecs.umich.edu    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
1152221SN/A    0x1d,  // SynchPtyErrOnTranslTableWalkL1
1163573Sgblack@eecs.umich.edu    0x1e,  // SynchPtyErrOnTranslTableWalkL2
1173576Sgblack@eecs.umich.edu    0x1f,  // SynchPtyErrOnTranslTableWalkL3
1183576Sgblack@eecs.umich.edu    0xff,  // TranslationL0 (INVALID)
1192221SN/A    0x05,  // TranslationL1
1203573Sgblack@eecs.umich.edu    0x06,  // TranslationL2
1213576Sgblack@eecs.umich.edu    0x07,  // TranslationL3
1223576Sgblack@eecs.umich.edu    0xff,  // AccessFlagL0 (INVALID)
1232221SN/A    0x09,  // AccessFlagL1
1243573Sgblack@eecs.umich.edu    0x0a,  // AccessFlagL2
1253576Sgblack@eecs.umich.edu    0x0b,  // AccessFlagL3
1263576Sgblack@eecs.umich.edu    0xff,  // DomainL0 (INVALID)
1272221SN/A    0x3d,  // DomainL1
1283573Sgblack@eecs.umich.edu    0x3e,  // DomainL2
1293576Sgblack@eecs.umich.edu    0xff,  // DomainL3 (RESERVED)
1303576Sgblack@eecs.umich.edu    0xff,  // PermissionL0 (INVALID)
1312223SN/A    0x0d,  // PermissionL1
1323573Sgblack@eecs.umich.edu    0x0e,  // PermissionL2
1333576Sgblack@eecs.umich.edu    0x0f,  // PermissionL3
1343576Sgblack@eecs.umich.edu    0x22,  // DebugEvent
1352223SN/A    0x10,  // SynchronousExternalAbort
1363573Sgblack@eecs.umich.edu    0x30,  // TLBConflictAbort
1373576Sgblack@eecs.umich.edu    0x18,  // SynchPtyErrOnMemoryAccess
1383576Sgblack@eecs.umich.edu    0x11,  // AsynchronousExternalAbort
1392223SN/A    0x19,  // AsynchPtyErrOnMemoryAccess
1403573Sgblack@eecs.umich.edu    0xff,  // AddressSizeL0 (INVALID)
1413576Sgblack@eecs.umich.edu    0xff,  // AddressSizeL1 (INVALID)
1423576Sgblack@eecs.umich.edu    0xff,  // AddressSizeL2 (INVALID)
1432223SN/A    0xff,  // AddressSizeL3 (INVALID)
1443573Sgblack@eecs.umich.edu    0x40,  // PrefetchTLBMiss
1453576Sgblack@eecs.umich.edu    0x80   // PrefetchUncacheable
1463576Sgblack@eecs.umich.edu};
1473576Sgblack@eecs.umich.edu
1483576Sgblack@eecs.umich.edustatic_assert(sizeof(ArmFault::longDescFaultSources) ==
1493576Sgblack@eecs.umich.edu              ArmFault::NumFaultSources,
1503576Sgblack@eecs.umich.edu              "Invalid size of ArmFault::longDescFaultSources[]");
1513576Sgblack@eecs.umich.edu
1522223SN/Auint8_t ArmFault::aarch64FaultSources[] = {
1533573Sgblack@eecs.umich.edu    0x21,  // AlignmentFault
1543576Sgblack@eecs.umich.edu    0xff,  // InstructionCacheMaintenance (INVALID)
1553576Sgblack@eecs.umich.edu    0x14,  // SynchExtAbtOnTranslTableWalkL0
1562223SN/A    0x15,  // SynchExtAbtOnTranslTableWalkL1
1573573Sgblack@eecs.umich.edu    0x16,  // SynchExtAbtOnTranslTableWalkL2
1583576Sgblack@eecs.umich.edu    0x17,  // SynchExtAbtOnTranslTableWalkL3
1593576Sgblack@eecs.umich.edu    0x1c,  // SynchPtyErrOnTranslTableWalkL0
1602223SN/A    0x1d,  // SynchPtyErrOnTranslTableWalkL1
1613573Sgblack@eecs.umich.edu    0x1e,  // SynchPtyErrOnTranslTableWalkL2
1623576Sgblack@eecs.umich.edu    0x1f,  // SynchPtyErrOnTranslTableWalkL3
1633576Sgblack@eecs.umich.edu    0x04,  // TranslationL0
1642223SN/A    0x05,  // TranslationL1
1653573Sgblack@eecs.umich.edu    0x06,  // TranslationL2
1663576Sgblack@eecs.umich.edu    0x07,  // TranslationL3
1673576Sgblack@eecs.umich.edu    0x08,  // AccessFlagL0
1682223SN/A    0x09,  // AccessFlagL1
1693573Sgblack@eecs.umich.edu    0x0a,  // AccessFlagL2
1703576Sgblack@eecs.umich.edu    0x0b,  // AccessFlagL3
1713576Sgblack@eecs.umich.edu    // @todo: Section & Page Domain Fault in AArch64?
1722223SN/A    0xff,  // DomainL0 (INVALID)
1733573Sgblack@eecs.umich.edu    0xff,  // DomainL1 (INVALID)
1743576Sgblack@eecs.umich.edu    0xff,  // DomainL2 (INVALID)
1753576Sgblack@eecs.umich.edu    0xff,  // DomainL3 (INVALID)
1762223SN/A    0x0c,  // PermissionL0
1773573Sgblack@eecs.umich.edu    0x0d,  // PermissionL1
1783576Sgblack@eecs.umich.edu    0x0e,  // PermissionL2
1793576Sgblack@eecs.umich.edu    0x0f,  // PermissionL3
1802223SN/A    0x22,  // DebugEvent
1813573Sgblack@eecs.umich.edu    0x10,  // SynchronousExternalAbort
1823576Sgblack@eecs.umich.edu    0x30,  // TLBConflictAbort
1833576Sgblack@eecs.umich.edu    0x18,  // SynchPtyErrOnMemoryAccess
1842223SN/A    0xff,  // AsynchronousExternalAbort (INVALID)
1853573Sgblack@eecs.umich.edu    0xff,  // AsynchPtyErrOnMemoryAccess (INVALID)
1863576Sgblack@eecs.umich.edu    0x00,  // AddressSizeL0
1873576Sgblack@eecs.umich.edu    0x01,  // AddressSizeL1
1882223SN/A    0x02,  // AddressSizeL2
1893573Sgblack@eecs.umich.edu    0x03,  // AddressSizeL3
1903576Sgblack@eecs.umich.edu    0x40,  // PrefetchTLBMiss
1913576Sgblack@eecs.umich.edu    0x80   // PrefetchUncacheable
1922223SN/A};
1933576Sgblack@eecs.umich.edu
1943576Sgblack@eecs.umich.edustatic_assert(sizeof(ArmFault::aarch64FaultSources) ==
1953576Sgblack@eecs.umich.edu              ArmFault::NumFaultSources,
1963576Sgblack@eecs.umich.edu              "Invalid size of ArmFault::aarch64FaultSources[]");
1972527SN/A
1983573Sgblack@eecs.umich.edu// Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode,
1993576Sgblack@eecs.umich.edu//         {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap,
2003576Sgblack@eecs.umich.edu//         {A, F} disable, class, stat
2012223SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals(
2023573Sgblack@eecs.umich.edu    // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED
2033576Sgblack@eecs.umich.edu    // location in AArch64)
2043576Sgblack@eecs.umich.edu    "Reset",                 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2052223SN/A    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN
2063573Sgblack@eecs.umich.edu);
2073576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals(
2083576Sgblack@eecs.umich.edu    "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
2092223SN/A    4, 2, 0, 0, true,  false, false, EC_UNKNOWN
2103573Sgblack@eecs.umich.edu);
2113576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals(
2123576Sgblack@eecs.umich.edu    "Supervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2132223SN/A    4, 2, 4, 2, true,  false, false, EC_SVC_TO_HYP
2143573Sgblack@eecs.umich.edu);
2153576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals(
2163576Sgblack@eecs.umich.edu    "Secure Monitor Call",   0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2172223SN/A    4, 4, 4, 4, false, true,  true,  EC_SMC_TO_HYP
2183573Sgblack@eecs.umich.edu);
2193576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals(
2203576Sgblack@eecs.umich.edu    "Hypervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2213576Sgblack@eecs.umich.edu    4, 4, 4, 4, true,  false, false, EC_HVC
2223576Sgblack@eecs.umich.edu);
2233576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals(
2243576Sgblack@eecs.umich.edu    "Prefetch Abort",        0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2253576Sgblack@eecs.umich.edu    4, 4, 0, 0, true,  true,  false, EC_PREFETCH_ABORT_TO_HYP
2263576Sgblack@eecs.umich.edu);
2273576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals(
2283576Sgblack@eecs.umich.edu    "Data Abort",            0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2293576Sgblack@eecs.umich.edu    8, 8, 0, 0, true,  true,  false, EC_DATA_ABORT_TO_HYP
2303576Sgblack@eecs.umich.edu);
2313576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals(
2323576Sgblack@eecs.umich.edu    "Virtual Data Abort",    0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2333576Sgblack@eecs.umich.edu    8, 8, 0, 0, true,  true,  false, EC_INVALID
2343576Sgblack@eecs.umich.edu);
2353576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals(
2363576Sgblack@eecs.umich.edu    // @todo: double check these values
2373576Sgblack@eecs.umich.edu    "Hypervisor Trap",       0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2383576Sgblack@eecs.umich.edu    0, 0, 0, 0, false, false, false, EC_UNKNOWN
2393576Sgblack@eecs.umich.edu);
2403576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals(
2413576Sgblack@eecs.umich.edu    "Secure Monitor Trap",   0x004, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2423576Sgblack@eecs.umich.edu    4, 2, 0, 0, false, false, false, EC_UNKNOWN
2433576Sgblack@eecs.umich.edu);
2443576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals(
2453576Sgblack@eecs.umich.edu    "IRQ",                   0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2463576Sgblack@eecs.umich.edu    4, 4, 0, 0, false, true,  false, EC_UNKNOWN
2473576Sgblack@eecs.umich.edu);
2483576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals(
2493576Sgblack@eecs.umich.edu    "Virtual IRQ",           0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2503576Sgblack@eecs.umich.edu    4, 4, 0, 0, false, true,  false, EC_INVALID
2513576Sgblack@eecs.umich.edu);
2523576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals(
2533576Sgblack@eecs.umich.edu    "FIQ",                   0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2543576Sgblack@eecs.umich.edu    4, 4, 0, 0, false, true,  true,  EC_UNKNOWN
2553576Sgblack@eecs.umich.edu);
2563576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals(
2573576Sgblack@eecs.umich.edu    "Virtual FIQ",           0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2583576Sgblack@eecs.umich.edu    4, 4, 0, 0, false, true,  true,  EC_INVALID
2593576Sgblack@eecs.umich.edu);
2603576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals(
2613576Sgblack@eecs.umich.edu    "Illegal Inst Set State Fault",   0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
2623576Sgblack@eecs.umich.edu    4, 2, 0, 0, true, false, false, EC_ILLEGAL_INST
2633576Sgblack@eecs.umich.edu);
2643576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals(
2652223SN/A    // Some dummy values (SupervisorTrap is AArch64-only)
2662800Ssaidi@eecs.umich.edu    "Supervisor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2673573Sgblack@eecs.umich.edu    0, 0, 0, 0, false, false, false, EC_UNKNOWN
2683576Sgblack@eecs.umich.edu);
2693576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals(
2702800Ssaidi@eecs.umich.edu    // Some dummy values (PCAlignmentFault is AArch64-only)
2712800Ssaidi@eecs.umich.edu    "PC Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2723415Sgblack@eecs.umich.edu    0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT
2733578Sgblack@eecs.umich.edu);
2743578Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals(
2753415Sgblack@eecs.umich.edu    // Some dummy values (SPAlignmentFault is AArch64-only)
2763415Sgblack@eecs.umich.edu    "SP Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2773578Sgblack@eecs.umich.edu    0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT
2783415Sgblack@eecs.umich.edu);
2793578Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals(
2803578Sgblack@eecs.umich.edu    // Some dummy values (SError is AArch64-only)
2813578Sgblack@eecs.umich.edu    "SError",                0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC,
2823578Sgblack@eecs.umich.edu    0, 0, 0, 0, false, true,  true,  EC_SERROR
2833578Sgblack@eecs.umich.edu);
2843578Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals(
2853578Sgblack@eecs.umich.edu    // Some dummy values (SoftwareBreakpoint is AArch64-only)
2863578Sgblack@eecs.umich.edu    "Software Breakpoint",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2873578Sgblack@eecs.umich.edu    0, 0, 0, 0, true, false, false,  EC_SOFTWARE_BREAKPOINT
2883578Sgblack@eecs.umich.edu);
2893578Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals(
2903578Sgblack@eecs.umich.edu    // Some dummy values
2913578Sgblack@eecs.umich.edu    "ArmSev Flush",          0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2923578Sgblack@eecs.umich.edu    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN
2933578Sgblack@eecs.umich.edu);
2943578Sgblack@eecs.umich.edu
2953578Sgblack@eecs.umich.eduAddr
2963578Sgblack@eecs.umich.eduArmFault::getVector(ThreadContext *tc)
2973578Sgblack@eecs.umich.edu{
2983578Sgblack@eecs.umich.edu    Addr base;
2993578Sgblack@eecs.umich.edu
3003578Sgblack@eecs.umich.edu    // Check for invalid modes
3013578Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
3023578Sgblack@eecs.umich.edu    assert(ArmSystem::haveSecurity(tc) || cpsr.mode != MODE_MON);
3033578Sgblack@eecs.umich.edu    assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
3043578Sgblack@eecs.umich.edu
3053578Sgblack@eecs.umich.edu    switch (cpsr.mode)
3063578Sgblack@eecs.umich.edu    {
3073578Sgblack@eecs.umich.edu      case MODE_MON:
3083578Sgblack@eecs.umich.edu        base = tc->readMiscReg(MISCREG_MVBAR);
3093578Sgblack@eecs.umich.edu        break;
3103578Sgblack@eecs.umich.edu      case MODE_HYP:
3113578Sgblack@eecs.umich.edu        base = tc->readMiscReg(MISCREG_HVBAR);
3123578Sgblack@eecs.umich.edu        break;
3133578Sgblack@eecs.umich.edu      default:
3143578Sgblack@eecs.umich.edu        SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
3153578Sgblack@eecs.umich.edu        if (sctlr.v) {
3163578Sgblack@eecs.umich.edu            base = HighVecs;
3173578Sgblack@eecs.umich.edu        } else {
3183578Sgblack@eecs.umich.edu            base = ArmSystem::haveSecurity(tc) ?
3193578Sgblack@eecs.umich.edu                tc->readMiscReg(MISCREG_VBAR) : 0;
3203578Sgblack@eecs.umich.edu        }
3213578Sgblack@eecs.umich.edu        break;
3223578Sgblack@eecs.umich.edu    }
3233578Sgblack@eecs.umich.edu
3243578Sgblack@eecs.umich.edu    return base + offset(tc);
3253578Sgblack@eecs.umich.edu}
3263578Sgblack@eecs.umich.edu
3273578Sgblack@eecs.umich.eduAddr
3283578Sgblack@eecs.umich.eduArmFault::getVector64(ThreadContext *tc)
3293578Sgblack@eecs.umich.edu{
3303578Sgblack@eecs.umich.edu    Addr vbar;
3313578Sgblack@eecs.umich.edu    switch (toEL) {
3323578Sgblack@eecs.umich.edu      case EL3:
3333578Sgblack@eecs.umich.edu        assert(ArmSystem::haveSecurity(tc));
3343578Sgblack@eecs.umich.edu        vbar = tc->readMiscReg(MISCREG_VBAR_EL3);
3353578Sgblack@eecs.umich.edu        break;
3363578Sgblack@eecs.umich.edu      case EL2:
3373578Sgblack@eecs.umich.edu        assert(ArmSystem::haveVirtualization(tc));
3383578Sgblack@eecs.umich.edu        vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
3393578Sgblack@eecs.umich.edu        break;
3403578Sgblack@eecs.umich.edu      case EL1:
3413578Sgblack@eecs.umich.edu        vbar = tc->readMiscReg(MISCREG_VBAR_EL1);
3423578Sgblack@eecs.umich.edu        break;
3433578Sgblack@eecs.umich.edu      default:
3443578Sgblack@eecs.umich.edu        panic("Invalid target exception level");
3453578Sgblack@eecs.umich.edu        break;
3463578Sgblack@eecs.umich.edu    }
3473578Sgblack@eecs.umich.edu    return vbar + offset64(tc);
3483578Sgblack@eecs.umich.edu}
3493578Sgblack@eecs.umich.edu
3503578Sgblack@eecs.umich.eduMiscRegIndex
3513578Sgblack@eecs.umich.eduArmFault::getSyndromeReg64() const
3523578Sgblack@eecs.umich.edu{
3533578Sgblack@eecs.umich.edu    switch (toEL) {
3543578Sgblack@eecs.umich.edu      case EL1:
3553578Sgblack@eecs.umich.edu        return MISCREG_ESR_EL1;
3563578Sgblack@eecs.umich.edu      case EL2:
3573578Sgblack@eecs.umich.edu        return MISCREG_ESR_EL2;
3583578Sgblack@eecs.umich.edu      case EL3:
3593578Sgblack@eecs.umich.edu        return MISCREG_ESR_EL3;
3603578Sgblack@eecs.umich.edu      default:
3613578Sgblack@eecs.umich.edu        panic("Invalid exception level");
3623578Sgblack@eecs.umich.edu        break;
3633578Sgblack@eecs.umich.edu    }
3643578Sgblack@eecs.umich.edu}
3653578Sgblack@eecs.umich.edu
3663578Sgblack@eecs.umich.eduMiscRegIndex
3673578Sgblack@eecs.umich.eduArmFault::getFaultAddrReg64() const
3683578Sgblack@eecs.umich.edu{
3693578Sgblack@eecs.umich.edu    switch (toEL) {
3703578Sgblack@eecs.umich.edu      case EL1:
3713578Sgblack@eecs.umich.edu        return MISCREG_FAR_EL1;
3723578Sgblack@eecs.umich.edu      case EL2:
3733578Sgblack@eecs.umich.edu        return MISCREG_FAR_EL2;
3743578Sgblack@eecs.umich.edu      case EL3:
3753578Sgblack@eecs.umich.edu        return MISCREG_FAR_EL3;
3763578Sgblack@eecs.umich.edu      default:
3773578Sgblack@eecs.umich.edu        panic("Invalid exception level");
3783578Sgblack@eecs.umich.edu        break;
3793578Sgblack@eecs.umich.edu    }
3803578Sgblack@eecs.umich.edu}
3813578Sgblack@eecs.umich.edu
3823578Sgblack@eecs.umich.eduvoid
3833578Sgblack@eecs.umich.eduArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
3843578Sgblack@eecs.umich.edu{
3853578Sgblack@eecs.umich.edu    uint32_t value;
3863578Sgblack@eecs.umich.edu    uint32_t exc_class = (uint32_t) ec(tc);
3873578Sgblack@eecs.umich.edu    uint32_t issVal = iss();
3883578Sgblack@eecs.umich.edu
3893578Sgblack@eecs.umich.edu    assert(!from64 || ArmSystem::highestELIs64(tc));
3903578Sgblack@eecs.umich.edu
3913578Sgblack@eecs.umich.edu    value = exc_class << 26;
3923578Sgblack@eecs.umich.edu
3933578Sgblack@eecs.umich.edu    // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24,
3943578Sgblack@eecs.umich.edu    // 0x25) for which the ISS information is not valid (ARMv7).
3953578Sgblack@eecs.umich.edu    // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not
3963578Sgblack@eecs.umich.edu    // valid it is treated as RES1.
3973578Sgblack@eecs.umich.edu    if (to64) {
3983578Sgblack@eecs.umich.edu        value |= 1 << 25;
3993415Sgblack@eecs.umich.edu    } else if ((bits(exc_class, 5, 3) != 4) ||
4003415Sgblack@eecs.umich.edu               (bits(exc_class, 2) && bits(issVal, 24))) {
4013415Sgblack@eecs.umich.edu        if (!machInst.thumb || machInst.bigThumb)
4023415Sgblack@eecs.umich.edu            value |= 1 << 25;
4033415Sgblack@eecs.umich.edu    }
4043415Sgblack@eecs.umich.edu    // Condition code valid for EC[5:4] nonzero
4053415Sgblack@eecs.umich.edu    if (!from64 && ((bits(exc_class, 5, 4) == 0) &&
4063415Sgblack@eecs.umich.edu                    (bits(exc_class, 3, 0) != 0))) {
4073415Sgblack@eecs.umich.edu        if (!machInst.thumb) {
4083415Sgblack@eecs.umich.edu            uint32_t      cond;
4093415Sgblack@eecs.umich.edu            ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode;
4103415Sgblack@eecs.umich.edu            // If its on unconditional instruction report with a cond code of
4113415Sgblack@eecs.umich.edu            // 0xE, ie the unconditional code
4123415Sgblack@eecs.umich.edu            cond  = (condCode == COND_UC) ? COND_AL : condCode;
4133415Sgblack@eecs.umich.edu            value |= cond << 20;
4143415Sgblack@eecs.umich.edu            value |= 1    << 24;
4153415Sgblack@eecs.umich.edu        }
4163415Sgblack@eecs.umich.edu        value |= bits(issVal, 19, 0);
4173415Sgblack@eecs.umich.edu    } else {
4183415Sgblack@eecs.umich.edu        value |= issVal;
4193415Sgblack@eecs.umich.edu    }
4203415Sgblack@eecs.umich.edu    tc->setMiscReg(syndrome_reg, value);
4213415Sgblack@eecs.umich.edu}
4223415Sgblack@eecs.umich.edu
4233415Sgblack@eecs.umich.eduvoid
4243415Sgblack@eecs.umich.eduArmFault::update(ThreadContext *tc)
4253415Sgblack@eecs.umich.edu{
4263415Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
4273415Sgblack@eecs.umich.edu
4283415Sgblack@eecs.umich.edu    // Determine source exception level and mode
4293415Sgblack@eecs.umich.edu    fromMode = (OperatingMode) (uint8_t) cpsr.mode;
4303415Sgblack@eecs.umich.edu    fromEL = opModeToEL(fromMode);
4313415Sgblack@eecs.umich.edu    if (opModeIs64(fromMode))
4323578Sgblack@eecs.umich.edu        from64 = true;
4333578Sgblack@eecs.umich.edu
4343415Sgblack@eecs.umich.edu    // Determine target exception level (aarch64) or target execution
4353578Sgblack@eecs.umich.edu    // mode (aarch32).
4363415Sgblack@eecs.umich.edu    if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc)) {
4373415Sgblack@eecs.umich.edu        toMode = MODE_MON;
4383415Sgblack@eecs.umich.edu        toEL = EL3;
4393415Sgblack@eecs.umich.edu    } else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc)) {
4403415Sgblack@eecs.umich.edu        toMode = MODE_HYP;
4413415Sgblack@eecs.umich.edu        toEL = EL2;
4423415Sgblack@eecs.umich.edu        hypRouted = true;
4433415Sgblack@eecs.umich.edu    } else {
4443578Sgblack@eecs.umich.edu        toMode = nextMode();
4453415Sgblack@eecs.umich.edu        toEL = opModeToEL(toMode);
4463415Sgblack@eecs.umich.edu    }
4473415Sgblack@eecs.umich.edu
4483415Sgblack@eecs.umich.edu    if (fromEL > toEL)
4493415Sgblack@eecs.umich.edu        toEL = fromEL;
4503415Sgblack@eecs.umich.edu
4513415Sgblack@eecs.umich.edu    // Check for Set Priviledge Access Never, if PAN is supported
4523415Sgblack@eecs.umich.edu    AA64MMFR1 mmfr1 = tc->readMiscReg(MISCREG_ID_AA64MMFR1_EL1);
4533415Sgblack@eecs.umich.edu    if (mmfr1.pan) {
4543415Sgblack@eecs.umich.edu        if (toEL == EL1) {
4553415Sgblack@eecs.umich.edu            const SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR_EL1);
4563415Sgblack@eecs.umich.edu            span = !sctlr.span;
4573415Sgblack@eecs.umich.edu        }
4583415Sgblack@eecs.umich.edu
4593415Sgblack@eecs.umich.edu        const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
4603415Sgblack@eecs.umich.edu        if (toEL == EL2 && hcr.e2h && hcr.tge) {
4613415Sgblack@eecs.umich.edu            const SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR_EL2);
4623415Sgblack@eecs.umich.edu            span = !sctlr.span;
4633415Sgblack@eecs.umich.edu        }
4643415Sgblack@eecs.umich.edu    }
4653578Sgblack@eecs.umich.edu
4663415Sgblack@eecs.umich.edu    to64 = ELIs64(tc, toEL);
4673415Sgblack@eecs.umich.edu
4683415Sgblack@eecs.umich.edu    // The fault specific informations have been updated; it is
4693415Sgblack@eecs.umich.edu    // now possible to use them inside the fault.
4703415Sgblack@eecs.umich.edu    faultUpdated = true;
4713415Sgblack@eecs.umich.edu}
4723415Sgblack@eecs.umich.edu
4733415Sgblack@eecs.umich.eduvoid
4743415Sgblack@eecs.umich.eduArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
4753415Sgblack@eecs.umich.edu{
4763415Sgblack@eecs.umich.edu
4773415Sgblack@eecs.umich.edu    // Update fault state informations, like the starting mode (aarch32)
4783415Sgblack@eecs.umich.edu    // or EL (aarch64) and the ending mode or EL.
4793415Sgblack@eecs.umich.edu    // From the update function we are also evaluating if the fault must
4803415Sgblack@eecs.umich.edu    // be handled in AArch64 mode (to64).
4813415Sgblack@eecs.umich.edu    update(tc);
4823415Sgblack@eecs.umich.edu
4833415Sgblack@eecs.umich.edu    if (to64) {
4843415Sgblack@eecs.umich.edu        // Invoke exception handler in AArch64 state
4853415Sgblack@eecs.umich.edu        invoke64(tc, inst);
4863420Sgblack@eecs.umich.edu        return;
4873415Sgblack@eecs.umich.edu    }
4883415Sgblack@eecs.umich.edu
4893415Sgblack@eecs.umich.edu    // ARMv7 (ARM ARM issue C B1.9)
4903415Sgblack@eecs.umich.edu
4913415Sgblack@eecs.umich.edu    bool have_security       = ArmSystem::haveSecurity(tc);
4923415Sgblack@eecs.umich.edu
4933415Sgblack@eecs.umich.edu    FaultBase::invoke(tc);
4943578Sgblack@eecs.umich.edu    if (!FullSystem)
4953578Sgblack@eecs.umich.edu        return;
4963585Sgblack@eecs.umich.edu    countStat()++;
4973578Sgblack@eecs.umich.edu
4983578Sgblack@eecs.umich.edu    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
4993578Sgblack@eecs.umich.edu    SCR scr = tc->readMiscReg(MISCREG_SCR);
5003578Sgblack@eecs.umich.edu    CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR);
5013578Sgblack@eecs.umich.edu    saved_cpsr.nz = tc->readCCReg(CCREG_NZ);
5023585Sgblack@eecs.umich.edu    saved_cpsr.c = tc->readCCReg(CCREG_C);
5033578Sgblack@eecs.umich.edu    saved_cpsr.v = tc->readCCReg(CCREG_V);
5043585Sgblack@eecs.umich.edu    saved_cpsr.ge = tc->readCCReg(CCREG_GE);
5053578Sgblack@eecs.umich.edu
5063578Sgblack@eecs.umich.edu    Addr curPc M5_VAR_USED = tc->pcState().pc();
5073578Sgblack@eecs.umich.edu    ITSTATE it = tc->pcState().itstate();
5083578Sgblack@eecs.umich.edu    saved_cpsr.it2 = it.top6;
5093585Sgblack@eecs.umich.edu    saved_cpsr.it1 = it.bottom2;
5103578Sgblack@eecs.umich.edu
5113585Sgblack@eecs.umich.edu    // if we have a valid instruction then use it to annotate this fault with
5123578Sgblack@eecs.umich.edu    // extra information. This is used to generate the correct fault syndrome
5133578Sgblack@eecs.umich.edu    // information
5143578Sgblack@eecs.umich.edu    ArmStaticInst *arm_inst M5_VAR_USED = instrAnnotate(inst);
5153578Sgblack@eecs.umich.edu
5163578Sgblack@eecs.umich.edu    // Ensure Secure state if initially in Monitor mode
5173578Sgblack@eecs.umich.edu    if (have_security && saved_cpsr.mode == MODE_MON) {
5182221SN/A        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
5192221SN/A        if (scr.ns) {
5203573Sgblack@eecs.umich.edu            scr.ns = 0;
5212221SN/A            tc->setMiscRegNoEffect(MISCREG_SCR, scr);
5222680Sktlim@umich.edu        }
5232223SN/A    }
5242221SN/A
5253578Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
5263578Sgblack@eecs.umich.edu    cpsr.mode = toMode;
5273578Sgblack@eecs.umich.edu
5283578Sgblack@eecs.umich.edu    // some bits are set differently if we have been routed to hyp mode
5293578Sgblack@eecs.umich.edu    if (cpsr.mode == MODE_HYP) {
5303578Sgblack@eecs.umich.edu        SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR);
5313578Sgblack@eecs.umich.edu        cpsr.t = hsctlr.te;
5323578Sgblack@eecs.umich.edu        cpsr.e = hsctlr.ee;
5333578Sgblack@eecs.umich.edu        if (!scr.ea)  {cpsr.a = 1;}
5343578Sgblack@eecs.umich.edu        if (!scr.fiq) {cpsr.f = 1;}
5353578Sgblack@eecs.umich.edu        if (!scr.irq) {cpsr.i = 1;}
5363578Sgblack@eecs.umich.edu    } else if (cpsr.mode == MODE_MON) {
5373578Sgblack@eecs.umich.edu        // Special case handling when entering monitor mode
5383578Sgblack@eecs.umich.edu        cpsr.t = sctlr.te;
5393578Sgblack@eecs.umich.edu        cpsr.e = sctlr.ee;
5403578Sgblack@eecs.umich.edu        cpsr.a = 1;
5413578Sgblack@eecs.umich.edu        cpsr.f = 1;
5423578Sgblack@eecs.umich.edu        cpsr.i = 1;
5433578Sgblack@eecs.umich.edu    } else {
5443578Sgblack@eecs.umich.edu        cpsr.t = sctlr.te;
5453578Sgblack@eecs.umich.edu        cpsr.e = sctlr.ee;
5463578Sgblack@eecs.umich.edu
5473578Sgblack@eecs.umich.edu        // The *Disable functions are virtual and different per fault
5483578Sgblack@eecs.umich.edu        cpsr.a = cpsr.a | abortDisable(tc);
5493578Sgblack@eecs.umich.edu        cpsr.f = cpsr.f | fiqDisable(tc);
5503578Sgblack@eecs.umich.edu        cpsr.i = 1;
5513578Sgblack@eecs.umich.edu    }
5523578Sgblack@eecs.umich.edu    cpsr.it1 = cpsr.it2 = 0;
5533578Sgblack@eecs.umich.edu    cpsr.j = 0;
5543578Sgblack@eecs.umich.edu    cpsr.pan = span ? 1 : saved_cpsr.pan;
5553578Sgblack@eecs.umich.edu    tc->setMiscReg(MISCREG_CPSR, cpsr);
5563578Sgblack@eecs.umich.edu
5573578Sgblack@eecs.umich.edu    // Make sure mailbox sets to one always
5583578Sgblack@eecs.umich.edu    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
5593578Sgblack@eecs.umich.edu
5603585Sgblack@eecs.umich.edu    // Clear the exclusive monitor
5613578Sgblack@eecs.umich.edu    tc->setMiscReg(MISCREG_LOCKFLAG, 0);
5623578Sgblack@eecs.umich.edu
5633578Sgblack@eecs.umich.edu    if (cpsr.mode == MODE_HYP) {
5643578Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_ELR_HYP, curPc +
5653585Sgblack@eecs.umich.edu                (saved_cpsr.t ? thumbPcOffset(true)  : armPcOffset(true)));
5663578Sgblack@eecs.umich.edu    } else {
5673578Sgblack@eecs.umich.edu        tc->setIntReg(INTREG_LR, curPc +
5683578Sgblack@eecs.umich.edu                (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false)));
5693578Sgblack@eecs.umich.edu    }
5703585Sgblack@eecs.umich.edu
5713578Sgblack@eecs.umich.edu    switch (cpsr.mode) {
5723578Sgblack@eecs.umich.edu      case MODE_FIQ:
5733578Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
5743578Sgblack@eecs.umich.edu        break;
5753578Sgblack@eecs.umich.edu      case MODE_IRQ:
5763420Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
5772221SN/A        break;
5783523Sgblack@eecs.umich.edu      case MODE_SVC:
5793523Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
5803578Sgblack@eecs.umich.edu        break;
5813578Sgblack@eecs.umich.edu      case MODE_MON:
5823578Sgblack@eecs.umich.edu        assert(have_security);
5833523Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr);
5843523Sgblack@eecs.umich.edu        break;
5853523Sgblack@eecs.umich.edu      case MODE_ABORT:
5863523Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
5873523Sgblack@eecs.umich.edu        break;
5883523Sgblack@eecs.umich.edu      case MODE_UNDEFINED:
5892221SN/A        tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
5903523Sgblack@eecs.umich.edu        if (ec(tc) != EC_UNKNOWN)
5913523Sgblack@eecs.umich.edu            setSyndrome(tc, MISCREG_HSR);
5922221SN/A        break;
5933523Sgblack@eecs.umich.edu      case MODE_HYP:
5943523Sgblack@eecs.umich.edu        assert(ArmSystem::haveVirtualization(tc));
5953523Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr);
5963523Sgblack@eecs.umich.edu        setSyndrome(tc, MISCREG_HSR);
5973523Sgblack@eecs.umich.edu        break;
5983523Sgblack@eecs.umich.edu      default:
5993523Sgblack@eecs.umich.edu        panic("unknown Mode\n");
6003523Sgblack@eecs.umich.edu    }
6013523Sgblack@eecs.umich.edu
6023523Sgblack@eecs.umich.edu    Addr newPc = getVector(tc);
6033523Sgblack@eecs.umich.edu    DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x "
6043523Sgblack@eecs.umich.edu            "%s\n", name(), cpsr, curPc, tc->readIntReg(INTREG_LR),
6053523Sgblack@eecs.umich.edu            newPc, arm_inst ? csprintf("inst: %#x", arm_inst->encoding()) :
6063523Sgblack@eecs.umich.edu            std::string());
6073523Sgblack@eecs.umich.edu    PCState pc(newPc);
6083523Sgblack@eecs.umich.edu    pc.thumb(cpsr.t);
6093523Sgblack@eecs.umich.edu    pc.nextThumb(pc.thumb());
6103523Sgblack@eecs.umich.edu    pc.jazelle(cpsr.j);
6113523Sgblack@eecs.umich.edu    pc.nextJazelle(pc.jazelle());
6122221SN/A    pc.aarch64(!cpsr.width);
6132221SN/A    pc.nextAArch64(!cpsr.width);
6143578Sgblack@eecs.umich.edu    pc.illegalExec(false);
6152612SN/A    tc->pcState(pc);
6163415Sgblack@eecs.umich.edu}
6173415Sgblack@eecs.umich.edu
6183578Sgblack@eecs.umich.eduvoid
6193415Sgblack@eecs.umich.eduArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
6203415Sgblack@eecs.umich.edu{
6213415Sgblack@eecs.umich.edu    // Determine actual misc. register indices for ELR_ELx and SPSR_ELx
6223578Sgblack@eecs.umich.edu    MiscRegIndex elr_idx, spsr_idx;
6233415Sgblack@eecs.umich.edu    switch (toEL) {
6243415Sgblack@eecs.umich.edu      case EL1:
6253415Sgblack@eecs.umich.edu        elr_idx = MISCREG_ELR_EL1;
6263415Sgblack@eecs.umich.edu        spsr_idx = MISCREG_SPSR_EL1;
6273415Sgblack@eecs.umich.edu        break;
6283415Sgblack@eecs.umich.edu      case EL2:
6293415Sgblack@eecs.umich.edu        assert(ArmSystem::haveVirtualization(tc));
6303415Sgblack@eecs.umich.edu        elr_idx = MISCREG_ELR_EL2;
6313415Sgblack@eecs.umich.edu        spsr_idx = MISCREG_SPSR_EL2;
6323415Sgblack@eecs.umich.edu        break;
6333415Sgblack@eecs.umich.edu      case EL3:
6343415Sgblack@eecs.umich.edu        assert(ArmSystem::haveSecurity(tc));
6353578Sgblack@eecs.umich.edu        elr_idx = MISCREG_ELR_EL3;
6363415Sgblack@eecs.umich.edu        spsr_idx = MISCREG_SPSR_EL3;
6373415Sgblack@eecs.umich.edu        break;
6383415Sgblack@eecs.umich.edu      default:
6393578Sgblack@eecs.umich.edu        panic("Invalid target exception level");
6403415Sgblack@eecs.umich.edu        break;
6413415Sgblack@eecs.umich.edu    }
6423415Sgblack@eecs.umich.edu
6433578Sgblack@eecs.umich.edu    // Save process state into SPSR_ELx
6443415Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
6453415Sgblack@eecs.umich.edu    CPSR spsr = cpsr;
6463415Sgblack@eecs.umich.edu    spsr.nz = tc->readCCReg(CCREG_NZ);
6473415Sgblack@eecs.umich.edu    spsr.c = tc->readCCReg(CCREG_C);
6483415Sgblack@eecs.umich.edu    spsr.v = tc->readCCReg(CCREG_V);
6493415Sgblack@eecs.umich.edu    if (from64) {
6502800Ssaidi@eecs.umich.edu        // Force some bitfields to 0
6512800Ssaidi@eecs.umich.edu        spsr.q = 0;
6522800Ssaidi@eecs.umich.edu        spsr.it1 = 0;
6532800Ssaidi@eecs.umich.edu        spsr.j = 0;
6542800Ssaidi@eecs.umich.edu        spsr.ge = 0;
6552800Ssaidi@eecs.umich.edu        spsr.it2 = 0;
6562800Ssaidi@eecs.umich.edu        spsr.t = 0;
6572800Ssaidi@eecs.umich.edu    } else {
6582800Ssaidi@eecs.umich.edu        spsr.ge = tc->readCCReg(CCREG_GE);
6592800Ssaidi@eecs.umich.edu        ITSTATE it = tc->pcState().itstate();
6602800Ssaidi@eecs.umich.edu        spsr.it2 = it.top6;
6612800Ssaidi@eecs.umich.edu        spsr.it1 = it.bottom2;
6622800Ssaidi@eecs.umich.edu        // Force some bitfields to 0
6632800Ssaidi@eecs.umich.edu        spsr.ss = 0;
6642800Ssaidi@eecs.umich.edu    }
6652800Ssaidi@eecs.umich.edu    tc->setMiscReg(spsr_idx, spsr);
6662800Ssaidi@eecs.umich.edu
6672800Ssaidi@eecs.umich.edu    // Save preferred return address into ELR_ELx
6682800Ssaidi@eecs.umich.edu    Addr curr_pc = tc->pcState().pc();
6693415Sgblack@eecs.umich.edu    Addr ret_addr = curr_pc;
6702221SN/A    if (from64)
6712221SN/A        ret_addr += armPcElrOffset();
6722223SN/A    else
6732221SN/A        ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset();
674    tc->setMiscReg(elr_idx, ret_addr);
675
676    Addr vec_address = getVector64(tc);
677
678    // Update process state
679    OperatingMode64 mode = 0;
680    mode.spX = 1;
681    mode.el = toEL;
682    mode.width = 0;
683    cpsr.mode = mode;
684    cpsr.daif = 0xf;
685    cpsr.il = 0;
686    cpsr.ss = 0;
687    cpsr.pan = span ? 1 : spsr.pan;
688    tc->setMiscReg(MISCREG_CPSR, cpsr);
689
690    // If we have a valid instruction then use it to annotate this fault with
691    // extra information. This is used to generate the correct fault syndrome
692    // information
693    ArmStaticInst *arm_inst M5_VAR_USED = instrAnnotate(inst);
694
695    // Set PC to start of exception handler
696    Addr new_pc = purifyTaggedAddr(vec_address, tc, toEL);
697    DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x "
698            "elr:%#x newVec: %#x %s\n", name(), cpsr, curr_pc, ret_addr,
699            new_pc, arm_inst ? csprintf("inst: %#x", arm_inst->encoding()) :
700            std::string());
701    PCState pc(new_pc);
702    pc.aarch64(!cpsr.width);
703    pc.nextAArch64(!cpsr.width);
704    pc.illegalExec(false);
705    tc->pcState(pc);
706
707    // Save exception syndrome
708    if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ))
709        setSyndrome(tc, getSyndromeReg64());
710}
711
712ArmStaticInst *
713ArmFault::instrAnnotate(const StaticInstPtr &inst)
714{
715    if (inst) {
716        auto arm_inst = static_cast<ArmStaticInst *>(inst.get());
717        arm_inst->annotateFault(this);
718        return arm_inst;
719    } else {
720        return nullptr;
721    }
722}
723
724Addr
725Reset::getVector(ThreadContext *tc)
726{
727    Addr base;
728
729    // Check for invalid modes
730    CPSR M5_VAR_USED cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
731    assert(ArmSystem::haveSecurity(tc) || cpsr.mode != MODE_MON);
732    assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
733
734    // RVBAR is aliased (implemented as) MVBAR in gem5, since the two
735    // are mutually exclusive; there is no need to check here for
736    // which register to use since they hold the same value
737    base = tc->readMiscReg(MISCREG_MVBAR);
738
739    return base + offset(tc);
740}
741
742void
743Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
744{
745    if (FullSystem) {
746        tc->getCpuPtr()->clearInterrupts(tc->threadId());
747        tc->clearArchRegs();
748    }
749    if (!ArmSystem::highestELIs64(tc)) {
750        ArmFault::invoke(tc, inst);
751        tc->setMiscReg(MISCREG_VMPIDR,
752                       getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc));
753
754        // Unless we have SMC code to get us there, boot in HYP!
755        if (ArmSystem::haveVirtualization(tc) &&
756            !ArmSystem::haveSecurity(tc)) {
757            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
758            cpsr.mode = MODE_HYP;
759            tc->setMiscReg(MISCREG_CPSR, cpsr);
760        }
761    } else {
762        // Advance the PC to the IMPLEMENTATION DEFINED reset value
763        PCState pc = ArmSystem::resetAddr(tc);
764        pc.aarch64(true);
765        pc.nextAArch64(true);
766        tc->pcState(pc);
767    }
768}
769
770void
771UndefinedInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
772{
773    if (FullSystem) {
774        ArmFault::invoke(tc, inst);
775        return;
776    }
777
778    // If the mnemonic isn't defined this has to be an unknown instruction.
779    assert(unknown || mnemonic != NULL);
780    auto arm_inst = static_cast<ArmStaticInst *>(inst.get());
781    if (disabled) {
782        panic("Attempted to execute disabled instruction "
783                "'%s' (inst 0x%08x)", mnemonic, arm_inst->encoding());
784    } else if (unknown) {
785        panic("Attempted to execute unknown instruction (inst 0x%08x)",
786              arm_inst->encoding());
787    } else {
788        panic("Attempted to execute unimplemented instruction "
789                "'%s' (inst 0x%08x)", mnemonic, arm_inst->encoding());
790    }
791}
792
793bool
794UndefinedInstruction::routeToHyp(ThreadContext *tc) const
795{
796    bool toHyp;
797
798    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
799    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
800    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
801
802    // if in Hyp mode then stay in Hyp mode
803    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
804    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
805    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
806    return toHyp;
807}
808
809uint32_t
810UndefinedInstruction::iss() const
811{
812
813    // If UndefinedInstruction is routed to hypervisor, iss field is 0.
814    if (hypRouted) {
815        return 0;
816    }
817
818    if (overrideEc == EC_INVALID)
819        return issRaw;
820
821    uint32_t new_iss = 0;
822    uint32_t op0, op1, op2, CRn, CRm, Rt, dir;
823
824    dir = bits(machInst, 21, 21);
825    op0 = bits(machInst, 20, 19);
826    op1 = bits(machInst, 18, 16);
827    CRn = bits(machInst, 15, 12);
828    CRm = bits(machInst, 11, 8);
829    op2 = bits(machInst, 7, 5);
830    Rt = bits(machInst, 4, 0);
831
832    new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 |
833            Rt << 5 | CRm << 1 | dir;
834
835    return new_iss;
836}
837
838void
839SupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
840{
841    if (FullSystem) {
842        ArmFault::invoke(tc, inst);
843        return;
844    }
845
846    // As of now, there isn't a 32 bit thumb version of this instruction.
847    assert(!machInst.bigThumb);
848    uint32_t callNum;
849    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
850    OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
851    if (opModeIs64(mode))
852        callNum = tc->readIntReg(INTREG_X8);
853    else
854        callNum = tc->readIntReg(INTREG_R7);
855    Fault fault;
856    tc->syscall(callNum, &fault);
857
858    // Advance the PC since that won't happen automatically.
859    PCState pc = tc->pcState();
860    assert(inst);
861    inst->advancePC(pc);
862    tc->pcState(pc);
863}
864
865bool
866SupervisorCall::routeToHyp(ThreadContext *tc) const
867{
868    bool toHyp;
869
870    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
871    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
872    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
873
874    // if in Hyp mode then stay in Hyp mode
875    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
876    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
877    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
878    return toHyp;
879}
880
881ExceptionClass
882SupervisorCall::ec(ThreadContext *tc) const
883{
884    return (overrideEc != EC_INVALID) ? overrideEc :
885        (from64 ? EC_SVC_64 : vals.ec);
886}
887
888uint32_t
889SupervisorCall::iss() const
890{
891    // Even if we have a 24 bit imm from an arm32 instruction then we only use
892    // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC).
893    return issRaw & 0xFFFF;
894}
895
896uint32_t
897SecureMonitorCall::iss() const
898{
899    if (from64)
900        return bits(machInst, 20, 5);
901    return 0;
902}
903
904ExceptionClass
905UndefinedInstruction::ec(ThreadContext *tc) const
906{
907    // If UndefinedInstruction is routed to hypervisor,
908    // HSR.EC field is 0.
909    if (hypRouted)
910        return EC_UNKNOWN;
911    else
912        return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
913}
914
915
916HypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) :
917        ArmFaultVals<HypervisorCall>(_machInst, _imm)
918{}
919
920ExceptionClass
921HypervisorCall::ec(ThreadContext *tc) const
922{
923    return from64 ? EC_HVC_64 : vals.ec;
924}
925
926ExceptionClass
927HypervisorTrap::ec(ThreadContext *tc) const
928{
929    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
930}
931
932template<class T>
933FaultOffset
934ArmFaultVals<T>::offset(ThreadContext *tc)
935{
936    bool isHypTrap = false;
937
938    // Normally we just use the exception vector from the table at the top if
939    // this file, however if this exception has caused a transition to hype
940    // mode, and its an exception type that would only do this if it has been
941    // trapped then we use the hyp trap vector instead of the normal vector
942    if (vals.hypTrappable) {
943        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
944        if (cpsr.mode == MODE_HYP) {
945            CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
946            isHypTrap = spsr.mode != MODE_HYP;
947        }
948    }
949    return isHypTrap ? 0x14 : vals.offset;
950}
951
952template<class T>
953FaultOffset
954ArmFaultVals<T>::offset64(ThreadContext *tc)
955{
956    if (toEL == fromEL) {
957        if (opModeIsT(fromMode))
958            return vals.currELTOffset;
959        return vals.currELHOffset;
960    } else {
961        bool lower_32 = false;
962        if (toEL == EL3) {
963            if (!inSecureState(tc) && ArmSystem::haveEL(tc, EL2))
964                lower_32 = ELIs32(tc, EL2);
965            else
966                lower_32 = ELIs32(tc, EL1);
967        } else {
968            lower_32 = ELIs32(tc, static_cast<ExceptionLevel>(toEL - 1));
969        }
970
971        if (lower_32)
972            return vals.lowerEL32Offset;
973        return vals.lowerEL64Offset;
974    }
975}
976
977// void
978// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx)
979// {
980//     ESR esr = 0;
981//     esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32;
982//     esr.il = !machInst.thumb;
983//     if (machInst.aarch64)
984//         esr.imm16 = bits(machInst.instBits, 20, 5);
985//     else if (machInst.thumb)
986//         esr.imm16 = bits(machInst.instBits, 7, 0);
987//     else
988//         esr.imm16 = bits(machInst.instBits, 15, 0);
989//     tc->setMiscReg(esr_idx, esr);
990// }
991
992void
993SecureMonitorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
994{
995    if (FullSystem) {
996        ArmFault::invoke(tc, inst);
997        return;
998    }
999}
1000
1001ExceptionClass
1002SecureMonitorCall::ec(ThreadContext *tc) const
1003{
1004    return (from64 ? EC_SMC_64 : vals.ec);
1005}
1006
1007bool
1008SupervisorTrap::routeToHyp(ThreadContext *tc) const
1009{
1010    bool toHyp = false;
1011
1012    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1013    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
1014    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1015
1016    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
1017    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (currEL(tc) == EL0);
1018    return toHyp;
1019}
1020
1021uint32_t
1022SupervisorTrap::iss() const
1023{
1024    // If SupervisorTrap is routed to hypervisor, iss field is 0.
1025    if (hypRouted) {
1026        return 0;
1027    }
1028    return issRaw;
1029}
1030
1031ExceptionClass
1032SupervisorTrap::ec(ThreadContext *tc) const
1033{
1034    if (hypRouted)
1035        return EC_UNKNOWN;
1036    else
1037        return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
1038}
1039
1040ExceptionClass
1041SecureMonitorTrap::ec(ThreadContext *tc) const
1042{
1043    return (overrideEc != EC_INVALID) ? overrideEc :
1044        (from64 ? EC_SMC_64 : vals.ec);
1045}
1046
1047template<class T>
1048void
1049AbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
1050{
1051    if (tranMethod == ArmFault::UnknownTran) {
1052        tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran
1053                                             : ArmFault::VmsaTran;
1054
1055        if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) {
1056            // See ARM ARM B3-1416
1057            bool override_LPAE = false;
1058            TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S);
1059            TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS);
1060            if (ttbcr_s.eae) {
1061                override_LPAE = true;
1062            } else {
1063                // Unimplemented code option, not seen in testing.  May need
1064                // extension according to the manual exceprt above.
1065                DPRINTF(Faults, "Warning: Incomplete translation method "
1066                        "override detected.\n");
1067            }
1068            if (override_LPAE)
1069                tranMethod = ArmFault::LpaeTran;
1070        }
1071    }
1072
1073    if (source == ArmFault::AsynchronousExternalAbort) {
1074        tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
1075    }
1076    // Get effective fault source encoding
1077    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
1078
1079    // source must be determined BEFORE invoking generic routines which will
1080    // try to set hsr etc. and are based upon source!
1081    ArmFaultVals<T>::invoke(tc, inst);
1082
1083    if (!this->to64) {  // AArch32
1084        FSR  fsr  = getFsr(tc);
1085        if (cpsr.mode == MODE_HYP) {
1086            tc->setMiscReg(T::HFarIndex, faultAddr);
1087        } else if (stage2) {
1088            tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf);
1089            tc->setMiscReg(T::HFarIndex,  OVAddr);
1090        } else {
1091            tc->setMiscReg(T::FsrIndex, fsr);
1092            tc->setMiscReg(T::FarIndex, faultAddr);
1093        }
1094        DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\
1095                "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod);
1096    } else {  // AArch64
1097        // Set the FAR register.  Nothing else to do if we are in AArch64 state
1098        // because the syndrome register has already been set inside invoke64()
1099        if (stage2) {
1100            // stage 2 fault, set HPFAR_EL2 to the faulting IPA
1101            // and FAR_EL2 to the Original VA
1102            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr);
1103            tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
1104
1105            DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
1106                    OVAddr, faultAddr);
1107        } else {
1108            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
1109        }
1110    }
1111}
1112
1113template<class T>
1114void
1115AbortFault<T>::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
1116{
1117    srcEncoded = getFaultStatusCode(tc);
1118    if (srcEncoded == ArmFault::FaultSourceInvalid) {
1119        panic("Invalid fault source\n");
1120    }
1121    ArmFault::setSyndrome(tc, syndrome_reg);
1122}
1123
1124template<class T>
1125uint8_t
1126AbortFault<T>::getFaultStatusCode(ThreadContext *tc) const
1127{
1128
1129    panic_if(!this->faultUpdated,
1130             "Trying to use un-updated ArmFault internal variables\n");
1131
1132    uint8_t fsc = 0;
1133
1134    if (!this->to64) {
1135        // AArch32
1136        assert(tranMethod != ArmFault::UnknownTran);
1137        if (tranMethod == ArmFault::LpaeTran) {
1138            fsc = ArmFault::longDescFaultSources[source];
1139        } else {
1140            fsc = ArmFault::shortDescFaultSources[source];
1141        }
1142    } else {
1143        // AArch64
1144        fsc = ArmFault::aarch64FaultSources[source];
1145    }
1146
1147    return fsc;
1148}
1149
1150template<class T>
1151FSR
1152AbortFault<T>::getFsr(ThreadContext *tc) const
1153{
1154    FSR fsr = 0;
1155
1156    auto fsc = getFaultStatusCode(tc);
1157
1158    // AArch32
1159    assert(tranMethod != ArmFault::UnknownTran);
1160    if (tranMethod == ArmFault::LpaeTran) {
1161        fsr.status = fsc;
1162        fsr.lpae   = 1;
1163    } else {
1164        fsr.fsLow  = bits(fsc, 3, 0);
1165        fsr.fsHigh = bits(fsc, 4);
1166        fsr.domain = static_cast<uint8_t>(domain);
1167    }
1168
1169    fsr.wnr = (write ? 1 : 0);
1170    fsr.ext = 0;
1171
1172    return fsr;
1173}
1174
1175template<class T>
1176bool
1177AbortFault<T>::abortDisable(ThreadContext *tc)
1178{
1179    if (ArmSystem::haveSecurity(tc)) {
1180        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1181        return (!scr.ns || scr.aw);
1182    }
1183    return true;
1184}
1185
1186template<class T>
1187void
1188AbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val)
1189{
1190    switch (id)
1191    {
1192      case ArmFault::S1PTW:
1193        s1ptw = val;
1194        break;
1195      case ArmFault::OVA:
1196        OVAddr = val;
1197        break;
1198
1199      // Just ignore unknown ID's
1200      default:
1201        break;
1202    }
1203}
1204
1205template<class T>
1206uint32_t
1207AbortFault<T>::iss() const
1208{
1209    uint32_t val;
1210
1211    val  = srcEncoded & 0x3F;
1212    val |= write << 6;
1213    val |= s1ptw << 7;
1214    return (val);
1215}
1216
1217template<class T>
1218bool
1219AbortFault<T>::isMMUFault() const
1220{
1221    // NOTE: Not relying on LL information being aligned to lowest bits here
1222    return
1223         (source == ArmFault::AlignmentFault)     ||
1224        ((source >= ArmFault::TranslationLL) &&
1225         (source <  ArmFault::TranslationLL + 4)) ||
1226        ((source >= ArmFault::AccessFlagLL) &&
1227         (source <  ArmFault::AccessFlagLL + 4))  ||
1228        ((source >= ArmFault::DomainLL) &&
1229         (source <  ArmFault::DomainLL + 4))      ||
1230        ((source >= ArmFault::PermissionLL) &&
1231         (source <  ArmFault::PermissionLL + 4));
1232}
1233
1234template<class T>
1235bool
1236AbortFault<T>::getFaultVAddr(Addr &va) const
1237{
1238    va = (stage2 ?  OVAddr : faultAddr);
1239    return true;
1240}
1241
1242ExceptionClass
1243PrefetchAbort::ec(ThreadContext *tc) const
1244{
1245    if (to64) {
1246        // AArch64
1247        if (toEL == fromEL)
1248            return EC_PREFETCH_ABORT_CURR_EL;
1249        else
1250            return EC_PREFETCH_ABORT_LOWER_EL;
1251    } else {
1252        // AArch32
1253        // Abort faults have different EC codes depending on whether
1254        // the fault originated within HYP mode, or not. So override
1255        // the method and add the extra adjustment of the EC value.
1256
1257        ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec;
1258
1259        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
1260        if (spsr.mode == MODE_HYP) {
1261            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
1262        }
1263        return ec;
1264    }
1265}
1266
1267bool
1268PrefetchAbort::routeToMonitor(ThreadContext *tc) const
1269{
1270    SCR scr = 0;
1271    if (from64)
1272        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1273    else
1274        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1275
1276    return scr.ea && !isMMUFault();
1277}
1278
1279bool
1280PrefetchAbort::routeToHyp(ThreadContext *tc) const
1281{
1282    bool toHyp;
1283
1284    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1285    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1286    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1287    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
1288
1289    // if in Hyp mode then stay in Hyp mode
1290    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
1291    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
1292    toHyp |= (stage2 ||
1293                ( (source ==               DebugEvent) && hdcr.tde && (cpsr.mode !=  MODE_HYP)) ||
1294                ( (source == SynchronousExternalAbort) && hcr.tge  && (cpsr.mode == MODE_USER))
1295             ) && !inSecureState(tc);
1296    return toHyp;
1297}
1298
1299ExceptionClass
1300DataAbort::ec(ThreadContext *tc) const
1301{
1302    if (to64) {
1303        // AArch64
1304        if (source == ArmFault::AsynchronousExternalAbort) {
1305            panic("Asynchronous External Abort should be handled with "
1306                    "SystemErrors (SErrors)!");
1307        }
1308        if (toEL == fromEL)
1309            return EC_DATA_ABORT_CURR_EL;
1310        else
1311            return EC_DATA_ABORT_LOWER_EL;
1312    } else {
1313        // AArch32
1314        // Abort faults have different EC codes depending on whether
1315        // the fault originated within HYP mode, or not. So override
1316        // the method and add the extra adjustment of the EC value.
1317
1318        ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec;
1319
1320        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
1321        if (spsr.mode == MODE_HYP) {
1322            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
1323        }
1324        return ec;
1325    }
1326}
1327
1328bool
1329DataAbort::routeToMonitor(ThreadContext *tc) const
1330{
1331    SCR scr = 0;
1332    if (from64)
1333        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1334    else
1335        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1336
1337    return scr.ea && !isMMUFault();
1338}
1339
1340bool
1341DataAbort::routeToHyp(ThreadContext *tc) const
1342{
1343    bool toHyp;
1344
1345    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1346    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1347    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1348    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
1349
1350    // if in Hyp mode then stay in Hyp mode
1351    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
1352    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
1353    toHyp |= (stage2 ||
1354                ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) ||
1355                                               ((source == DebugEvent) && hdcr.tde) )
1356                ) ||
1357                ( (cpsr.mode == MODE_USER) && hcr.tge &&
1358                  ((source == AlignmentFault)            ||
1359                   (source == SynchronousExternalAbort))
1360                )
1361             ) && !inSecureState(tc);
1362    return toHyp;
1363}
1364
1365uint32_t
1366DataAbort::iss() const
1367{
1368    uint32_t val;
1369
1370    // Add on the data abort specific fields to the generic abort ISS value
1371    val  = AbortFault<DataAbort>::iss();
1372    // ISS is valid if not caused by a stage 1 page table walk, and when taken
1373    // to AArch64 only when directed to EL2
1374    if (!s1ptw && (!to64 || toEL == EL2)) {
1375        val |= isv << 24;
1376        if (isv) {
1377            val |= sas << 22;
1378            val |= sse << 21;
1379            val |= srt << 16;
1380            // AArch64 only. These assignments are safe on AArch32 as well
1381            // because these vars are initialized to false
1382            val |= sf << 15;
1383            val |= ar << 14;
1384        }
1385    }
1386    return (val);
1387}
1388
1389void
1390DataAbort::annotate(AnnotationIDs id, uint64_t val)
1391{
1392    AbortFault<DataAbort>::annotate(id, val);
1393    switch (id)
1394    {
1395      case SAS:
1396        isv = true;
1397        sas = val;
1398        break;
1399      case SSE:
1400        isv = true;
1401        sse = val;
1402        break;
1403      case SRT:
1404        isv = true;
1405        srt = val;
1406        break;
1407      case SF:
1408        isv = true;
1409        sf  = val;
1410        break;
1411      case AR:
1412        isv = true;
1413        ar  = val;
1414        break;
1415      // Just ignore unknown ID's
1416      default:
1417        break;
1418    }
1419}
1420
1421void
1422VirtualDataAbort::invoke(ThreadContext *tc, const StaticInstPtr &inst)
1423{
1424    AbortFault<VirtualDataAbort>::invoke(tc, inst);
1425    HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
1426    hcr.va = 0;
1427    tc->setMiscRegNoEffect(MISCREG_HCR, hcr);
1428}
1429
1430bool
1431Interrupt::routeToMonitor(ThreadContext *tc) const
1432{
1433    assert(ArmSystem::haveSecurity(tc));
1434    SCR scr = 0;
1435    if (from64)
1436        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1437    else
1438        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1439    return scr.irq;
1440}
1441
1442bool
1443Interrupt::routeToHyp(ThreadContext *tc) const
1444{
1445    bool toHyp;
1446
1447    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1448    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1449    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1450    // Determine whether IRQs are routed to Hyp mode.
1451    toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) ||
1452            (cpsr.mode == MODE_HYP);
1453    return toHyp;
1454}
1455
1456bool
1457Interrupt::abortDisable(ThreadContext *tc)
1458{
1459    if (ArmSystem::haveSecurity(tc)) {
1460        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1461        return (!scr.ns || scr.aw);
1462    }
1463    return true;
1464}
1465
1466VirtualInterrupt::VirtualInterrupt()
1467{}
1468
1469bool
1470FastInterrupt::routeToMonitor(ThreadContext *tc) const
1471{
1472    assert(ArmSystem::haveSecurity(tc));
1473    SCR scr = 0;
1474    if (from64)
1475        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1476    else
1477        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1478    return scr.fiq;
1479}
1480
1481bool
1482FastInterrupt::routeToHyp(ThreadContext *tc) const
1483{
1484    bool toHyp;
1485
1486    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1487    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1488    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1489    // Determine whether IRQs are routed to Hyp mode.
1490    toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) ||
1491            (cpsr.mode == MODE_HYP);
1492    return toHyp;
1493}
1494
1495bool
1496FastInterrupt::abortDisable(ThreadContext *tc)
1497{
1498    if (ArmSystem::haveSecurity(tc)) {
1499        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1500        return (!scr.ns || scr.aw);
1501    }
1502    return true;
1503}
1504
1505bool
1506FastInterrupt::fiqDisable(ThreadContext *tc)
1507{
1508    if (ArmSystem::haveVirtualization(tc)) {
1509        return true;
1510    } else if (ArmSystem::haveSecurity(tc)) {
1511        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1512        return (!scr.ns || scr.fw);
1513    }
1514    return true;
1515}
1516
1517VirtualFastInterrupt::VirtualFastInterrupt()
1518{}
1519
1520void
1521PCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
1522{
1523    ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
1524    assert(from64);
1525    // Set the FAR
1526    tc->setMiscReg(getFaultAddrReg64(), faultPC);
1527}
1528
1529bool
1530PCAlignmentFault::routeToHyp(ThreadContext *tc) const
1531{
1532    bool toHyp = false;
1533
1534    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1535    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
1536    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1537
1538    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
1539    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (currEL(tc) == EL0);
1540    return toHyp;
1541}
1542
1543SPAlignmentFault::SPAlignmentFault()
1544{}
1545
1546SystemError::SystemError()
1547{}
1548
1549void
1550SystemError::invoke(ThreadContext *tc, const StaticInstPtr &inst)
1551{
1552    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
1553    ArmFault::invoke(tc, inst);
1554}
1555
1556bool
1557SystemError::routeToMonitor(ThreadContext *tc) const
1558{
1559    assert(ArmSystem::haveSecurity(tc));
1560    assert(from64);
1561    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1562    return scr.ea;
1563}
1564
1565bool
1566SystemError::routeToHyp(ThreadContext *tc) const
1567{
1568    bool toHyp;
1569    assert(from64);
1570
1571    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1572    HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1573
1574    toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) ||
1575            (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc));
1576    return toHyp;
1577}
1578
1579
1580SoftwareBreakpoint::SoftwareBreakpoint(ExtMachInst _mach_inst, uint32_t _iss)
1581    : ArmFaultVals<SoftwareBreakpoint>(_mach_inst, _iss)
1582{}
1583
1584bool
1585SoftwareBreakpoint::routeToHyp(ThreadContext *tc) const
1586{
1587    const bool have_el2 = ArmSystem::haveVirtualization(tc);
1588
1589    const HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
1590    const HDCR mdcr  = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
1591
1592    return have_el2 && !inSecureState(tc) && fromEL <= EL1 &&
1593        (hcr.tge || mdcr.tde);
1594}
1595
1596ExceptionClass
1597SoftwareBreakpoint::ec(ThreadContext *tc) const
1598{
1599    return from64 ? EC_SOFTWARE_BREAKPOINT_64 : vals.ec;
1600}
1601
1602void
1603ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
1604    DPRINTF(Faults, "Invoking ArmSev Fault\n");
1605    if (!FullSystem)
1606        return;
1607
1608    // Set sev_mailbox to 1, clear the pending interrupt from remote
1609    // SEV execution and let pipeline continue as pcState is still
1610    // valid.
1611    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
1612    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0);
1613}
1614
1615// Instantiate all the templates to make the linker happy
1616template class ArmFaultVals<Reset>;
1617template class ArmFaultVals<UndefinedInstruction>;
1618template class ArmFaultVals<SupervisorCall>;
1619template class ArmFaultVals<SecureMonitorCall>;
1620template class ArmFaultVals<HypervisorCall>;
1621template class ArmFaultVals<PrefetchAbort>;
1622template class ArmFaultVals<DataAbort>;
1623template class ArmFaultVals<VirtualDataAbort>;
1624template class ArmFaultVals<HypervisorTrap>;
1625template class ArmFaultVals<Interrupt>;
1626template class ArmFaultVals<VirtualInterrupt>;
1627template class ArmFaultVals<FastInterrupt>;
1628template class ArmFaultVals<VirtualFastInterrupt>;
1629template class ArmFaultVals<SupervisorTrap>;
1630template class ArmFaultVals<SecureMonitorTrap>;
1631template class ArmFaultVals<PCAlignmentFault>;
1632template class ArmFaultVals<SPAlignmentFault>;
1633template class ArmFaultVals<SystemError>;
1634template class ArmFaultVals<SoftwareBreakpoint>;
1635template class ArmFaultVals<ArmSev>;
1636template class AbortFault<PrefetchAbort>;
1637template class AbortFault<DataAbort>;
1638template class AbortFault<VirtualDataAbort>;
1639
1640
1641IllegalInstSetStateFault::IllegalInstSetStateFault()
1642{}
1643
1644bool
1645getFaultVAddr(Fault fault, Addr &va)
1646{
1647    auto arm_fault = dynamic_cast<ArmFault *>(fault.get());
1648
1649    if (arm_fault) {
1650        return arm_fault->getFaultVAddr(va);
1651    } else {
1652        auto pgt_fault = dynamic_cast<GenericPageTableFault *>(fault.get());
1653        if (pgt_fault) {
1654            va = pgt_fault->getFaultVAddr();
1655            return true;
1656        }
1657
1658        auto align_fault = dynamic_cast<GenericAlignmentFault *>(fault.get());
1659        if (align_fault) {
1660            va = align_fault->getFaultVAddr();
1661            return true;
1662        }
1663
1664        // Return false since it's not an address triggered exception
1665        return false;
1666    }
1667}
1668
1669} // namespace ArmISA
1670