faults.cc revision 10367
12221SN/A/*
22221SN/A * Copyright (c) 2010, 2012-2014 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,
368778Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
373578Sgblack@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
393415Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
408750Sgblack@eecs.umich.edu *
413415Sgblack@eecs.umich.edu * Authors: Ali Saidi
422680Sktlim@umich.edu *          Gabe Black
433415Sgblack@eecs.umich.edu *          Giacomo Gabrielli
442800Ssaidi@eecs.umich.edu *          Thomas Grocutt
458750Sgblack@eecs.umich.edu */
462221SN/A
473415Sgblack@eecs.umich.edu#include "arch/arm/faults.hh"
483415Sgblack@eecs.umich.edu#include "arch/arm/system.hh"
492223SN/A#include "arch/arm/utility.hh"
502221SN/A#include "arch/arm/insts/static_inst.hh"
512221SN/A#include "base/compiler.hh"
523573Sgblack@eecs.umich.edu#include "base/trace.hh"
533576Sgblack@eecs.umich.edu#include "cpu/base.hh"
543576Sgblack@eecs.umich.edu#include "cpu/thread_context.hh"
552221SN/A#include "debug/Faults.hh"
563573Sgblack@eecs.umich.edu#include "sim/full_system.hh"
573576Sgblack@eecs.umich.edu
583576Sgblack@eecs.umich.edunamespace ArmISA
592221SN/A{
603573Sgblack@eecs.umich.edu
613576Sgblack@eecs.umich.eduuint8_t ArmFault::shortDescFaultSources[] = {
623576Sgblack@eecs.umich.edu    0x01,  // AlignmentFault
632221SN/A    0x04,  // InstructionCacheMaintenance
643573Sgblack@eecs.umich.edu    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
653576Sgblack@eecs.umich.edu    0x0c,  // SynchExtAbtOnTranslTableWalkL1
663576Sgblack@eecs.umich.edu    0x0e,  // SynchExtAbtOnTranslTableWalkL2
672221SN/A    0xff,  // SynchExtAbtOnTranslTableWalkL3 (INVALID)
683573Sgblack@eecs.umich.edu    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
693576Sgblack@eecs.umich.edu    0x1c,  // SynchPtyErrOnTranslTableWalkL1
703576Sgblack@eecs.umich.edu    0x1e,  // SynchPtyErrOnTranslTableWalkL2
712221SN/A    0xff,  // SynchPtyErrOnTranslTableWalkL3 (INVALID)
723573Sgblack@eecs.umich.edu    0xff,  // TranslationL0 (INVALID)
733576Sgblack@eecs.umich.edu    0x05,  // TranslationL1
743576Sgblack@eecs.umich.edu    0x07,  // TranslationL2
752221SN/A    0xff,  // TranslationL3 (INVALID)
763573Sgblack@eecs.umich.edu    0xff,  // AccessFlagL0 (INVALID)
773576Sgblack@eecs.umich.edu    0x03,  // AccessFlagL1
783576Sgblack@eecs.umich.edu    0x06,  // AccessFlagL2
793576Sgblack@eecs.umich.edu    0xff,  // AccessFlagL3 (INVALID)
803576Sgblack@eecs.umich.edu    0xff,  // DomainL0 (INVALID)
813576Sgblack@eecs.umich.edu    0x09,  // DomainL1
823576Sgblack@eecs.umich.edu    0x0b,  // DomainL2
833576Sgblack@eecs.umich.edu    0xff,  // DomainL3 (INVALID)
842221SN/A    0xff,  // PermissionL0 (INVALID)
853573Sgblack@eecs.umich.edu    0x0d,  // PermissionL1
863576Sgblack@eecs.umich.edu    0x0f,  // PermissionL2
873576Sgblack@eecs.umich.edu    0xff,  // PermissionL3 (INVALID)
882221SN/A    0x02,  // DebugEvent
893573Sgblack@eecs.umich.edu    0x08,  // SynchronousExternalAbort
903576Sgblack@eecs.umich.edu    0x10,  // TLBConflictAbort
913576Sgblack@eecs.umich.edu    0x19,  // SynchPtyErrOnMemoryAccess
922221SN/A    0x16,  // AsynchronousExternalAbort
933573Sgblack@eecs.umich.edu    0x18,  // AsynchPtyErrOnMemoryAccess
943576Sgblack@eecs.umich.edu    0xff,  // AddressSizeL0 (INVALID)
953576Sgblack@eecs.umich.edu    0xff,  // AddressSizeL1 (INVALID)
963576Sgblack@eecs.umich.edu    0xff,  // AddressSizeL2 (INVALID)
973576Sgblack@eecs.umich.edu    0xff,  // AddressSizeL3 (INVALID)
983576Sgblack@eecs.umich.edu    0x40,  // PrefetchTLBMiss
993576Sgblack@eecs.umich.edu    0x80   // PrefetchUncacheable
1003576Sgblack@eecs.umich.edu};
1013576Sgblack@eecs.umich.edu
1023576Sgblack@eecs.umich.edustatic_assert(sizeof(ArmFault::shortDescFaultSources) ==
1033576Sgblack@eecs.umich.edu              ArmFault::NumFaultSources,
1043576Sgblack@eecs.umich.edu              "Invalid size of ArmFault::shortDescFaultSources[]");
1053576Sgblack@eecs.umich.edu
1062221SN/Auint8_t ArmFault::longDescFaultSources[] = {
1073573Sgblack@eecs.umich.edu    0x21,  // AlignmentFault
1083576Sgblack@eecs.umich.edu    0xff,  // InstructionCacheMaintenance (INVALID)
1093576Sgblack@eecs.umich.edu    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
1102221SN/A    0x15,  // SynchExtAbtOnTranslTableWalkL1
1113573Sgblack@eecs.umich.edu    0x16,  // SynchExtAbtOnTranslTableWalkL2
1123576Sgblack@eecs.umich.edu    0x17,  // SynchExtAbtOnTranslTableWalkL3
1133576Sgblack@eecs.umich.edu    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
1142221SN/A    0x1d,  // SynchPtyErrOnTranslTableWalkL1
1153573Sgblack@eecs.umich.edu    0x1e,  // SynchPtyErrOnTranslTableWalkL2
1163576Sgblack@eecs.umich.edu    0x1f,  // SynchPtyErrOnTranslTableWalkL3
1173576Sgblack@eecs.umich.edu    0xff,  // TranslationL0 (INVALID)
1182221SN/A    0x05,  // TranslationL1
1193573Sgblack@eecs.umich.edu    0x06,  // TranslationL2
1203576Sgblack@eecs.umich.edu    0x07,  // TranslationL3
1213576Sgblack@eecs.umich.edu    0xff,  // AccessFlagL0 (INVALID)
1222221SN/A    0x09,  // AccessFlagL1
1233573Sgblack@eecs.umich.edu    0x0a,  // AccessFlagL2
1243576Sgblack@eecs.umich.edu    0x0b,  // AccessFlagL3
1253576Sgblack@eecs.umich.edu    0xff,  // DomainL0 (INVALID)
1262221SN/A    0x3d,  // DomainL1
1273573Sgblack@eecs.umich.edu    0x3e,  // DomainL2
1283576Sgblack@eecs.umich.edu    0xff,  // DomainL3 (RESERVED)
1293576Sgblack@eecs.umich.edu    0xff,  // PermissionL0 (INVALID)
1302223SN/A    0x0d,  // PermissionL1
1313573Sgblack@eecs.umich.edu    0x0e,  // PermissionL2
1323576Sgblack@eecs.umich.edu    0x0f,  // PermissionL3
1333576Sgblack@eecs.umich.edu    0x22,  // DebugEvent
1342223SN/A    0x10,  // SynchronousExternalAbort
1353573Sgblack@eecs.umich.edu    0x30,  // TLBConflictAbort
1363576Sgblack@eecs.umich.edu    0x18,  // SynchPtyErrOnMemoryAccess
1373576Sgblack@eecs.umich.edu    0x11,  // AsynchronousExternalAbort
1382223SN/A    0x19,  // AsynchPtyErrOnMemoryAccess
1393573Sgblack@eecs.umich.edu    0xff,  // AddressSizeL0 (INVALID)
1403576Sgblack@eecs.umich.edu    0xff,  // AddressSizeL1 (INVALID)
1413576Sgblack@eecs.umich.edu    0xff,  // AddressSizeL2 (INVALID)
1422223SN/A    0xff,  // AddressSizeL3 (INVALID)
1433573Sgblack@eecs.umich.edu    0x40,  // PrefetchTLBMiss
1443576Sgblack@eecs.umich.edu    0x80   // PrefetchUncacheable
1453576Sgblack@eecs.umich.edu};
1463576Sgblack@eecs.umich.edu
1473576Sgblack@eecs.umich.edustatic_assert(sizeof(ArmFault::longDescFaultSources) ==
1483576Sgblack@eecs.umich.edu              ArmFault::NumFaultSources,
1493576Sgblack@eecs.umich.edu              "Invalid size of ArmFault::longDescFaultSources[]");
1503576Sgblack@eecs.umich.edu
1512223SN/Auint8_t ArmFault::aarch64FaultSources[] = {
1523573Sgblack@eecs.umich.edu    0x21,  // AlignmentFault
1533576Sgblack@eecs.umich.edu    0xff,  // InstructionCacheMaintenance (INVALID)
1543576Sgblack@eecs.umich.edu    0x14,  // SynchExtAbtOnTranslTableWalkL0
1552223SN/A    0x15,  // SynchExtAbtOnTranslTableWalkL1
1563573Sgblack@eecs.umich.edu    0x16,  // SynchExtAbtOnTranslTableWalkL2
1573576Sgblack@eecs.umich.edu    0x17,  // SynchExtAbtOnTranslTableWalkL3
1583576Sgblack@eecs.umich.edu    0x1c,  // SynchPtyErrOnTranslTableWalkL0
1592223SN/A    0x1d,  // SynchPtyErrOnTranslTableWalkL1
1603573Sgblack@eecs.umich.edu    0x1e,  // SynchPtyErrOnTranslTableWalkL2
1613576Sgblack@eecs.umich.edu    0x1f,  // SynchPtyErrOnTranslTableWalkL3
1623576Sgblack@eecs.umich.edu    0x04,  // TranslationL0
1632223SN/A    0x05,  // TranslationL1
1643573Sgblack@eecs.umich.edu    0x06,  // TranslationL2
1653576Sgblack@eecs.umich.edu    0x07,  // TranslationL3
1663576Sgblack@eecs.umich.edu    0x08,  // AccessFlagL0
1672223SN/A    0x09,  // AccessFlagL1
1683573Sgblack@eecs.umich.edu    0x0a,  // AccessFlagL2
1693576Sgblack@eecs.umich.edu    0x0b,  // AccessFlagL3
1703576Sgblack@eecs.umich.edu    // @todo: Section & Page Domain Fault in AArch64?
1712223SN/A    0xff,  // DomainL0 (INVALID)
1723573Sgblack@eecs.umich.edu    0xff,  // DomainL1 (INVALID)
1733576Sgblack@eecs.umich.edu    0xff,  // DomainL2 (INVALID)
1743576Sgblack@eecs.umich.edu    0xff,  // DomainL3 (INVALID)
1752223SN/A    0x0c,  // PermissionL0
1763573Sgblack@eecs.umich.edu    0x0d,  // PermissionL1
1773576Sgblack@eecs.umich.edu    0x0e,  // PermissionL2
1783576Sgblack@eecs.umich.edu    0x0f,  // PermissionL3
1792223SN/A    0xff,  // DebugEvent (INVALID)
1803573Sgblack@eecs.umich.edu    0x10,  // SynchronousExternalAbort
1813576Sgblack@eecs.umich.edu    0x30,  // TLBConflictAbort
1823576Sgblack@eecs.umich.edu    0x18,  // SynchPtyErrOnMemoryAccess
1832223SN/A    0xff,  // AsynchronousExternalAbort (INVALID)
1843573Sgblack@eecs.umich.edu    0xff,  // AsynchPtyErrOnMemoryAccess (INVALID)
1853576Sgblack@eecs.umich.edu    0x00,  // AddressSizeL0
1863576Sgblack@eecs.umich.edu    0x01,  // AddressSizeL1
1872223SN/A    0x02,  // AddressSizeL2
1883573Sgblack@eecs.umich.edu    0x03,  // AddressSizeL3
1893576Sgblack@eecs.umich.edu    0x40,  // PrefetchTLBMiss
1903576Sgblack@eecs.umich.edu    0x80   // PrefetchUncacheable
1912223SN/A};
1923576Sgblack@eecs.umich.edu
1933576Sgblack@eecs.umich.edustatic_assert(sizeof(ArmFault::aarch64FaultSources) ==
1943576Sgblack@eecs.umich.edu              ArmFault::NumFaultSources,
1953576Sgblack@eecs.umich.edu              "Invalid size of ArmFault::aarch64FaultSources[]");
1962527SN/A
1973573Sgblack@eecs.umich.edu// Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode,
1983576Sgblack@eecs.umich.edu//         {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap,
1993890Ssaidi@eecs.umich.edu//         {A, F} disable, class, stat
2002223SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals = {
2013573Sgblack@eecs.umich.edu    // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED
2023576Sgblack@eecs.umich.edu    // location in AArch64)
2033576Sgblack@eecs.umich.edu    "Reset",                 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2042223SN/A    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2053573Sgblack@eecs.umich.edu};
2063576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals = {
2073576Sgblack@eecs.umich.edu    "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
2082223SN/A    4, 2, 0, 0, true,  false, false, EC_UNKNOWN, FaultStat()
2093573Sgblack@eecs.umich.edu};
2104103Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals = {
2114103Ssaidi@eecs.umich.edu    "Supervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2124103Ssaidi@eecs.umich.edu    4, 2, 4, 2, true,  false, false, EC_SVC_TO_HYP, FaultStat()
2134103Ssaidi@eecs.umich.edu};
2143576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals = {
2153576Sgblack@eecs.umich.edu    "Secure Monitor Call",   0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2162223SN/A    4, 4, 4, 4, false, true,  true,  EC_SMC_TO_HYP, FaultStat()
2173573Sgblack@eecs.umich.edu};
2183576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals = {
2193576Sgblack@eecs.umich.edu    "Hypervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2202223SN/A    4, 4, 4, 4, true,  false, false, EC_HVC, FaultStat()
2213573Sgblack@eecs.umich.edu};
2223576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals = {
2233576Sgblack@eecs.umich.edu    "Prefetch Abort",        0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2243576Sgblack@eecs.umich.edu    4, 4, 0, 0, true,  true,  false, EC_PREFETCH_ABORT_TO_HYP, FaultStat()
2253576Sgblack@eecs.umich.edu};
2263576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals = {
2273576Sgblack@eecs.umich.edu    "Data Abort",            0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2283576Sgblack@eecs.umich.edu    8, 8, 0, 0, true,  true,  false, EC_DATA_ABORT_TO_HYP, FaultStat()
2293576Sgblack@eecs.umich.edu};
2303576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals = {
2313576Sgblack@eecs.umich.edu    "Virtual Data Abort",    0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2323576Sgblack@eecs.umich.edu    8, 8, 0, 0, true,  true,  false, EC_INVALID, FaultStat()
2333576Sgblack@eecs.umich.edu};
2343576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals = {
2353576Sgblack@eecs.umich.edu    // @todo: double check these values
2363576Sgblack@eecs.umich.edu    "Hypervisor Trap",       0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2373576Sgblack@eecs.umich.edu    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
2383576Sgblack@eecs.umich.edu};
2393576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals = {
2403576Sgblack@eecs.umich.edu    "IRQ",                   0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2413576Sgblack@eecs.umich.edu    4, 4, 0, 0, false, true,  false, EC_UNKNOWN, FaultStat()
2423576Sgblack@eecs.umich.edu};
2433576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals = {
2443576Sgblack@eecs.umich.edu    "Virtual IRQ",           0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2453576Sgblack@eecs.umich.edu    4, 4, 0, 0, false, true,  false, EC_INVALID, FaultStat()
2463893Shsul@eecs.umich.edu};
2473576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals = {
2483576Sgblack@eecs.umich.edu    "FIQ",                   0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2493576Sgblack@eecs.umich.edu    4, 4, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2503576Sgblack@eecs.umich.edu};
2513576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals = {
2523576Sgblack@eecs.umich.edu    "Virtual FIQ",           0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2533576Sgblack@eecs.umich.edu    4, 4, 0, 0, false, true,  true,  EC_INVALID, FaultStat()
2543576Sgblack@eecs.umich.edu};
2553576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals = {
2563576Sgblack@eecs.umich.edu    // Some dummy values (SupervisorTrap is AArch64-only)
2573576Sgblack@eecs.umich.edu    "Supervisor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2583576Sgblack@eecs.umich.edu    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
2593576Sgblack@eecs.umich.edu};
2603576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals = {
2613576Sgblack@eecs.umich.edu    // Some dummy values (SecureMonitorTrap is AArch64-only)
2623576Sgblack@eecs.umich.edu    "Secure Monitor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2633576Sgblack@eecs.umich.edu    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
2643576Sgblack@eecs.umich.edu};
2653576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals = {
2663576Sgblack@eecs.umich.edu    // Some dummy values (PCAlignmentFault is AArch64-only)
2673576Sgblack@eecs.umich.edu    "PC Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2682223SN/A    0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT, FaultStat()
2693415Sgblack@eecs.umich.edu};
2703578Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals = {
2713578Sgblack@eecs.umich.edu    // Some dummy values (SPAlignmentFault is AArch64-only)
2723415Sgblack@eecs.umich.edu    "SP Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2733415Sgblack@eecs.umich.edu    0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT, FaultStat()
2747741Sgblack@eecs.umich.edu};
2757741Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals = {
2763415Sgblack@eecs.umich.edu    // Some dummy values (SError is AArch64-only)
2773578Sgblack@eecs.umich.edu    "SError",                0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC,
2783578Sgblack@eecs.umich.edu    0, 0, 0, 0, false, true,  true,  EC_SERROR, FaultStat()
2794172Ssaidi@eecs.umich.edu};
2807741Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<FlushPipe>::vals = {
2813578Sgblack@eecs.umich.edu    // Some dummy values
2827741Sgblack@eecs.umich.edu    "Pipe Flush",            0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2833578Sgblack@eecs.umich.edu    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2844172Ssaidi@eecs.umich.edu};
2857741Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals = {
2867741Sgblack@eecs.umich.edu    // Some dummy values
2874172Ssaidi@eecs.umich.edu    "ArmSev Flush",          0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2883746Sgblack@eecs.umich.edu    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2894172Ssaidi@eecs.umich.edu};
2903578Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals = {
2913578Sgblack@eecs.umich.edu    // Some dummy values (SPAlignmentFault is AArch64-only)
2923578Sgblack@eecs.umich.edu    "Illegal Inst Set State Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2933578Sgblack@eecs.umich.edu    0, 0, 0, 0, true, false, false, EC_ILLEGAL_INST, FaultStat()
2943578Sgblack@eecs.umich.edu};
2953578Sgblack@eecs.umich.edu
2963578Sgblack@eecs.umich.eduAddr
2977741Sgblack@eecs.umich.eduArmFault::getVector(ThreadContext *tc)
2987741Sgblack@eecs.umich.edu{
2993578Sgblack@eecs.umich.edu    Addr base;
3004172Ssaidi@eecs.umich.edu
3014172Ssaidi@eecs.umich.edu    // ARM ARM issue C B1.8.1
3024172Ssaidi@eecs.umich.edu    bool haveSecurity = ArmSystem::haveSecurity(tc);
3034172Ssaidi@eecs.umich.edu
3043761Sgblack@eecs.umich.edu    // panic if SCTLR.VE because I have no idea what to do with vectored
3054172Ssaidi@eecs.umich.edu    // interrupts
3064172Ssaidi@eecs.umich.edu    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
3074172Ssaidi@eecs.umich.edu    assert(!sctlr.ve);
3084172Ssaidi@eecs.umich.edu    // Check for invalid modes
3097720Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
3103578Sgblack@eecs.umich.edu    assert(haveSecurity                      || cpsr.mode != MODE_MON);
3113578Sgblack@eecs.umich.edu    assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
3123578Sgblack@eecs.umich.edu
3137720Sgblack@eecs.umich.edu    switch (cpsr.mode)
3143928Ssaidi@eecs.umich.edu    {
3157741Sgblack@eecs.umich.edu      case MODE_MON:
3163578Sgblack@eecs.umich.edu        base = tc->readMiscReg(MISCREG_MVBAR);
3177741Sgblack@eecs.umich.edu        break;
3183578Sgblack@eecs.umich.edu      case MODE_HYP:
3197741Sgblack@eecs.umich.edu        base = tc->readMiscReg(MISCREG_HVBAR);
3203578Sgblack@eecs.umich.edu        break;
3217741Sgblack@eecs.umich.edu      default:
3223578Sgblack@eecs.umich.edu        if (sctlr.v) {
3237741Sgblack@eecs.umich.edu            base = HighVecs;
3243578Sgblack@eecs.umich.edu        } else {
3253578Sgblack@eecs.umich.edu            base = haveSecurity ? tc->readMiscReg(MISCREG_VBAR) : 0;
3267741Sgblack@eecs.umich.edu        }
3274172Ssaidi@eecs.umich.edu        break;
3283578Sgblack@eecs.umich.edu    }
3297741Sgblack@eecs.umich.edu    return base + offset(tc);
3307720Sgblack@eecs.umich.edu}
3317741Sgblack@eecs.umich.edu
3327720Sgblack@eecs.umich.eduAddr
3333578Sgblack@eecs.umich.eduArmFault::getVector64(ThreadContext *tc)
3347741Sgblack@eecs.umich.edu{
3354172Ssaidi@eecs.umich.edu    Addr vbar;
3363578Sgblack@eecs.umich.edu    switch (toEL) {
3377741Sgblack@eecs.umich.edu      case EL3:
3384172Ssaidi@eecs.umich.edu        assert(ArmSystem::haveSecurity(tc));
3393578Sgblack@eecs.umich.edu        vbar = tc->readMiscReg(MISCREG_VBAR_EL3);
3407741Sgblack@eecs.umich.edu        break;
3414172Ssaidi@eecs.umich.edu      // @todo: uncomment this to enable Virtualization
3423578Sgblack@eecs.umich.edu      // case EL2:
3433926Ssaidi@eecs.umich.edu      //   assert(ArmSystem::haveVirtualization(tc));
3447741Sgblack@eecs.umich.edu      //   vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
3454172Ssaidi@eecs.umich.edu      //   break;
3463578Sgblack@eecs.umich.edu      case EL1:
3477741Sgblack@eecs.umich.edu        vbar = tc->readMiscReg(MISCREG_VBAR_EL1);
3483578Sgblack@eecs.umich.edu        break;
3497741Sgblack@eecs.umich.edu      default:
3503578Sgblack@eecs.umich.edu        panic("Invalid target exception level");
3517741Sgblack@eecs.umich.edu        break;
3523578Sgblack@eecs.umich.edu    }
3537741Sgblack@eecs.umich.edu    return vbar + offset64();
3543578Sgblack@eecs.umich.edu}
3554172Ssaidi@eecs.umich.edu
3563578Sgblack@eecs.umich.eduMiscRegIndex
3573578Sgblack@eecs.umich.eduArmFault::getSyndromeReg64() const
3583893Shsul@eecs.umich.edu{
3593415Sgblack@eecs.umich.edu    switch (toEL) {
3603893Shsul@eecs.umich.edu      case EL1:
3613415Sgblack@eecs.umich.edu        return MISCREG_ESR_EL1;
3623893Shsul@eecs.umich.edu      case EL2:
3633415Sgblack@eecs.umich.edu        return MISCREG_ESR_EL2;
3643415Sgblack@eecs.umich.edu      case EL3:
3653415Sgblack@eecs.umich.edu        return MISCREG_ESR_EL3;
3663420Sgblack@eecs.umich.edu      default:
3677741Sgblack@eecs.umich.edu        panic("Invalid exception level");
3683415Sgblack@eecs.umich.edu        break;
3694172Ssaidi@eecs.umich.edu    }
3703415Sgblack@eecs.umich.edu}
3713415Sgblack@eecs.umich.edu
3723415Sgblack@eecs.umich.eduMiscRegIndex
3737741Sgblack@eecs.umich.eduArmFault::getFaultAddrReg64() const
3747741Sgblack@eecs.umich.edu{
3757741Sgblack@eecs.umich.edu    switch (toEL) {
3767741Sgblack@eecs.umich.edu      case EL1:
3777741Sgblack@eecs.umich.edu        return MISCREG_FAR_EL1;
3787741Sgblack@eecs.umich.edu      case EL2:
3797741Sgblack@eecs.umich.edu        return MISCREG_FAR_EL2;
3807741Sgblack@eecs.umich.edu      case EL3:
3817741Sgblack@eecs.umich.edu        return MISCREG_FAR_EL3;
3827741Sgblack@eecs.umich.edu      default:
3837741Sgblack@eecs.umich.edu        panic("Invalid exception level");
3847741Sgblack@eecs.umich.edu        break;
3857741Sgblack@eecs.umich.edu    }
3867741Sgblack@eecs.umich.edu}
3877741Sgblack@eecs.umich.edu
3887741Sgblack@eecs.umich.eduvoid
3897741Sgblack@eecs.umich.eduArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
3907741Sgblack@eecs.umich.edu{
3917741Sgblack@eecs.umich.edu    uint32_t value;
3927741Sgblack@eecs.umich.edu    uint32_t exc_class = (uint32_t) ec(tc);
3937741Sgblack@eecs.umich.edu    uint32_t issVal = iss();
3947741Sgblack@eecs.umich.edu    assert(!from64 || ArmSystem::highestELIs64(tc));
3957741Sgblack@eecs.umich.edu
3967741Sgblack@eecs.umich.edu    value = exc_class << 26;
3977741Sgblack@eecs.umich.edu
3987741Sgblack@eecs.umich.edu    // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24,
3997741Sgblack@eecs.umich.edu    // 0x25) for which the ISS information is not valid (ARMv7).
4007741Sgblack@eecs.umich.edu    // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not
4017741Sgblack@eecs.umich.edu    // valid it is treated as RES1.
4027741Sgblack@eecs.umich.edu    if (to64) {
4037741Sgblack@eecs.umich.edu        value |= 1 << 25;
4047741Sgblack@eecs.umich.edu    } else if ((bits(exc_class, 5, 3) != 4) ||
4057741Sgblack@eecs.umich.edu               (bits(exc_class, 2) && bits(issVal, 24))) {
4067741Sgblack@eecs.umich.edu        if (!machInst.thumb || machInst.bigThumb)
4077741Sgblack@eecs.umich.edu            value |= 1 << 25;
4087741Sgblack@eecs.umich.edu    }
4097741Sgblack@eecs.umich.edu    // Condition code valid for EC[5:4] nonzero
4107741Sgblack@eecs.umich.edu    if (!from64 && ((bits(exc_class, 5, 4) == 0) &&
4117741Sgblack@eecs.umich.edu                    (bits(exc_class, 3, 0) != 0))) {
4127741Sgblack@eecs.umich.edu        if (!machInst.thumb) {
4137741Sgblack@eecs.umich.edu            uint32_t      cond;
4147741Sgblack@eecs.umich.edu            ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode;
4157741Sgblack@eecs.umich.edu            // If its on unconditional instruction report with a cond code of
4167741Sgblack@eecs.umich.edu            // 0xE, ie the unconditional code
4177741Sgblack@eecs.umich.edu            cond  = (condCode == COND_UC) ? COND_AL : condCode;
4187741Sgblack@eecs.umich.edu            value |= cond << 20;
4197741Sgblack@eecs.umich.edu            value |= 1    << 24;
4207741Sgblack@eecs.umich.edu        }
4217741Sgblack@eecs.umich.edu        value |= bits(issVal, 19, 0);
4227741Sgblack@eecs.umich.edu    } else {
4237741Sgblack@eecs.umich.edu        value |= issVal;
4247741Sgblack@eecs.umich.edu    }
4257741Sgblack@eecs.umich.edu    tc->setMiscReg(syndrome_reg, value);
4267741Sgblack@eecs.umich.edu}
4277741Sgblack@eecs.umich.edu
4287741Sgblack@eecs.umich.eduvoid
4297741Sgblack@eecs.umich.eduArmFault::invoke(ThreadContext *tc, StaticInstPtr inst)
4307741Sgblack@eecs.umich.edu{
4317741Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
4327741Sgblack@eecs.umich.edu
4337741Sgblack@eecs.umich.edu    if (ArmSystem::highestELIs64(tc)) {  // ARMv8
4347741Sgblack@eecs.umich.edu        // Determine source exception level and mode
4357741Sgblack@eecs.umich.edu        fromMode = (OperatingMode) (uint8_t) cpsr.mode;
4367741Sgblack@eecs.umich.edu        fromEL = opModeToEL(fromMode);
4377741Sgblack@eecs.umich.edu        if (opModeIs64(fromMode))
4387741Sgblack@eecs.umich.edu            from64 = true;
4397741Sgblack@eecs.umich.edu
4407741Sgblack@eecs.umich.edu        // Determine target exception level
4417741Sgblack@eecs.umich.edu        if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc))
4427741Sgblack@eecs.umich.edu            toEL = EL3;
4437741Sgblack@eecs.umich.edu        else
4447741Sgblack@eecs.umich.edu            toEL = opModeToEL(nextMode());
4457741Sgblack@eecs.umich.edu        if (fromEL > toEL)
4467741Sgblack@eecs.umich.edu            toEL = fromEL;
4477741Sgblack@eecs.umich.edu
4487741Sgblack@eecs.umich.edu        if (toEL == ArmSystem::highestEL(tc) || ELIs64(tc, toEL)) {
4497741Sgblack@eecs.umich.edu            // Invoke exception handler in AArch64 state
4507741Sgblack@eecs.umich.edu            to64 = true;
4517741Sgblack@eecs.umich.edu            invoke64(tc, inst);
4527741Sgblack@eecs.umich.edu            return;
4537741Sgblack@eecs.umich.edu        }
4547741Sgblack@eecs.umich.edu    }
4557741Sgblack@eecs.umich.edu
4567741Sgblack@eecs.umich.edu    // ARMv7 (ARM ARM issue C B1.9)
4577741Sgblack@eecs.umich.edu
4587741Sgblack@eecs.umich.edu    bool have_security       = ArmSystem::haveSecurity(tc);
4597741Sgblack@eecs.umich.edu    bool have_virtualization = ArmSystem::haveVirtualization(tc);
4607741Sgblack@eecs.umich.edu
4617741Sgblack@eecs.umich.edu    FaultBase::invoke(tc);
4627741Sgblack@eecs.umich.edu    if (!FullSystem)
4637741Sgblack@eecs.umich.edu        return;
4647741Sgblack@eecs.umich.edu    countStat()++;
4657741Sgblack@eecs.umich.edu
4667741Sgblack@eecs.umich.edu    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
4677741Sgblack@eecs.umich.edu    SCR scr = tc->readMiscReg(MISCREG_SCR);
4687741Sgblack@eecs.umich.edu    CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR);
4697741Sgblack@eecs.umich.edu    saved_cpsr.nz = tc->readCCReg(CCREG_NZ);
4707741Sgblack@eecs.umich.edu    saved_cpsr.c = tc->readCCReg(CCREG_C);
4713578Sgblack@eecs.umich.edu    saved_cpsr.v = tc->readCCReg(CCREG_V);
4723585Sgblack@eecs.umich.edu    saved_cpsr.ge = tc->readCCReg(CCREG_GE);
4733603Ssaidi@eecs.umich.edu
4743595Sgblack@eecs.umich.edu    Addr curPc M5_VAR_USED = tc->pcState().pc();
4753578Sgblack@eecs.umich.edu    ITSTATE it = tc->pcState().itstate();
4763578Sgblack@eecs.umich.edu    saved_cpsr.it2 = it.top6;
4773578Sgblack@eecs.umich.edu    saved_cpsr.it1 = it.bottom2;
4787741Sgblack@eecs.umich.edu
4797741Sgblack@eecs.umich.edu    // if we have a valid instruction then use it to annotate this fault with
4803578Sgblack@eecs.umich.edu    // extra information. This is used to generate the correct fault syndrome
4814172Ssaidi@eecs.umich.edu    // information
4823578Sgblack@eecs.umich.edu    if (inst) {
4833578Sgblack@eecs.umich.edu        ArmStaticInst *armInst = reinterpret_cast<ArmStaticInst *>(inst.get());
4843578Sgblack@eecs.umich.edu        armInst->annotateFault(this);
4853578Sgblack@eecs.umich.edu    }
4867741Sgblack@eecs.umich.edu
4877741Sgblack@eecs.umich.edu    if (have_security && routeToMonitor(tc))
4883578Sgblack@eecs.umich.edu        cpsr.mode = MODE_MON;
4894172Ssaidi@eecs.umich.edu    else if (have_virtualization && routeToHyp(tc))
4903578Sgblack@eecs.umich.edu        cpsr.mode = MODE_HYP;
4913578Sgblack@eecs.umich.edu    else
4923578Sgblack@eecs.umich.edu        cpsr.mode = nextMode();
4933578Sgblack@eecs.umich.edu
4943578Sgblack@eecs.umich.edu    // Ensure Secure state if initially in Monitor mode
4953578Sgblack@eecs.umich.edu    if (have_security && saved_cpsr.mode == MODE_MON) {
4967741Sgblack@eecs.umich.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
4977741Sgblack@eecs.umich.edu        if (scr.ns) {
4982221SN/A            scr.ns = 0;
4992680Sktlim@umich.edu            tc->setMiscRegNoEffect(MISCREG_SCR, scr);
5008750Sgblack@eecs.umich.edu        }
5018750Sgblack@eecs.umich.edu    }
5028750Sgblack@eecs.umich.edu
5032223SN/A    // some bits are set differently if we have been routed to hyp mode
5042221SN/A    if (cpsr.mode == MODE_HYP) {
5057741Sgblack@eecs.umich.edu        SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR);
5067741Sgblack@eecs.umich.edu        cpsr.t = hsctlr.te;
5074172Ssaidi@eecs.umich.edu        cpsr.e = hsctlr.ee;
5084172Ssaidi@eecs.umich.edu        if (!scr.ea)  {cpsr.a = 1;}
5094172Ssaidi@eecs.umich.edu        if (!scr.fiq) {cpsr.f = 1;}
5104172Ssaidi@eecs.umich.edu        if (!scr.irq) {cpsr.i = 1;}
5113578Sgblack@eecs.umich.edu    } else if (cpsr.mode == MODE_MON) {
5123578Sgblack@eecs.umich.edu        // Special case handling when entering monitor mode
5133578Sgblack@eecs.umich.edu        cpsr.t = sctlr.te;
5143578Sgblack@eecs.umich.edu        cpsr.e = sctlr.ee;
5153893Shsul@eecs.umich.edu        cpsr.a = 1;
5163746Sgblack@eecs.umich.edu        cpsr.f = 1;
5173893Shsul@eecs.umich.edu        cpsr.i = 1;
5183578Sgblack@eecs.umich.edu    } else {
5193578Sgblack@eecs.umich.edu        cpsr.t = sctlr.te;
5203746Sgblack@eecs.umich.edu        cpsr.e = sctlr.ee;
5213578Sgblack@eecs.umich.edu
5223578Sgblack@eecs.umich.edu        // The *Disable functions are virtual and different per fault
5233578Sgblack@eecs.umich.edu        cpsr.a = cpsr.a | abortDisable(tc);
5243893Shsul@eecs.umich.edu        cpsr.f = cpsr.f | fiqDisable(tc);
5253595Sgblack@eecs.umich.edu        cpsr.i = 1;
5263893Shsul@eecs.umich.edu    }
5277741Sgblack@eecs.umich.edu    cpsr.it1 = cpsr.it2 = 0;
5287741Sgblack@eecs.umich.edu    cpsr.j = 0;
5293578Sgblack@eecs.umich.edu    tc->setMiscReg(MISCREG_CPSR, cpsr);
5303893Shsul@eecs.umich.edu
5313825Ssaidi@eecs.umich.edu    // Make sure mailbox sets to one always
5327741Sgblack@eecs.umich.edu    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
5337741Sgblack@eecs.umich.edu
5347741Sgblack@eecs.umich.edu    // Clear the exclusive monitor
5353893Shsul@eecs.umich.edu    tc->setMiscReg(MISCREG_LOCKFLAG, 0);
5367741Sgblack@eecs.umich.edu
5373578Sgblack@eecs.umich.edu    if (cpsr.mode == MODE_HYP) {
5383585Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_ELR_HYP, curPc +
5393893Shsul@eecs.umich.edu                (saved_cpsr.t ? thumbPcOffset(true)  : armPcOffset(true)));
5405570Snate@binkert.org    } else {
5413578Sgblack@eecs.umich.edu        tc->setIntReg(INTREG_LR, curPc +
5423585Sgblack@eecs.umich.edu                (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false)));
5433826Ssaidi@eecs.umich.edu    }
5443578Sgblack@eecs.umich.edu
5457741Sgblack@eecs.umich.edu    switch (cpsr.mode) {
5463578Sgblack@eecs.umich.edu      case MODE_FIQ:
5473578Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
5487720Sgblack@eecs.umich.edu        break;
5497720Sgblack@eecs.umich.edu      case MODE_IRQ:
5507720Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
5517720Sgblack@eecs.umich.edu        break;
5527720Sgblack@eecs.umich.edu      case MODE_SVC:
5537720Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
5547720Sgblack@eecs.umich.edu        break;
5553420Sgblack@eecs.umich.edu      case MODE_MON:
5562221SN/A        assert(have_security);
5577741Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr);
5587741Sgblack@eecs.umich.edu        break;
5593523Sgblack@eecs.umich.edu      case MODE_ABORT:
5607741Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
5617741Sgblack@eecs.umich.edu        break;
5627741Sgblack@eecs.umich.edu      case MODE_UNDEFINED:
5633595Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
5644172Ssaidi@eecs.umich.edu        if (ec(tc) != EC_UNKNOWN)
5654172Ssaidi@eecs.umich.edu            setSyndrome(tc, MISCREG_HSR);
5664172Ssaidi@eecs.umich.edu        break;
5673595Sgblack@eecs.umich.edu      case MODE_HYP:
5687741Sgblack@eecs.umich.edu        assert(have_virtualization);
5694172Ssaidi@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr);
5703595Sgblack@eecs.umich.edu        setSyndrome(tc, MISCREG_HSR);
5717741Sgblack@eecs.umich.edu        break;
5724172Ssaidi@eecs.umich.edu      default:
5737741Sgblack@eecs.umich.edu        panic("unknown Mode\n");
5743628Sgblack@eecs.umich.edu    }
5757741Sgblack@eecs.umich.edu
5763628Sgblack@eecs.umich.edu    Addr newPc = getVector(tc);
5777741Sgblack@eecs.umich.edu    DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n",
5783628Sgblack@eecs.umich.edu            name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc);
5797741Sgblack@eecs.umich.edu    PCState pc(newPc);
5803628Sgblack@eecs.umich.edu    pc.thumb(cpsr.t);
5814172Ssaidi@eecs.umich.edu    pc.nextThumb(pc.thumb());
5823595Sgblack@eecs.umich.edu    pc.jazelle(cpsr.j);
5837741Sgblack@eecs.umich.edu    pc.nextJazelle(pc.jazelle());
5844172Ssaidi@eecs.umich.edu    pc.aarch64(!cpsr.width);
5853595Sgblack@eecs.umich.edu    pc.nextAArch64(!cpsr.width);
5867741Sgblack@eecs.umich.edu    tc->pcState(pc);
5877741Sgblack@eecs.umich.edu}
5883746Sgblack@eecs.umich.edu
5893746Sgblack@eecs.umich.eduvoid
5903595Sgblack@eecs.umich.eduArmFault::invoke64(ThreadContext *tc, StaticInstPtr inst)
5913595Sgblack@eecs.umich.edu{
5927720Sgblack@eecs.umich.edu    // Determine actual misc. register indices for ELR_ELx and SPSR_ELx
5937720Sgblack@eecs.umich.edu    MiscRegIndex elr_idx, spsr_idx;
5947720Sgblack@eecs.umich.edu    switch (toEL) {
5957720Sgblack@eecs.umich.edu      case EL1:
5967720Sgblack@eecs.umich.edu        elr_idx = MISCREG_ELR_EL1;
5977720Sgblack@eecs.umich.edu        spsr_idx = MISCREG_SPSR_EL1;
5987720Sgblack@eecs.umich.edu        break;
5997720Sgblack@eecs.umich.edu      // @todo: uncomment this to enable Virtualization
6003595Sgblack@eecs.umich.edu      // case EL2:
6017741Sgblack@eecs.umich.edu      //   assert(ArmSystem::haveVirtualization());
6027741Sgblack@eecs.umich.edu      //   elr_idx = MISCREG_ELR_EL2;
6033523Sgblack@eecs.umich.edu      //   spsr_idx = MISCREG_SPSR_EL2;
6043595Sgblack@eecs.umich.edu      //   break;
6053595Sgblack@eecs.umich.edu      case EL3:
6063595Sgblack@eecs.umich.edu        assert(ArmSystem::haveSecurity(tc));
6074172Ssaidi@eecs.umich.edu        elr_idx = MISCREG_ELR_EL3;
6083595Sgblack@eecs.umich.edu        spsr_idx = MISCREG_SPSR_EL3;
6093523Sgblack@eecs.umich.edu        break;
6107741Sgblack@eecs.umich.edu      default:
6113523Sgblack@eecs.umich.edu        panic("Invalid target exception level");
6123523Sgblack@eecs.umich.edu        break;
6133523Sgblack@eecs.umich.edu    }
6143523Sgblack@eecs.umich.edu
6153523Sgblack@eecs.umich.edu    // Save process state into SPSR_ELx
6163523Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
6173523Sgblack@eecs.umich.edu    CPSR spsr = cpsr;
6183523Sgblack@eecs.umich.edu    spsr.nz = tc->readCCReg(CCREG_NZ);
6193523Sgblack@eecs.umich.edu    spsr.c = tc->readCCReg(CCREG_C);
6202221SN/A    spsr.v = tc->readCCReg(CCREG_V);
6212221SN/A    if (from64) {
6227741Sgblack@eecs.umich.edu        // Force some bitfields to 0
6237741Sgblack@eecs.umich.edu        spsr.q = 0;
6244997Sgblack@eecs.umich.edu        spsr.it1 = 0;
6258767Sgblack@eecs.umich.edu        spsr.j = 0;
6268767Sgblack@eecs.umich.edu        spsr.res0_23_22 = 0;
6274997Sgblack@eecs.umich.edu        spsr.ge = 0;
6288767Sgblack@eecs.umich.edu        spsr.it2 = 0;
6298767Sgblack@eecs.umich.edu        spsr.t = 0;
6308767Sgblack@eecs.umich.edu    } else {
6318767Sgblack@eecs.umich.edu        spsr.ge = tc->readCCReg(CCREG_GE);
6328767Sgblack@eecs.umich.edu        ITSTATE it = tc->pcState().itstate();
6338767Sgblack@eecs.umich.edu        spsr.it2 = it.top6;
6348767Sgblack@eecs.umich.edu        spsr.it1 = it.bottom2;
6358767Sgblack@eecs.umich.edu        // Force some bitfields to 0
6368767Sgblack@eecs.umich.edu        spsr.res0_23_22 = 0;
6378767Sgblack@eecs.umich.edu        spsr.ss = 0;
6384997Sgblack@eecs.umich.edu    }
6394997Sgblack@eecs.umich.edu    tc->setMiscReg(spsr_idx, spsr);
6404997Sgblack@eecs.umich.edu
6417741Sgblack@eecs.umich.edu    // Save preferred return address into ELR_ELx
6427741Sgblack@eecs.umich.edu    Addr curr_pc = tc->pcState().pc();
6434997Sgblack@eecs.umich.edu    Addr ret_addr = curr_pc;
6448767Sgblack@eecs.umich.edu    if (from64)
6458767Sgblack@eecs.umich.edu        ret_addr += armPcElrOffset();
6468767Sgblack@eecs.umich.edu    else
6478767Sgblack@eecs.umich.edu        ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset();
6488767Sgblack@eecs.umich.edu    tc->setMiscReg(elr_idx, ret_addr);
6498767Sgblack@eecs.umich.edu
6508767Sgblack@eecs.umich.edu    // Update process state
6518767Sgblack@eecs.umich.edu    OperatingMode64 mode = 0;
6528767Sgblack@eecs.umich.edu    mode.spX = 1;
6538767Sgblack@eecs.umich.edu    mode.el = toEL;
6548767Sgblack@eecs.umich.edu    mode.width = 0;
6558767Sgblack@eecs.umich.edu    cpsr.mode = mode;
6568767Sgblack@eecs.umich.edu    cpsr.daif = 0xf;
6578767Sgblack@eecs.umich.edu    cpsr.il = 0;
6588767Sgblack@eecs.umich.edu    cpsr.ss = 0;
6598767Sgblack@eecs.umich.edu    tc->setMiscReg(MISCREG_CPSR, cpsr);
6608767Sgblack@eecs.umich.edu
6614997Sgblack@eecs.umich.edu    // Set PC to start of exception handler
6624997Sgblack@eecs.umich.edu    Addr new_pc = purifyTaggedAddr(getVector64(tc), tc, toEL);
6634997Sgblack@eecs.umich.edu    DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x "
6647741Sgblack@eecs.umich.edu            "elr:%#x newVec: %#x\n", name(), cpsr, curr_pc, ret_addr, new_pc);
6657741Sgblack@eecs.umich.edu    PCState pc(new_pc);
6663415Sgblack@eecs.umich.edu    pc.aarch64(!cpsr.width);
6678778Sgblack@eecs.umich.edu    pc.nextAArch64(!cpsr.width);
6688778Sgblack@eecs.umich.edu    tc->pcState(pc);
6698778Sgblack@eecs.umich.edu
6708778Sgblack@eecs.umich.edu    // If we have a valid instruction then use it to annotate this fault with
6713415Sgblack@eecs.umich.edu    // extra information. This is used to generate the correct fault syndrome
6728778Sgblack@eecs.umich.edu    // information
6733415Sgblack@eecs.umich.edu    if (inst)
6748778Sgblack@eecs.umich.edu        reinterpret_cast<ArmStaticInst *>(inst.get())->annotateFault(this);
6758778Sgblack@eecs.umich.edu    // Save exception syndrome
6768778Sgblack@eecs.umich.edu    if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ))
6773415Sgblack@eecs.umich.edu        setSyndrome(tc, getSyndromeReg64());
6788778Sgblack@eecs.umich.edu}
6798778Sgblack@eecs.umich.edu
6808778Sgblack@eecs.umich.eduvoid
6813415Sgblack@eecs.umich.eduReset::invoke(ThreadContext *tc, StaticInstPtr inst)
6823415Sgblack@eecs.umich.edu{
6837741Sgblack@eecs.umich.edu    if (FullSystem) {
6847741Sgblack@eecs.umich.edu        tc->getCpuPtr()->clearInterrupts();
6853415Sgblack@eecs.umich.edu        tc->clearArchRegs();
6868778Sgblack@eecs.umich.edu    }
6878778Sgblack@eecs.umich.edu    if (!ArmSystem::highestELIs64(tc)) {
6888778Sgblack@eecs.umich.edu        ArmFault::invoke(tc, inst);
6898778Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_VMPIDR,
6903415Sgblack@eecs.umich.edu                       getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc));
6918778Sgblack@eecs.umich.edu
6923415Sgblack@eecs.umich.edu        // Unless we have SMC code to get us there, boot in HYP!
6938778Sgblack@eecs.umich.edu        if (ArmSystem::haveVirtualization(tc) &&
6948778Sgblack@eecs.umich.edu            !ArmSystem::haveSecurity(tc)) {
6958778Sgblack@eecs.umich.edu            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
6963415Sgblack@eecs.umich.edu            cpsr.mode = MODE_HYP;
6978778Sgblack@eecs.umich.edu            tc->setMiscReg(MISCREG_CPSR, cpsr);
6988778Sgblack@eecs.umich.edu        }
6998778Sgblack@eecs.umich.edu    } else {
7003415Sgblack@eecs.umich.edu        // Advance the PC to the IMPLEMENTATION DEFINED reset value
7013415Sgblack@eecs.umich.edu        PCState pc = ArmSystem::resetAddr64(tc);
7027741Sgblack@eecs.umich.edu        pc.aarch64(true);
7037741Sgblack@eecs.umich.edu        pc.nextAArch64(true);
7044111Sgblack@eecs.umich.edu        tc->pcState(pc);
7058778Sgblack@eecs.umich.edu    }
7068778Sgblack@eecs.umich.edu}
7078778Sgblack@eecs.umich.edu
7088778Sgblack@eecs.umich.eduvoid
7098778Sgblack@eecs.umich.eduUndefinedInstruction::invoke(ThreadContext *tc, StaticInstPtr inst)
7108778Sgblack@eecs.umich.edu{
7114111Sgblack@eecs.umich.edu    if (FullSystem) {
7128778Sgblack@eecs.umich.edu        ArmFault::invoke(tc, inst);
7134111Sgblack@eecs.umich.edu        return;
7148778Sgblack@eecs.umich.edu    }
7158778Sgblack@eecs.umich.edu
7164111Sgblack@eecs.umich.edu    // If the mnemonic isn't defined this has to be an unknown instruction.
7178778Sgblack@eecs.umich.edu    assert(unknown || mnemonic != NULL);
7184111Sgblack@eecs.umich.edu    if (disabled) {
7198778Sgblack@eecs.umich.edu        panic("Attempted to execute disabled instruction "
7208778Sgblack@eecs.umich.edu                "'%s' (inst 0x%08x)", mnemonic, machInst);
7218778Sgblack@eecs.umich.edu    } else if (unknown) {
7228778Sgblack@eecs.umich.edu        panic("Attempted to execute unknown instruction (inst 0x%08x)",
7238778Sgblack@eecs.umich.edu              machInst);
7248778Sgblack@eecs.umich.edu    } else {
7254111Sgblack@eecs.umich.edu        panic("Attempted to execute unimplemented instruction "
7264111Sgblack@eecs.umich.edu                "'%s' (inst 0x%08x)", mnemonic, machInst);
7272223SN/A    }
7282221SN/A}
729
730bool
731UndefinedInstruction::routeToHyp(ThreadContext *tc) const
732{
733    bool toHyp;
734
735    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
736    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
737    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
738
739    // if in Hyp mode then stay in Hyp mode
740    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
741    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
742    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
743    return toHyp;
744}
745
746uint32_t
747UndefinedInstruction::iss() const
748{
749    if (overrideEc == EC_INVALID)
750        return issRaw;
751
752    uint32_t new_iss = 0;
753    uint32_t op0, op1, op2, CRn, CRm, Rt, dir;
754
755    dir = bits(machInst, 21, 21);
756    op0 = bits(machInst, 20, 19);
757    op1 = bits(machInst, 18, 16);
758    CRn = bits(machInst, 15, 12);
759    CRm = bits(machInst, 11, 8);
760    op2 = bits(machInst, 7, 5);
761    Rt = bits(machInst, 4, 0);
762
763    new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 |
764            Rt << 5 | CRm << 1 | dir;
765
766    return new_iss;
767}
768
769void
770SupervisorCall::invoke(ThreadContext *tc, StaticInstPtr inst)
771{
772    if (FullSystem) {
773        ArmFault::invoke(tc, inst);
774        return;
775    }
776
777    // As of now, there isn't a 32 bit thumb version of this instruction.
778    assert(!machInst.bigThumb);
779    uint32_t callNum;
780    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
781    OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
782    if (opModeIs64(mode))
783        callNum = tc->readIntReg(INTREG_X8);
784    else
785        callNum = tc->readIntReg(INTREG_R7);
786    tc->syscall(callNum);
787
788    // Advance the PC since that won't happen automatically.
789    PCState pc = tc->pcState();
790    assert(inst);
791    inst->advancePC(pc);
792    tc->pcState(pc);
793}
794
795bool
796SupervisorCall::routeToHyp(ThreadContext *tc) const
797{
798    bool toHyp;
799
800    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
801    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
802    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
803
804    // if in Hyp mode then stay in Hyp mode
805    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
806    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
807    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
808    return toHyp;
809}
810
811ExceptionClass
812SupervisorCall::ec(ThreadContext *tc) const
813{
814    return (overrideEc != EC_INVALID) ? overrideEc :
815        (from64 ? EC_SVC_64 : vals.ec);
816}
817
818uint32_t
819SupervisorCall::iss() const
820{
821    // Even if we have a 24 bit imm from an arm32 instruction then we only use
822    // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC).
823    return issRaw & 0xFFFF;
824}
825
826uint32_t
827SecureMonitorCall::iss() const
828{
829    if (from64)
830        return bits(machInst, 20, 5);
831    return 0;
832}
833
834ExceptionClass
835UndefinedInstruction::ec(ThreadContext *tc) const
836{
837    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
838}
839
840
841HypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) :
842        ArmFaultVals<HypervisorCall>(_machInst, _imm)
843{}
844
845ExceptionClass
846HypervisorTrap::ec(ThreadContext *tc) const
847{
848    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
849}
850
851template<class T>
852FaultOffset
853ArmFaultVals<T>::offset(ThreadContext *tc)
854{
855    bool isHypTrap = false;
856
857    // Normally we just use the exception vector from the table at the top if
858    // this file, however if this exception has caused a transition to hype
859    // mode, and its an exception type that would only do this if it has been
860    // trapped then we use the hyp trap vector instead of the normal vector
861    if (vals.hypTrappable) {
862        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
863        if (cpsr.mode == MODE_HYP) {
864            CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
865            isHypTrap = spsr.mode != MODE_HYP;
866        }
867    }
868    return isHypTrap ? 0x14 : vals.offset;
869}
870
871// void
872// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx)
873// {
874//     ESR esr = 0;
875//     esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32;
876//     esr.il = !machInst.thumb;
877//     if (machInst.aarch64)
878//         esr.imm16 = bits(machInst.instBits, 20, 5);
879//     else if (machInst.thumb)
880//         esr.imm16 = bits(machInst.instBits, 7, 0);
881//     else
882//         esr.imm16 = bits(machInst.instBits, 15, 0);
883//     tc->setMiscReg(esr_idx, esr);
884// }
885
886void
887SecureMonitorCall::invoke(ThreadContext *tc, StaticInstPtr inst)
888{
889    if (FullSystem) {
890        ArmFault::invoke(tc, inst);
891        return;
892    }
893}
894
895ExceptionClass
896SecureMonitorCall::ec(ThreadContext *tc) const
897{
898    return (from64 ? EC_SMC_64 : vals.ec);
899}
900
901ExceptionClass
902SupervisorTrap::ec(ThreadContext *tc) const
903{
904    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
905}
906
907ExceptionClass
908SecureMonitorTrap::ec(ThreadContext *tc) const
909{
910    return (overrideEc != EC_INVALID) ? overrideEc :
911        (from64 ? EC_SMC_64 : vals.ec);
912}
913
914template<class T>
915void
916AbortFault<T>::invoke(ThreadContext *tc, StaticInstPtr inst)
917{
918    if (tranMethod == ArmFault::UnknownTran) {
919        tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran
920                                             : ArmFault::VmsaTran;
921
922        if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) {
923            // See ARM ARM B3-1416
924            bool override_LPAE = false;
925            TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S);
926            TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS);
927            if (ttbcr_s.eae) {
928                override_LPAE = true;
929            } else {
930                // Unimplemented code option, not seen in testing.  May need
931                // extension according to the manual exceprt above.
932                DPRINTF(Faults, "Warning: Incomplete translation method "
933                        "override detected.\n");
934            }
935            if (override_LPAE)
936                tranMethod = ArmFault::LpaeTran;
937        }
938    }
939
940    if (source == ArmFault::AsynchronousExternalAbort) {
941        tc->getCpuPtr()->clearInterrupt(INT_ABT, 0);
942    }
943    // Get effective fault source encoding
944    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
945    FSR  fsr  = getFsr(tc);
946
947    // source must be determined BEFORE invoking generic routines which will
948    // try to set hsr etc. and are based upon source!
949    ArmFaultVals<T>::invoke(tc, inst);
950
951    if (cpsr.width) {  // AArch32
952        if (cpsr.mode == MODE_HYP) {
953            tc->setMiscReg(T::HFarIndex, faultAddr);
954        } else if (stage2) {
955            tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf);
956            tc->setMiscReg(T::HFarIndex,  OVAddr);
957        } else {
958            tc->setMiscReg(T::FsrIndex, fsr);
959            tc->setMiscReg(T::FarIndex, faultAddr);
960        }
961        DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\
962                "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod);
963    } else {  // AArch64
964        // Set the FAR register.  Nothing else to do if we are in AArch64 state
965        // because the syndrome register has already been set inside invoke64()
966        tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
967    }
968}
969
970template<class T>
971FSR
972AbortFault<T>::getFsr(ThreadContext *tc)
973{
974    FSR fsr = 0;
975
976    if (((CPSR) tc->readMiscRegNoEffect(MISCREG_CPSR)).width) {
977        // AArch32
978        assert(tranMethod != ArmFault::UnknownTran);
979        if (tranMethod == ArmFault::LpaeTran) {
980            srcEncoded = ArmFault::longDescFaultSources[source];
981            fsr.status = srcEncoded;
982            fsr.lpae   = 1;
983        } else {
984            srcEncoded = ArmFault::shortDescFaultSources[source];
985            fsr.fsLow  = bits(srcEncoded, 3, 0);
986            fsr.fsHigh = bits(srcEncoded, 4);
987            fsr.domain = static_cast<uint8_t>(domain);
988        }
989        fsr.wnr = (write ? 1 : 0);
990        fsr.ext = 0;
991    } else {
992        // AArch64
993        srcEncoded = ArmFault::aarch64FaultSources[source];
994    }
995    if (srcEncoded == ArmFault::FaultSourceInvalid) {
996        panic("Invalid fault source\n");
997    }
998    return fsr;
999}
1000
1001template<class T>
1002bool
1003AbortFault<T>::abortDisable(ThreadContext *tc)
1004{
1005    if (ArmSystem::haveSecurity(tc)) {
1006        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1007        return (!scr.ns || scr.aw);
1008    }
1009    return true;
1010}
1011
1012template<class T>
1013void
1014AbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val)
1015{
1016    switch (id)
1017    {
1018      case ArmFault::S1PTW:
1019        s1ptw = val;
1020        break;
1021      case ArmFault::OVA:
1022        OVAddr = val;
1023        break;
1024
1025      // Just ignore unknown ID's
1026      default:
1027        break;
1028    }
1029}
1030
1031template<class T>
1032uint32_t
1033AbortFault<T>::iss() const
1034{
1035    uint32_t val;
1036
1037    val  = srcEncoded & 0x3F;
1038    val |= write << 6;
1039    val |= s1ptw << 7;
1040    return (val);
1041}
1042
1043template<class T>
1044bool
1045AbortFault<T>::isMMUFault() const
1046{
1047    // NOTE: Not relying on LL information being aligned to lowest bits here
1048    return
1049         (source == ArmFault::AlignmentFault)     ||
1050        ((source >= ArmFault::TranslationLL) &&
1051         (source <  ArmFault::TranslationLL + 4)) ||
1052        ((source >= ArmFault::AccessFlagLL) &&
1053         (source <  ArmFault::AccessFlagLL + 4))  ||
1054        ((source >= ArmFault::DomainLL) &&
1055         (source <  ArmFault::DomainLL + 4))      ||
1056        ((source >= ArmFault::PermissionLL) &&
1057         (source <  ArmFault::PermissionLL + 4));
1058}
1059
1060ExceptionClass
1061PrefetchAbort::ec(ThreadContext *tc) const
1062{
1063    if (to64) {
1064        // AArch64
1065        if (toEL == fromEL)
1066            return EC_PREFETCH_ABORT_CURR_EL;
1067        else
1068            return EC_PREFETCH_ABORT_LOWER_EL;
1069    } else {
1070        // AArch32
1071        // Abort faults have different EC codes depending on whether
1072        // the fault originated within HYP mode, or not. So override
1073        // the method and add the extra adjustment of the EC value.
1074
1075        ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec;
1076
1077        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
1078        if (spsr.mode == MODE_HYP) {
1079            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
1080        }
1081        return ec;
1082    }
1083}
1084
1085bool
1086PrefetchAbort::routeToMonitor(ThreadContext *tc) const
1087{
1088    SCR scr = 0;
1089    if (from64)
1090        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1091    else
1092        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1093
1094    return scr.ea && !isMMUFault();
1095}
1096
1097bool
1098PrefetchAbort::routeToHyp(ThreadContext *tc) const
1099{
1100    bool toHyp;
1101
1102    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1103    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1104    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1105    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
1106
1107    // if in Hyp mode then stay in Hyp mode
1108    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
1109    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
1110    toHyp |= (stage2 ||
1111                ( (source ==               DebugEvent) && hdcr.tde && (cpsr.mode !=  MODE_HYP)) ||
1112                ( (source == SynchronousExternalAbort) && hcr.tge  && (cpsr.mode == MODE_USER))
1113             ) && !inSecureState(scr, cpsr);
1114    return toHyp;
1115}
1116
1117ExceptionClass
1118DataAbort::ec(ThreadContext *tc) const
1119{
1120    if (to64) {
1121        // AArch64
1122        if (source == ArmFault::AsynchronousExternalAbort) {
1123            panic("Asynchronous External Abort should be handled with "
1124                    "SystemErrors (SErrors)!");
1125        }
1126        if (toEL == fromEL)
1127            return EC_DATA_ABORT_CURR_EL;
1128        else
1129            return EC_DATA_ABORT_LOWER_EL;
1130    } else {
1131        // AArch32
1132        // Abort faults have different EC codes depending on whether
1133        // the fault originated within HYP mode, or not. So override
1134        // the method and add the extra adjustment of the EC value.
1135
1136        ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec;
1137
1138        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
1139        if (spsr.mode == MODE_HYP) {
1140            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
1141        }
1142        return ec;
1143    }
1144}
1145
1146bool
1147DataAbort::routeToMonitor(ThreadContext *tc) const
1148{
1149    SCR scr = 0;
1150    if (from64)
1151        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1152    else
1153        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1154
1155    return scr.ea && !isMMUFault();
1156}
1157
1158bool
1159DataAbort::routeToHyp(ThreadContext *tc) const
1160{
1161    bool toHyp;
1162
1163    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1164    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1165    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1166    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
1167
1168    // if in Hyp mode then stay in Hyp mode
1169    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
1170    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
1171    toHyp |= (stage2 ||
1172                ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) ||
1173                                               ((source == DebugEvent) && hdcr.tde) )
1174                ) ||
1175                ( (cpsr.mode == MODE_USER) && hcr.tge &&
1176                  ((source == AlignmentFault)            ||
1177                   (source == SynchronousExternalAbort))
1178                )
1179             ) && !inSecureState(scr, cpsr);
1180    return toHyp;
1181}
1182
1183uint32_t
1184DataAbort::iss() const
1185{
1186    uint32_t val;
1187
1188    // Add on the data abort specific fields to the generic abort ISS value
1189    val  = AbortFault<DataAbort>::iss();
1190    // ISS is valid if not caused by a stage 1 page table walk, and when taken
1191    // to AArch64 only when directed to EL2
1192    if (!s1ptw && (!to64 || toEL == EL2)) {
1193        val |= isv << 24;
1194        if (isv) {
1195            val |= sas << 22;
1196            val |= sse << 21;
1197            val |= srt << 16;
1198            // AArch64 only. These assignments are safe on AArch32 as well
1199            // because these vars are initialized to false
1200            val |= sf << 15;
1201            val |= ar << 14;
1202        }
1203    }
1204    return (val);
1205}
1206
1207void
1208DataAbort::annotate(AnnotationIDs id, uint64_t val)
1209{
1210    AbortFault<DataAbort>::annotate(id, val);
1211    switch (id)
1212    {
1213      case SAS:
1214        isv = true;
1215        sas = val;
1216        break;
1217      case SSE:
1218        isv = true;
1219        sse = val;
1220        break;
1221      case SRT:
1222        isv = true;
1223        srt = val;
1224        break;
1225      case SF:
1226        isv = true;
1227        sf  = val;
1228        break;
1229      case AR:
1230        isv = true;
1231        ar  = val;
1232        break;
1233      // Just ignore unknown ID's
1234      default:
1235        break;
1236    }
1237}
1238
1239void
1240VirtualDataAbort::invoke(ThreadContext *tc, StaticInstPtr inst)
1241{
1242    AbortFault<VirtualDataAbort>::invoke(tc, inst);
1243    HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
1244    hcr.va = 0;
1245    tc->setMiscRegNoEffect(MISCREG_HCR, hcr);
1246}
1247
1248bool
1249Interrupt::routeToMonitor(ThreadContext *tc) const
1250{
1251    assert(ArmSystem::haveSecurity(tc));
1252    SCR scr = 0;
1253    if (from64)
1254        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1255    else
1256        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1257    return scr.irq;
1258}
1259
1260bool
1261Interrupt::routeToHyp(ThreadContext *tc) const
1262{
1263    bool toHyp;
1264
1265    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1266    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1267    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1268    // Determine whether IRQs are routed to Hyp mode.
1269    toHyp = (!scr.irq && hcr.imo && !inSecureState(scr, cpsr)) ||
1270            (cpsr.mode == MODE_HYP);
1271    return toHyp;
1272}
1273
1274bool
1275Interrupt::abortDisable(ThreadContext *tc)
1276{
1277    if (ArmSystem::haveSecurity(tc)) {
1278        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1279        return (!scr.ns || scr.aw);
1280    }
1281    return true;
1282}
1283
1284VirtualInterrupt::VirtualInterrupt()
1285{}
1286
1287bool
1288FastInterrupt::routeToMonitor(ThreadContext *tc) const
1289{
1290    assert(ArmSystem::haveSecurity(tc));
1291    SCR scr = 0;
1292    if (from64)
1293        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1294    else
1295        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1296    return scr.fiq;
1297}
1298
1299bool
1300FastInterrupt::routeToHyp(ThreadContext *tc) const
1301{
1302    bool toHyp;
1303
1304    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1305    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1306    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1307    // Determine whether IRQs are routed to Hyp mode.
1308    toHyp = (!scr.fiq && hcr.fmo && !inSecureState(scr, cpsr)) ||
1309            (cpsr.mode == MODE_HYP);
1310    return toHyp;
1311}
1312
1313bool
1314FastInterrupt::abortDisable(ThreadContext *tc)
1315{
1316    if (ArmSystem::haveSecurity(tc)) {
1317        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1318        return (!scr.ns || scr.aw);
1319    }
1320    return true;
1321}
1322
1323bool
1324FastInterrupt::fiqDisable(ThreadContext *tc)
1325{
1326    if (ArmSystem::haveVirtualization(tc)) {
1327        return true;
1328    } else if (ArmSystem::haveSecurity(tc)) {
1329        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1330        return (!scr.ns || scr.fw);
1331    }
1332    return true;
1333}
1334
1335VirtualFastInterrupt::VirtualFastInterrupt()
1336{}
1337
1338void
1339PCAlignmentFault::invoke(ThreadContext *tc, StaticInstPtr inst)
1340{
1341    ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
1342    assert(from64);
1343    // Set the FAR
1344    tc->setMiscReg(getFaultAddrReg64(), faultPC);
1345}
1346
1347SPAlignmentFault::SPAlignmentFault()
1348{}
1349
1350SystemError::SystemError()
1351{}
1352
1353void
1354SystemError::invoke(ThreadContext *tc, StaticInstPtr inst)
1355{
1356    tc->getCpuPtr()->clearInterrupt(INT_ABT, 0);
1357    ArmFault::invoke(tc, inst);
1358}
1359
1360bool
1361SystemError::routeToMonitor(ThreadContext *tc) const
1362{
1363    assert(ArmSystem::haveSecurity(tc));
1364    assert(from64);
1365    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1366    return scr.ea;
1367}
1368
1369bool
1370SystemError::routeToHyp(ThreadContext *tc) const
1371{
1372    bool toHyp;
1373    assert(from64);
1374
1375    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1376    HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1377    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1378
1379    toHyp = (!scr.ea && hcr.amo && !inSecureState(scr, cpsr)) ||
1380            (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(scr,cpsr));
1381    return toHyp;
1382}
1383
1384void
1385FlushPipe::invoke(ThreadContext *tc, StaticInstPtr inst) {
1386    DPRINTF(Faults, "Invoking FlushPipe Fault\n");
1387
1388    // Set the PC to the next instruction of the faulting instruction.
1389    // Net effect is simply squashing all instructions behind and
1390    // start refetching from the next instruction.
1391    PCState pc = tc->pcState();
1392    assert(inst);
1393    inst->advancePC(pc);
1394    tc->pcState(pc);
1395}
1396
1397void
1398ArmSev::invoke(ThreadContext *tc, StaticInstPtr inst) {
1399    DPRINTF(Faults, "Invoking ArmSev Fault\n");
1400    if (!FullSystem)
1401        return;
1402
1403    // Set sev_mailbox to 1, clear the pending interrupt from remote
1404    // SEV execution and let pipeline continue as pcState is still
1405    // valid.
1406    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
1407    tc->getCpuPtr()->clearInterrupt(INT_SEV, 0);
1408}
1409
1410// Instantiate all the templates to make the linker happy
1411template class ArmFaultVals<Reset>;
1412template class ArmFaultVals<UndefinedInstruction>;
1413template class ArmFaultVals<SupervisorCall>;
1414template class ArmFaultVals<SecureMonitorCall>;
1415template class ArmFaultVals<HypervisorCall>;
1416template class ArmFaultVals<PrefetchAbort>;
1417template class ArmFaultVals<DataAbort>;
1418template class ArmFaultVals<VirtualDataAbort>;
1419template class ArmFaultVals<HypervisorTrap>;
1420template class ArmFaultVals<Interrupt>;
1421template class ArmFaultVals<VirtualInterrupt>;
1422template class ArmFaultVals<FastInterrupt>;
1423template class ArmFaultVals<VirtualFastInterrupt>;
1424template class ArmFaultVals<SupervisorTrap>;
1425template class ArmFaultVals<SecureMonitorTrap>;
1426template class ArmFaultVals<PCAlignmentFault>;
1427template class ArmFaultVals<SPAlignmentFault>;
1428template class ArmFaultVals<SystemError>;
1429template class ArmFaultVals<FlushPipe>;
1430template class ArmFaultVals<ArmSev>;
1431template class AbortFault<PrefetchAbort>;
1432template class AbortFault<DataAbort>;
1433template class AbortFault<VirtualDataAbort>;
1434
1435
1436IllegalInstSetStateFault::IllegalInstSetStateFault()
1437{}
1438
1439
1440} // namespace ArmISA
1441