faults.cc revision 12299
15952Ssaidi@eecs.umich.edu/*
25952Ssaidi@eecs.umich.edu * Copyright (c) 2010, 2012-2014, 2016-2017 ARM Limited
35952Ssaidi@eecs.umich.edu * All rights reserved
45952Ssaidi@eecs.umich.edu *
55952Ssaidi@eecs.umich.edu * The license below extends only to copyright in the software and shall
65952Ssaidi@eecs.umich.edu * not be construed as granting a license to any other intellectual
75952Ssaidi@eecs.umich.edu * property including but not limited to intellectual property relating
85952Ssaidi@eecs.umich.edu * to a hardware implementation of the functionality of the software
95952Ssaidi@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
105952Ssaidi@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
115952Ssaidi@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
125952Ssaidi@eecs.umich.edu * modified or unmodified, in source code or in binary form.
135952Ssaidi@eecs.umich.edu *
145952Ssaidi@eecs.umich.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan
155952Ssaidi@eecs.umich.edu * Copyright (c) 2007-2008 The Florida State University
165952Ssaidi@eecs.umich.edu * All rights reserved.
175952Ssaidi@eecs.umich.edu *
185952Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
195952Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are
205952Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright
215952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
225952Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
235952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
245952Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution;
255952Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its
265952Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from
275952Ssaidi@eecs.umich.edu * this software without specific prior written permission.
285952Ssaidi@eecs.umich.edu *
295952Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
305952Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3110377Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
325952Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
338229Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
348229Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
355952Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
365952Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
375952Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
386658Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
395952Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4010377Sandreas.hansson@arm.com *
4110377Sandreas.hansson@arm.com * Authors: Ali Saidi
425952Ssaidi@eecs.umich.edu *          Gabe Black
435952Ssaidi@eecs.umich.edu *          Giacomo Gabrielli
445952Ssaidi@eecs.umich.edu *          Thomas Grocutt
455952Ssaidi@eecs.umich.edu */
465952Ssaidi@eecs.umich.edu
475952Ssaidi@eecs.umich.edu#include "arch/arm/faults.hh"
485952Ssaidi@eecs.umich.edu
495952Ssaidi@eecs.umich.edu#include "arch/arm/insts/static_inst.hh"
505952Ssaidi@eecs.umich.edu#include "arch/arm/system.hh"
515952Ssaidi@eecs.umich.edu#include "arch/arm/utility.hh"
525952Ssaidi@eecs.umich.edu#include "base/compiler.hh"
535952Ssaidi@eecs.umich.edu#include "base/trace.hh"
545952Ssaidi@eecs.umich.edu#include "cpu/base.hh"
555952Ssaidi@eecs.umich.edu#include "cpu/thread_context.hh"
565952Ssaidi@eecs.umich.edu#include "debug/Faults.hh"
575952Ssaidi@eecs.umich.edu#include "sim/full_system.hh"
585952Ssaidi@eecs.umich.edu
595952Ssaidi@eecs.umich.edunamespace ArmISA
605952Ssaidi@eecs.umich.edu{
615952Ssaidi@eecs.umich.edu
625952Ssaidi@eecs.umich.eduuint8_t ArmFault::shortDescFaultSources[] = {
635952Ssaidi@eecs.umich.edu    0x01,  // AlignmentFault
645952Ssaidi@eecs.umich.edu    0x04,  // InstructionCacheMaintenance
655952Ssaidi@eecs.umich.edu    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
665952Ssaidi@eecs.umich.edu    0x0c,  // SynchExtAbtOnTranslTableWalkL1
675952Ssaidi@eecs.umich.edu    0x0e,  // SynchExtAbtOnTranslTableWalkL2
685952Ssaidi@eecs.umich.edu    0xff,  // SynchExtAbtOnTranslTableWalkL3 (INVALID)
695952Ssaidi@eecs.umich.edu    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
705952Ssaidi@eecs.umich.edu    0x1c,  // SynchPtyErrOnTranslTableWalkL1
715952Ssaidi@eecs.umich.edu    0x1e,  // SynchPtyErrOnTranslTableWalkL2
725952Ssaidi@eecs.umich.edu    0xff,  // SynchPtyErrOnTranslTableWalkL3 (INVALID)
735952Ssaidi@eecs.umich.edu    0xff,  // TranslationL0 (INVALID)
745952Ssaidi@eecs.umich.edu    0x05,  // TranslationL1
755952Ssaidi@eecs.umich.edu    0x07,  // TranslationL2
765952Ssaidi@eecs.umich.edu    0xff,  // TranslationL3 (INVALID)
775952Ssaidi@eecs.umich.edu    0xff,  // AccessFlagL0 (INVALID)
785952Ssaidi@eecs.umich.edu    0x03,  // AccessFlagL1
795952Ssaidi@eecs.umich.edu    0x06,  // AccessFlagL2
805952Ssaidi@eecs.umich.edu    0xff,  // AccessFlagL3 (INVALID)
815952Ssaidi@eecs.umich.edu    0xff,  // DomainL0 (INVALID)
825952Ssaidi@eecs.umich.edu    0x09,  // DomainL1
835952Ssaidi@eecs.umich.edu    0x0b,  // DomainL2
845952Ssaidi@eecs.umich.edu    0xff,  // DomainL3 (INVALID)
855952Ssaidi@eecs.umich.edu    0xff,  // PermissionL0 (INVALID)
865952Ssaidi@eecs.umich.edu    0x0d,  // PermissionL1
875952Ssaidi@eecs.umich.edu    0x0f,  // PermissionL2
885952Ssaidi@eecs.umich.edu    0xff,  // PermissionL3 (INVALID)
895952Ssaidi@eecs.umich.edu    0x02,  // DebugEvent
905952Ssaidi@eecs.umich.edu    0x08,  // SynchronousExternalAbort
915952Ssaidi@eecs.umich.edu    0x10,  // TLBConflictAbort
925952Ssaidi@eecs.umich.edu    0x19,  // SynchPtyErrOnMemoryAccess
935952Ssaidi@eecs.umich.edu    0x16,  // AsynchronousExternalAbort
945952Ssaidi@eecs.umich.edu    0x18,  // AsynchPtyErrOnMemoryAccess
955952Ssaidi@eecs.umich.edu    0xff,  // AddressSizeL0 (INVALID)
965952Ssaidi@eecs.umich.edu    0xff,  // AddressSizeL1 (INVALID)
975952Ssaidi@eecs.umich.edu    0xff,  // AddressSizeL2 (INVALID)
985952Ssaidi@eecs.umich.edu    0xff,  // AddressSizeL3 (INVALID)
995952Ssaidi@eecs.umich.edu    0x40,  // PrefetchTLBMiss
1005952Ssaidi@eecs.umich.edu    0x80   // PrefetchUncacheable
1015952Ssaidi@eecs.umich.edu};
1025952Ssaidi@eecs.umich.edu
1035952Ssaidi@eecs.umich.edustatic_assert(sizeof(ArmFault::shortDescFaultSources) ==
1045952Ssaidi@eecs.umich.edu              ArmFault::NumFaultSources,
1055952Ssaidi@eecs.umich.edu              "Invalid size of ArmFault::shortDescFaultSources[]");
1065952Ssaidi@eecs.umich.edu
1075952Ssaidi@eecs.umich.eduuint8_t ArmFault::longDescFaultSources[] = {
1085952Ssaidi@eecs.umich.edu    0x21,  // AlignmentFault
1095952Ssaidi@eecs.umich.edu    0xff,  // InstructionCacheMaintenance (INVALID)
1105952Ssaidi@eecs.umich.edu    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
1115952Ssaidi@eecs.umich.edu    0x15,  // SynchExtAbtOnTranslTableWalkL1
1125952Ssaidi@eecs.umich.edu    0x16,  // SynchExtAbtOnTranslTableWalkL2
1135952Ssaidi@eecs.umich.edu    0x17,  // SynchExtAbtOnTranslTableWalkL3
1145952Ssaidi@eecs.umich.edu    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
1155952Ssaidi@eecs.umich.edu    0x1d,  // SynchPtyErrOnTranslTableWalkL1
1165952Ssaidi@eecs.umich.edu    0x1e,  // SynchPtyErrOnTranslTableWalkL2
1175952Ssaidi@eecs.umich.edu    0x1f,  // SynchPtyErrOnTranslTableWalkL3
1185952Ssaidi@eecs.umich.edu    0xff,  // TranslationL0 (INVALID)
1195952Ssaidi@eecs.umich.edu    0x05,  // TranslationL1
1205952Ssaidi@eecs.umich.edu    0x06,  // TranslationL2
1215952Ssaidi@eecs.umich.edu    0x07,  // TranslationL3
1225952Ssaidi@eecs.umich.edu    0xff,  // AccessFlagL0 (INVALID)
1235952Ssaidi@eecs.umich.edu    0x09,  // AccessFlagL1
1245952Ssaidi@eecs.umich.edu    0x0a,  // AccessFlagL2
1255952Ssaidi@eecs.umich.edu    0x0b,  // AccessFlagL3
1265952Ssaidi@eecs.umich.edu    0xff,  // DomainL0 (INVALID)
1275952Ssaidi@eecs.umich.edu    0x3d,  // DomainL1
1285952Ssaidi@eecs.umich.edu    0x3e,  // DomainL2
1295952Ssaidi@eecs.umich.edu    0xff,  // DomainL3 (RESERVED)
1305952Ssaidi@eecs.umich.edu    0xff,  // PermissionL0 (INVALID)
1315952Ssaidi@eecs.umich.edu    0x0d,  // PermissionL1
1325952Ssaidi@eecs.umich.edu    0x0e,  // PermissionL2
1335952Ssaidi@eecs.umich.edu    0x0f,  // PermissionL3
1345952Ssaidi@eecs.umich.edu    0x22,  // DebugEvent
1355952Ssaidi@eecs.umich.edu    0x10,  // SynchronousExternalAbort
1365952Ssaidi@eecs.umich.edu    0x30,  // TLBConflictAbort
1375952Ssaidi@eecs.umich.edu    0x18,  // SynchPtyErrOnMemoryAccess
1385952Ssaidi@eecs.umich.edu    0x11,  // AsynchronousExternalAbort
1395952Ssaidi@eecs.umich.edu    0x19,  // AsynchPtyErrOnMemoryAccess
1405952Ssaidi@eecs.umich.edu    0xff,  // AddressSizeL0 (INVALID)
1415952Ssaidi@eecs.umich.edu    0xff,  // AddressSizeL1 (INVALID)
1425952Ssaidi@eecs.umich.edu    0xff,  // AddressSizeL2 (INVALID)
1435952Ssaidi@eecs.umich.edu    0xff,  // AddressSizeL3 (INVALID)
1445952Ssaidi@eecs.umich.edu    0x40,  // PrefetchTLBMiss
1455952Ssaidi@eecs.umich.edu    0x80   // PrefetchUncacheable
1465952Ssaidi@eecs.umich.edu};
14710377Sandreas.hansson@arm.com
14810377Sandreas.hansson@arm.comstatic_assert(sizeof(ArmFault::longDescFaultSources) ==
14910377Sandreas.hansson@arm.com              ArmFault::NumFaultSources,
15010377Sandreas.hansson@arm.com              "Invalid size of ArmFault::longDescFaultSources[]");
15110377Sandreas.hansson@arm.com
15210377Sandreas.hansson@arm.comuint8_t ArmFault::aarch64FaultSources[] = {
15310377Sandreas.hansson@arm.com    0x21,  // AlignmentFault
15410377Sandreas.hansson@arm.com    0xff,  // InstructionCacheMaintenance (INVALID)
15510377Sandreas.hansson@arm.com    0x14,  // SynchExtAbtOnTranslTableWalkL0
15610377Sandreas.hansson@arm.com    0x15,  // SynchExtAbtOnTranslTableWalkL1
15710377Sandreas.hansson@arm.com    0x16,  // SynchExtAbtOnTranslTableWalkL2
1585952Ssaidi@eecs.umich.edu    0x17,  // SynchExtAbtOnTranslTableWalkL3
1595952Ssaidi@eecs.umich.edu    0x1c,  // SynchPtyErrOnTranslTableWalkL0
1605952Ssaidi@eecs.umich.edu    0x1d,  // SynchPtyErrOnTranslTableWalkL1
1615952Ssaidi@eecs.umich.edu    0x1e,  // SynchPtyErrOnTranslTableWalkL2
1625952Ssaidi@eecs.umich.edu    0x1f,  // SynchPtyErrOnTranslTableWalkL3
1635952Ssaidi@eecs.umich.edu    0x04,  // TranslationL0
1645952Ssaidi@eecs.umich.edu    0x05,  // TranslationL1
1655952Ssaidi@eecs.umich.edu    0x06,  // TranslationL2
1665952Ssaidi@eecs.umich.edu    0x07,  // TranslationL3
1675952Ssaidi@eecs.umich.edu    0x08,  // AccessFlagL0
1685952Ssaidi@eecs.umich.edu    0x09,  // AccessFlagL1
1695952Ssaidi@eecs.umich.edu    0x0a,  // AccessFlagL2
1705952Ssaidi@eecs.umich.edu    0x0b,  // AccessFlagL3
1715952Ssaidi@eecs.umich.edu    // @todo: Section & Page Domain Fault in AArch64?
1725952Ssaidi@eecs.umich.edu    0xff,  // DomainL0 (INVALID)
1735952Ssaidi@eecs.umich.edu    0xff,  // DomainL1 (INVALID)
1745952Ssaidi@eecs.umich.edu    0xff,  // DomainL2 (INVALID)
1755952Ssaidi@eecs.umich.edu    0xff,  // DomainL3 (INVALID)
1765952Ssaidi@eecs.umich.edu    0x0c,  // PermissionL0
1777823Ssteve.reinhardt@amd.com    0x0d,  // PermissionL1
1785952Ssaidi@eecs.umich.edu    0x0e,  // PermissionL2
1795952Ssaidi@eecs.umich.edu    0x0f,  // PermissionL3
1805952Ssaidi@eecs.umich.edu    0xff,  // DebugEvent (INVALID)
1815952Ssaidi@eecs.umich.edu    0x10,  // SynchronousExternalAbort
1825952Ssaidi@eecs.umich.edu    0x30,  // TLBConflictAbort
1835952Ssaidi@eecs.umich.edu    0x18,  // SynchPtyErrOnMemoryAccess
1845952Ssaidi@eecs.umich.edu    0xff,  // AsynchronousExternalAbort (INVALID)
1855952Ssaidi@eecs.umich.edu    0xff,  // AsynchPtyErrOnMemoryAccess (INVALID)
1865952Ssaidi@eecs.umich.edu    0x00,  // AddressSizeL0
1875952Ssaidi@eecs.umich.edu    0x01,  // AddressSizeL1
1885952Ssaidi@eecs.umich.edu    0x02,  // AddressSizeL2
1895952Ssaidi@eecs.umich.edu    0x03,  // AddressSizeL3
1905952Ssaidi@eecs.umich.edu    0x40,  // PrefetchTLBMiss
1915952Ssaidi@eecs.umich.edu    0x80   // PrefetchUncacheable
1925952Ssaidi@eecs.umich.edu};
1935952Ssaidi@eecs.umich.edu
1945952Ssaidi@eecs.umich.edustatic_assert(sizeof(ArmFault::aarch64FaultSources) ==
1955952Ssaidi@eecs.umich.edu              ArmFault::NumFaultSources,
1965952Ssaidi@eecs.umich.edu              "Invalid size of ArmFault::aarch64FaultSources[]");
1975952Ssaidi@eecs.umich.edu
1985952Ssaidi@eecs.umich.edu// Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode,
1995952Ssaidi@eecs.umich.edu//         {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap,
2005952Ssaidi@eecs.umich.edu//         {A, F} disable, class, stat
2015952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals = {
2025952Ssaidi@eecs.umich.edu    // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED
2035952Ssaidi@eecs.umich.edu    // location in AArch64)
2045952Ssaidi@eecs.umich.edu    "Reset",                 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2055952Ssaidi@eecs.umich.edu    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2065952Ssaidi@eecs.umich.edu};
2075952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals = {
2085952Ssaidi@eecs.umich.edu    "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
2095952Ssaidi@eecs.umich.edu    4, 2, 0, 0, true,  false, false, EC_UNKNOWN, FaultStat()
2105952Ssaidi@eecs.umich.edu};
2115952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals = {
2125952Ssaidi@eecs.umich.edu    "Supervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2135952Ssaidi@eecs.umich.edu    4, 2, 4, 2, true,  false, false, EC_SVC_TO_HYP, FaultStat()
2145952Ssaidi@eecs.umich.edu};
2155952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals = {
2165952Ssaidi@eecs.umich.edu    "Secure Monitor Call",   0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2175952Ssaidi@eecs.umich.edu    4, 4, 4, 4, false, true,  true,  EC_SMC_TO_HYP, FaultStat()
2185952Ssaidi@eecs.umich.edu};
2195952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals = {
2205952Ssaidi@eecs.umich.edu    "Hypervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2215952Ssaidi@eecs.umich.edu    4, 4, 4, 4, true,  false, false, EC_HVC, FaultStat()
2225952Ssaidi@eecs.umich.edu};
2235952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals = {
2245952Ssaidi@eecs.umich.edu    "Prefetch Abort",        0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2255952Ssaidi@eecs.umich.edu    4, 4, 0, 0, true,  true,  false, EC_PREFETCH_ABORT_TO_HYP, FaultStat()
2265952Ssaidi@eecs.umich.edu};
2275952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals = {
2285952Ssaidi@eecs.umich.edu    "Data Abort",            0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2295952Ssaidi@eecs.umich.edu    8, 8, 0, 0, true,  true,  false, EC_DATA_ABORT_TO_HYP, FaultStat()
2305952Ssaidi@eecs.umich.edu};
2315952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals = {
2325952Ssaidi@eecs.umich.edu    "Virtual Data Abort",    0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2335952Ssaidi@eecs.umich.edu    8, 8, 0, 0, true,  true,  false, EC_INVALID, FaultStat()
2345952Ssaidi@eecs.umich.edu};
2355952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals = {
2365952Ssaidi@eecs.umich.edu    // @todo: double check these values
2375952Ssaidi@eecs.umich.edu    "Hypervisor Trap",       0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2385952Ssaidi@eecs.umich.edu    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
2395952Ssaidi@eecs.umich.edu};
2405952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals = {
2415952Ssaidi@eecs.umich.edu    "IRQ",                   0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2425952Ssaidi@eecs.umich.edu    4, 4, 0, 0, false, true,  false, EC_UNKNOWN, FaultStat()
2435952Ssaidi@eecs.umich.edu};
2445952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals = {
2455952Ssaidi@eecs.umich.edu    "Virtual IRQ",           0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2465952Ssaidi@eecs.umich.edu    4, 4, 0, 0, false, true,  false, EC_INVALID, FaultStat()
2475952Ssaidi@eecs.umich.edu};
2485952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals = {
2495952Ssaidi@eecs.umich.edu    "FIQ",                   0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2505952Ssaidi@eecs.umich.edu    4, 4, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2515952Ssaidi@eecs.umich.edu};
2525952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals = {
2535952Ssaidi@eecs.umich.edu    "Virtual FIQ",           0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2545952Ssaidi@eecs.umich.edu    4, 4, 0, 0, false, true,  true,  EC_INVALID, FaultStat()
2555952Ssaidi@eecs.umich.edu};
2565952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals = {
2575952Ssaidi@eecs.umich.edu    // Some dummy values (SupervisorTrap is AArch64-only)
2585952Ssaidi@eecs.umich.edu    "Supervisor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2595952Ssaidi@eecs.umich.edu    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
2605952Ssaidi@eecs.umich.edu};
2615952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals = {
2625952Ssaidi@eecs.umich.edu    // Some dummy values (SecureMonitorTrap is AArch64-only)
2635952Ssaidi@eecs.umich.edu    "Secure Monitor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2645952Ssaidi@eecs.umich.edu    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
2655952Ssaidi@eecs.umich.edu};
2665952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals = {
2675952Ssaidi@eecs.umich.edu    // Some dummy values (PCAlignmentFault is AArch64-only)
2685952Ssaidi@eecs.umich.edu    "PC Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2695952Ssaidi@eecs.umich.edu    0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT, FaultStat()
2705952Ssaidi@eecs.umich.edu};
2715952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals = {
2725952Ssaidi@eecs.umich.edu    // Some dummy values (SPAlignmentFault is AArch64-only)
2735952Ssaidi@eecs.umich.edu    "SP Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2745952Ssaidi@eecs.umich.edu    0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT, FaultStat()
2755952Ssaidi@eecs.umich.edu};
2765952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals = {
2775952Ssaidi@eecs.umich.edu    // Some dummy values (SError is AArch64-only)
2785952Ssaidi@eecs.umich.edu    "SError",                0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC,
2795952Ssaidi@eecs.umich.edu    0, 0, 0, 0, false, true,  true,  EC_SERROR, FaultStat()
2805952Ssaidi@eecs.umich.edu};
2815952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals = {
2825952Ssaidi@eecs.umich.edu    // Some dummy values (SoftwareBreakpoint is AArch64-only)
2835952Ssaidi@eecs.umich.edu    "Software Breakpoint",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2845952Ssaidi@eecs.umich.edu    0, 0, 0, 0, true, false, false,  EC_SOFTWARE_BREAKPOINT, FaultStat()
2855952Ssaidi@eecs.umich.edu};
2865952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals = {
2875952Ssaidi@eecs.umich.edu    // Some dummy values
2885952Ssaidi@eecs.umich.edu    "ArmSev Flush",          0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2897823Ssteve.reinhardt@amd.com    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2905952Ssaidi@eecs.umich.edu};
2915952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals = {
2925952Ssaidi@eecs.umich.edu    // Some dummy values (SPAlignmentFault is AArch64-only)
2935952Ssaidi@eecs.umich.edu    "Illegal Inst Set State Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2945952Ssaidi@eecs.umich.edu    0, 0, 0, 0, true, false, false, EC_ILLEGAL_INST, FaultStat()
2955952Ssaidi@eecs.umich.edu};
2965952Ssaidi@eecs.umich.edu
2975952Ssaidi@eecs.umich.eduAddr
2985952Ssaidi@eecs.umich.eduArmFault::getVector(ThreadContext *tc)
2995952Ssaidi@eecs.umich.edu{
3005952Ssaidi@eecs.umich.edu    Addr base;
3015952Ssaidi@eecs.umich.edu
3025952Ssaidi@eecs.umich.edu    // ARM ARM issue C B1.8.1
3035952Ssaidi@eecs.umich.edu    bool haveSecurity = ArmSystem::haveSecurity(tc);
3045952Ssaidi@eecs.umich.edu
3055952Ssaidi@eecs.umich.edu    // panic if SCTLR.VE because I have no idea what to do with vectored
3065952Ssaidi@eecs.umich.edu    // interrupts
3075952Ssaidi@eecs.umich.edu    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
3085952Ssaidi@eecs.umich.edu    assert(!sctlr.ve);
3095952Ssaidi@eecs.umich.edu    // Check for invalid modes
3105952Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
3115952Ssaidi@eecs.umich.edu    assert(haveSecurity                      || cpsr.mode != MODE_MON);
3125952Ssaidi@eecs.umich.edu    assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
3135952Ssaidi@eecs.umich.edu
3145952Ssaidi@eecs.umich.edu    switch (cpsr.mode)
3155952Ssaidi@eecs.umich.edu    {
3165952Ssaidi@eecs.umich.edu      case MODE_MON:
3175952Ssaidi@eecs.umich.edu        base = tc->readMiscReg(MISCREG_MVBAR);
3185952Ssaidi@eecs.umich.edu        break;
3195952Ssaidi@eecs.umich.edu      case MODE_HYP:
3205952Ssaidi@eecs.umich.edu        base = tc->readMiscReg(MISCREG_HVBAR);
3215952Ssaidi@eecs.umich.edu        break;
3225952Ssaidi@eecs.umich.edu      default:
3235952Ssaidi@eecs.umich.edu        if (sctlr.v) {
3245952Ssaidi@eecs.umich.edu            base = HighVecs;
3255952Ssaidi@eecs.umich.edu        } else {
3265952Ssaidi@eecs.umich.edu            base = haveSecurity ? tc->readMiscReg(MISCREG_VBAR) : 0;
3275952Ssaidi@eecs.umich.edu        }
3285952Ssaidi@eecs.umich.edu        break;
3295952Ssaidi@eecs.umich.edu    }
3305952Ssaidi@eecs.umich.edu    return base + offset(tc);
3315952Ssaidi@eecs.umich.edu}
3327823Ssteve.reinhardt@amd.com
3335952Ssaidi@eecs.umich.eduAddr
3345952Ssaidi@eecs.umich.eduArmFault::getVector64(ThreadContext *tc)
3355952Ssaidi@eecs.umich.edu{
3365952Ssaidi@eecs.umich.edu    Addr vbar;
3375952Ssaidi@eecs.umich.edu    switch (toEL) {
3385952Ssaidi@eecs.umich.edu      case EL3:
3395952Ssaidi@eecs.umich.edu        assert(ArmSystem::haveSecurity(tc));
3405952Ssaidi@eecs.umich.edu        vbar = tc->readMiscReg(MISCREG_VBAR_EL3);
3415952Ssaidi@eecs.umich.edu        break;
3425952Ssaidi@eecs.umich.edu      case EL2:
3435952Ssaidi@eecs.umich.edu        assert(ArmSystem::haveVirtualization(tc));
3445952Ssaidi@eecs.umich.edu        vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
3455952Ssaidi@eecs.umich.edu        break;
3465952Ssaidi@eecs.umich.edu      case EL1:
3475952Ssaidi@eecs.umich.edu        vbar = tc->readMiscReg(MISCREG_VBAR_EL1);
3485952Ssaidi@eecs.umich.edu        break;
3495952Ssaidi@eecs.umich.edu      default:
3505952Ssaidi@eecs.umich.edu        panic("Invalid target exception level");
3515952Ssaidi@eecs.umich.edu        break;
3525952Ssaidi@eecs.umich.edu    }
3535952Ssaidi@eecs.umich.edu    return vbar + offset64();
3545952Ssaidi@eecs.umich.edu}
3555952Ssaidi@eecs.umich.edu
3565952Ssaidi@eecs.umich.eduMiscRegIndex
3575952Ssaidi@eecs.umich.eduArmFault::getSyndromeReg64() const
3585952Ssaidi@eecs.umich.edu{
3595952Ssaidi@eecs.umich.edu    switch (toEL) {
3605952Ssaidi@eecs.umich.edu      case EL1:
3615952Ssaidi@eecs.umich.edu        return MISCREG_ESR_EL1;
3625952Ssaidi@eecs.umich.edu      case EL2:
3635952Ssaidi@eecs.umich.edu        return MISCREG_ESR_EL2;
3645952Ssaidi@eecs.umich.edu      case EL3:
3655952Ssaidi@eecs.umich.edu        return MISCREG_ESR_EL3;
3665952Ssaidi@eecs.umich.edu      default:
3675952Ssaidi@eecs.umich.edu        panic("Invalid exception level");
3685952Ssaidi@eecs.umich.edu        break;
3695952Ssaidi@eecs.umich.edu    }
3705952Ssaidi@eecs.umich.edu}
3715952Ssaidi@eecs.umich.edu
3725952Ssaidi@eecs.umich.eduMiscRegIndex
3735952Ssaidi@eecs.umich.eduArmFault::getFaultAddrReg64() const
3745952Ssaidi@eecs.umich.edu{
3755952Ssaidi@eecs.umich.edu    switch (toEL) {
3765952Ssaidi@eecs.umich.edu      case EL1:
3775952Ssaidi@eecs.umich.edu        return MISCREG_FAR_EL1;
3785952Ssaidi@eecs.umich.edu      case EL2:
3795952Ssaidi@eecs.umich.edu        return MISCREG_FAR_EL2;
3805952Ssaidi@eecs.umich.edu      case EL3:
3815952Ssaidi@eecs.umich.edu        return MISCREG_FAR_EL3;
3825952Ssaidi@eecs.umich.edu      default:
3835952Ssaidi@eecs.umich.edu        panic("Invalid exception level");
3845952Ssaidi@eecs.umich.edu        break;
3855952Ssaidi@eecs.umich.edu    }
3865952Ssaidi@eecs.umich.edu}
3875952Ssaidi@eecs.umich.edu
3885952Ssaidi@eecs.umich.eduvoid
3895952Ssaidi@eecs.umich.eduArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
3905952Ssaidi@eecs.umich.edu{
3915952Ssaidi@eecs.umich.edu    uint32_t value;
3925952Ssaidi@eecs.umich.edu    uint32_t exc_class = (uint32_t) ec(tc);
3935952Ssaidi@eecs.umich.edu    uint32_t issVal = iss();
3945952Ssaidi@eecs.umich.edu    assert(!from64 || ArmSystem::highestELIs64(tc));
3955952Ssaidi@eecs.umich.edu
3965952Ssaidi@eecs.umich.edu    value = exc_class << 26;
3975952Ssaidi@eecs.umich.edu
3985952Ssaidi@eecs.umich.edu    // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24,
3995952Ssaidi@eecs.umich.edu    // 0x25) for which the ISS information is not valid (ARMv7).
4005952Ssaidi@eecs.umich.edu    // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not
4015952Ssaidi@eecs.umich.edu    // valid it is treated as RES1.
4025952Ssaidi@eecs.umich.edu    if (to64) {
4035952Ssaidi@eecs.umich.edu        value |= 1 << 25;
4045952Ssaidi@eecs.umich.edu    } else if ((bits(exc_class, 5, 3) != 4) ||
4055952Ssaidi@eecs.umich.edu               (bits(exc_class, 2) && bits(issVal, 24))) {
4065952Ssaidi@eecs.umich.edu        if (!machInst.thumb || machInst.bigThumb)
4075952Ssaidi@eecs.umich.edu            value |= 1 << 25;
4085952Ssaidi@eecs.umich.edu    }
4095952Ssaidi@eecs.umich.edu    // Condition code valid for EC[5:4] nonzero
4105952Ssaidi@eecs.umich.edu    if (!from64 && ((bits(exc_class, 5, 4) == 0) &&
4115952Ssaidi@eecs.umich.edu                    (bits(exc_class, 3, 0) != 0))) {
4125952Ssaidi@eecs.umich.edu        if (!machInst.thumb) {
4135952Ssaidi@eecs.umich.edu            uint32_t      cond;
4145952Ssaidi@eecs.umich.edu            ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode;
4155952Ssaidi@eecs.umich.edu            // If its on unconditional instruction report with a cond code of
4165952Ssaidi@eecs.umich.edu            // 0xE, ie the unconditional code
4175952Ssaidi@eecs.umich.edu            cond  = (condCode == COND_UC) ? COND_AL : condCode;
4185952Ssaidi@eecs.umich.edu            value |= cond << 20;
4195952Ssaidi@eecs.umich.edu            value |= 1    << 24;
4205952Ssaidi@eecs.umich.edu        }
4215952Ssaidi@eecs.umich.edu        value |= bits(issVal, 19, 0);
4225952Ssaidi@eecs.umich.edu    } else {
4235952Ssaidi@eecs.umich.edu        value |= issVal;
4245952Ssaidi@eecs.umich.edu    }
4255952Ssaidi@eecs.umich.edu    tc->setMiscReg(syndrome_reg, value);
4265952Ssaidi@eecs.umich.edu}
4275952Ssaidi@eecs.umich.edu
4285952Ssaidi@eecs.umich.eduvoid
4295952Ssaidi@eecs.umich.eduArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
4305952Ssaidi@eecs.umich.edu{
4315952Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
4325952Ssaidi@eecs.umich.edu
4335952Ssaidi@eecs.umich.edu    if (ArmSystem::highestELIs64(tc)) {  // ARMv8
4345952Ssaidi@eecs.umich.edu        // Determine source exception level and mode
4355952Ssaidi@eecs.umich.edu        fromMode = (OperatingMode) (uint8_t) cpsr.mode;
4365952Ssaidi@eecs.umich.edu        fromEL = opModeToEL(fromMode);
4375952Ssaidi@eecs.umich.edu        if (opModeIs64(fromMode))
4385952Ssaidi@eecs.umich.edu            from64 = true;
4395952Ssaidi@eecs.umich.edu
4405952Ssaidi@eecs.umich.edu        // Determine target exception level
4415952Ssaidi@eecs.umich.edu        if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc))
4425952Ssaidi@eecs.umich.edu            toEL = EL3;
4435952Ssaidi@eecs.umich.edu        else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc))
4445952Ssaidi@eecs.umich.edu            toEL = EL2;
4455952Ssaidi@eecs.umich.edu        else
4465952Ssaidi@eecs.umich.edu            toEL = opModeToEL(nextMode());
4475952Ssaidi@eecs.umich.edu        if (fromEL > toEL)
4485952Ssaidi@eecs.umich.edu            toEL = fromEL;
4495952Ssaidi@eecs.umich.edu
4505952Ssaidi@eecs.umich.edu        if (toEL == ArmSystem::highestEL(tc) || ELIs64(tc, toEL)) {
4515952Ssaidi@eecs.umich.edu            // Invoke exception handler in AArch64 state
4525952Ssaidi@eecs.umich.edu            to64 = true;
4535952Ssaidi@eecs.umich.edu            invoke64(tc, inst);
4545952Ssaidi@eecs.umich.edu            return;
4555952Ssaidi@eecs.umich.edu        }
4565952Ssaidi@eecs.umich.edu    }
4575952Ssaidi@eecs.umich.edu
4585952Ssaidi@eecs.umich.edu    // ARMv7 (ARM ARM issue C B1.9)
4595952Ssaidi@eecs.umich.edu
4605952Ssaidi@eecs.umich.edu    bool have_security       = ArmSystem::haveSecurity(tc);
4615952Ssaidi@eecs.umich.edu    bool have_virtualization = ArmSystem::haveVirtualization(tc);
4625952Ssaidi@eecs.umich.edu
4635952Ssaidi@eecs.umich.edu    FaultBase::invoke(tc);
4645952Ssaidi@eecs.umich.edu    if (!FullSystem)
4655952Ssaidi@eecs.umich.edu        return;
4665952Ssaidi@eecs.umich.edu    countStat()++;
4675952Ssaidi@eecs.umich.edu
4685952Ssaidi@eecs.umich.edu    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
4695952Ssaidi@eecs.umich.edu    SCR scr = tc->readMiscReg(MISCREG_SCR);
4705952Ssaidi@eecs.umich.edu    CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR);
4715952Ssaidi@eecs.umich.edu    saved_cpsr.nz = tc->readCCReg(CCREG_NZ);
4725952Ssaidi@eecs.umich.edu    saved_cpsr.c = tc->readCCReg(CCREG_C);
4735952Ssaidi@eecs.umich.edu    saved_cpsr.v = tc->readCCReg(CCREG_V);
4745952Ssaidi@eecs.umich.edu    saved_cpsr.ge = tc->readCCReg(CCREG_GE);
4755952Ssaidi@eecs.umich.edu
4765952Ssaidi@eecs.umich.edu    Addr curPc M5_VAR_USED = tc->pcState().pc();
4775952Ssaidi@eecs.umich.edu    ITSTATE it = tc->pcState().itstate();
4785952Ssaidi@eecs.umich.edu    saved_cpsr.it2 = it.top6;
4795952Ssaidi@eecs.umich.edu    saved_cpsr.it1 = it.bottom2;
4805952Ssaidi@eecs.umich.edu
4815952Ssaidi@eecs.umich.edu    // if we have a valid instruction then use it to annotate this fault with
4825952Ssaidi@eecs.umich.edu    // extra information. This is used to generate the correct fault syndrome
4835952Ssaidi@eecs.umich.edu    // information
4845952Ssaidi@eecs.umich.edu    if (inst) {
4855952Ssaidi@eecs.umich.edu        ArmStaticInst *armInst = reinterpret_cast<ArmStaticInst *>(inst.get());
4865952Ssaidi@eecs.umich.edu        armInst->annotateFault(this);
4875952Ssaidi@eecs.umich.edu    }
4885952Ssaidi@eecs.umich.edu
4895952Ssaidi@eecs.umich.edu    if (have_security && routeToMonitor(tc))
4905952Ssaidi@eecs.umich.edu        cpsr.mode = MODE_MON;
4915952Ssaidi@eecs.umich.edu    else if (have_virtualization && routeToHyp(tc))
4925952Ssaidi@eecs.umich.edu        cpsr.mode = MODE_HYP;
4935952Ssaidi@eecs.umich.edu    else
4945952Ssaidi@eecs.umich.edu        cpsr.mode = nextMode();
4955952Ssaidi@eecs.umich.edu
4965952Ssaidi@eecs.umich.edu    // Ensure Secure state if initially in Monitor mode
4975952Ssaidi@eecs.umich.edu    if (have_security && saved_cpsr.mode == MODE_MON) {
4985952Ssaidi@eecs.umich.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
4995952Ssaidi@eecs.umich.edu        if (scr.ns) {
5005952Ssaidi@eecs.umich.edu            scr.ns = 0;
5015952Ssaidi@eecs.umich.edu            tc->setMiscRegNoEffect(MISCREG_SCR, scr);
5025952Ssaidi@eecs.umich.edu        }
5035952Ssaidi@eecs.umich.edu    }
5045952Ssaidi@eecs.umich.edu
5055952Ssaidi@eecs.umich.edu    // some bits are set differently if we have been routed to hyp mode
5065952Ssaidi@eecs.umich.edu    if (cpsr.mode == MODE_HYP) {
5075952Ssaidi@eecs.umich.edu        SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR);
5085952Ssaidi@eecs.umich.edu        cpsr.t = hsctlr.te;
5095952Ssaidi@eecs.umich.edu        cpsr.e = hsctlr.ee;
5105952Ssaidi@eecs.umich.edu        if (!scr.ea)  {cpsr.a = 1;}
5115952Ssaidi@eecs.umich.edu        if (!scr.fiq) {cpsr.f = 1;}
5125952Ssaidi@eecs.umich.edu        if (!scr.irq) {cpsr.i = 1;}
5135952Ssaidi@eecs.umich.edu    } else if (cpsr.mode == MODE_MON) {
5145952Ssaidi@eecs.umich.edu        // Special case handling when entering monitor mode
5155952Ssaidi@eecs.umich.edu        cpsr.t = sctlr.te;
5165952Ssaidi@eecs.umich.edu        cpsr.e = sctlr.ee;
5175952Ssaidi@eecs.umich.edu        cpsr.a = 1;
5185952Ssaidi@eecs.umich.edu        cpsr.f = 1;
5195952Ssaidi@eecs.umich.edu        cpsr.i = 1;
5205952Ssaidi@eecs.umich.edu    } else {
5215952Ssaidi@eecs.umich.edu        cpsr.t = sctlr.te;
5225952Ssaidi@eecs.umich.edu        cpsr.e = sctlr.ee;
5235952Ssaidi@eecs.umich.edu
5245952Ssaidi@eecs.umich.edu        // The *Disable functions are virtual and different per fault
5255952Ssaidi@eecs.umich.edu        cpsr.a = cpsr.a | abortDisable(tc);
5265952Ssaidi@eecs.umich.edu        cpsr.f = cpsr.f | fiqDisable(tc);
5275952Ssaidi@eecs.umich.edu        cpsr.i = 1;
5285952Ssaidi@eecs.umich.edu    }
5295952Ssaidi@eecs.umich.edu    cpsr.it1 = cpsr.it2 = 0;
5305952Ssaidi@eecs.umich.edu    cpsr.j = 0;
5315952Ssaidi@eecs.umich.edu    tc->setMiscReg(MISCREG_CPSR, cpsr);
5325952Ssaidi@eecs.umich.edu
5335952Ssaidi@eecs.umich.edu    // Make sure mailbox sets to one always
5345952Ssaidi@eecs.umich.edu    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
5355952Ssaidi@eecs.umich.edu
5365952Ssaidi@eecs.umich.edu    // Clear the exclusive monitor
5375952Ssaidi@eecs.umich.edu    tc->setMiscReg(MISCREG_LOCKFLAG, 0);
5385952Ssaidi@eecs.umich.edu
5395952Ssaidi@eecs.umich.edu    if (cpsr.mode == MODE_HYP) {
5405952Ssaidi@eecs.umich.edu        tc->setMiscReg(MISCREG_ELR_HYP, curPc +
5415952Ssaidi@eecs.umich.edu                (saved_cpsr.t ? thumbPcOffset(true)  : armPcOffset(true)));
5425952Ssaidi@eecs.umich.edu    } else {
5435952Ssaidi@eecs.umich.edu        tc->setIntReg(INTREG_LR, curPc +
5445952Ssaidi@eecs.umich.edu                (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false)));
5455952Ssaidi@eecs.umich.edu    }
5465952Ssaidi@eecs.umich.edu
5475952Ssaidi@eecs.umich.edu    switch (cpsr.mode) {
5485952Ssaidi@eecs.umich.edu      case MODE_FIQ:
5495952Ssaidi@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
5505952Ssaidi@eecs.umich.edu        break;
5515952Ssaidi@eecs.umich.edu      case MODE_IRQ:
5525952Ssaidi@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
5535952Ssaidi@eecs.umich.edu        break;
5545952Ssaidi@eecs.umich.edu      case MODE_SVC:
5555952Ssaidi@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
5565952Ssaidi@eecs.umich.edu        break;
5575952Ssaidi@eecs.umich.edu      case MODE_MON:
5585952Ssaidi@eecs.umich.edu        assert(have_security);
5595952Ssaidi@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr);
5605952Ssaidi@eecs.umich.edu        break;
5615952Ssaidi@eecs.umich.edu      case MODE_ABORT:
5625952Ssaidi@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
5635952Ssaidi@eecs.umich.edu        break;
5645952Ssaidi@eecs.umich.edu      case MODE_UNDEFINED:
5655952Ssaidi@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
5665952Ssaidi@eecs.umich.edu        if (ec(tc) != EC_UNKNOWN)
5675952Ssaidi@eecs.umich.edu            setSyndrome(tc, MISCREG_HSR);
5685952Ssaidi@eecs.umich.edu        break;
5695952Ssaidi@eecs.umich.edu      case MODE_HYP:
5705952Ssaidi@eecs.umich.edu        assert(have_virtualization);
5715952Ssaidi@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr);
5725952Ssaidi@eecs.umich.edu        setSyndrome(tc, MISCREG_HSR);
5735952Ssaidi@eecs.umich.edu        break;
5745952Ssaidi@eecs.umich.edu      default:
5755952Ssaidi@eecs.umich.edu        panic("unknown Mode\n");
5765952Ssaidi@eecs.umich.edu    }
5775952Ssaidi@eecs.umich.edu
5785952Ssaidi@eecs.umich.edu    Addr newPc = getVector(tc);
5795952Ssaidi@eecs.umich.edu    DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n",
5805952Ssaidi@eecs.umich.edu            name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc);
5815952Ssaidi@eecs.umich.edu    PCState pc(newPc);
5825952Ssaidi@eecs.umich.edu    pc.thumb(cpsr.t);
5835952Ssaidi@eecs.umich.edu    pc.nextThumb(pc.thumb());
5845952Ssaidi@eecs.umich.edu    pc.jazelle(cpsr.j);
5855952Ssaidi@eecs.umich.edu    pc.nextJazelle(pc.jazelle());
5865952Ssaidi@eecs.umich.edu    pc.aarch64(!cpsr.width);
5875952Ssaidi@eecs.umich.edu    pc.nextAArch64(!cpsr.width);
5885952Ssaidi@eecs.umich.edu    tc->pcState(pc);
5895952Ssaidi@eecs.umich.edu}
5905952Ssaidi@eecs.umich.edu
5915952Ssaidi@eecs.umich.eduvoid
5925952Ssaidi@eecs.umich.eduArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
5935952Ssaidi@eecs.umich.edu{
5945952Ssaidi@eecs.umich.edu    // Determine actual misc. register indices for ELR_ELx and SPSR_ELx
5955952Ssaidi@eecs.umich.edu    MiscRegIndex elr_idx, spsr_idx;
5965952Ssaidi@eecs.umich.edu    switch (toEL) {
5975952Ssaidi@eecs.umich.edu      case EL1:
5985952Ssaidi@eecs.umich.edu        elr_idx = MISCREG_ELR_EL1;
5995952Ssaidi@eecs.umich.edu        spsr_idx = MISCREG_SPSR_EL1;
6005952Ssaidi@eecs.umich.edu        break;
6015952Ssaidi@eecs.umich.edu      case EL2:
6025952Ssaidi@eecs.umich.edu        assert(ArmSystem::haveVirtualization(tc));
6035952Ssaidi@eecs.umich.edu        elr_idx = MISCREG_ELR_EL2;
6045952Ssaidi@eecs.umich.edu        spsr_idx = MISCREG_SPSR_EL2;
6055952Ssaidi@eecs.umich.edu        break;
6065952Ssaidi@eecs.umich.edu      case EL3:
6075952Ssaidi@eecs.umich.edu        assert(ArmSystem::haveSecurity(tc));
6085952Ssaidi@eecs.umich.edu        elr_idx = MISCREG_ELR_EL3;
6095952Ssaidi@eecs.umich.edu        spsr_idx = MISCREG_SPSR_EL3;
6105952Ssaidi@eecs.umich.edu        break;
6115952Ssaidi@eecs.umich.edu      default:
6125952Ssaidi@eecs.umich.edu        panic("Invalid target exception level");
6135952Ssaidi@eecs.umich.edu        break;
6145952Ssaidi@eecs.umich.edu    }
6155952Ssaidi@eecs.umich.edu
6165952Ssaidi@eecs.umich.edu    // Save process state into SPSR_ELx
6175952Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
6185952Ssaidi@eecs.umich.edu    CPSR spsr = cpsr;
6195952Ssaidi@eecs.umich.edu    spsr.nz = tc->readCCReg(CCREG_NZ);
6205952Ssaidi@eecs.umich.edu    spsr.c = tc->readCCReg(CCREG_C);
6215952Ssaidi@eecs.umich.edu    spsr.v = tc->readCCReg(CCREG_V);
6225952Ssaidi@eecs.umich.edu    if (from64) {
6235952Ssaidi@eecs.umich.edu        // Force some bitfields to 0
6245952Ssaidi@eecs.umich.edu        spsr.q = 0;
6255952Ssaidi@eecs.umich.edu        spsr.it1 = 0;
6265952Ssaidi@eecs.umich.edu        spsr.j = 0;
6275952Ssaidi@eecs.umich.edu        spsr.res0_23_22 = 0;
6285952Ssaidi@eecs.umich.edu        spsr.ge = 0;
6295952Ssaidi@eecs.umich.edu        spsr.it2 = 0;
6305952Ssaidi@eecs.umich.edu        spsr.t = 0;
6315952Ssaidi@eecs.umich.edu    } else {
6325952Ssaidi@eecs.umich.edu        spsr.ge = tc->readCCReg(CCREG_GE);
6335952Ssaidi@eecs.umich.edu        ITSTATE it = tc->pcState().itstate();
6345952Ssaidi@eecs.umich.edu        spsr.it2 = it.top6;
6355952Ssaidi@eecs.umich.edu        spsr.it1 = it.bottom2;
6365952Ssaidi@eecs.umich.edu        // Force some bitfields to 0
6375952Ssaidi@eecs.umich.edu        spsr.res0_23_22 = 0;
6385952Ssaidi@eecs.umich.edu        spsr.ss = 0;
6395952Ssaidi@eecs.umich.edu    }
6405952Ssaidi@eecs.umich.edu    tc->setMiscReg(spsr_idx, spsr);
6415952Ssaidi@eecs.umich.edu
6425952Ssaidi@eecs.umich.edu    // Save preferred return address into ELR_ELx
6435952Ssaidi@eecs.umich.edu    Addr curr_pc = tc->pcState().pc();
6445952Ssaidi@eecs.umich.edu    Addr ret_addr = curr_pc;
6455952Ssaidi@eecs.umich.edu    if (from64)
6465952Ssaidi@eecs.umich.edu        ret_addr += armPcElrOffset();
6475952Ssaidi@eecs.umich.edu    else
6485952Ssaidi@eecs.umich.edu        ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset();
6495952Ssaidi@eecs.umich.edu    tc->setMiscReg(elr_idx, ret_addr);
6505952Ssaidi@eecs.umich.edu
6515952Ssaidi@eecs.umich.edu    // Update process state
6525952Ssaidi@eecs.umich.edu    OperatingMode64 mode = 0;
6535952Ssaidi@eecs.umich.edu    mode.spX = 1;
6545952Ssaidi@eecs.umich.edu    mode.el = toEL;
6555952Ssaidi@eecs.umich.edu    mode.width = 0;
6565952Ssaidi@eecs.umich.edu    cpsr.mode = mode;
6575952Ssaidi@eecs.umich.edu    cpsr.daif = 0xf;
6585952Ssaidi@eecs.umich.edu    cpsr.il = 0;
6595952Ssaidi@eecs.umich.edu    cpsr.ss = 0;
6605952Ssaidi@eecs.umich.edu    tc->setMiscReg(MISCREG_CPSR, cpsr);
6615952Ssaidi@eecs.umich.edu
6625952Ssaidi@eecs.umich.edu    // Set PC to start of exception handler
6635952Ssaidi@eecs.umich.edu    Addr new_pc = purifyTaggedAddr(getVector64(tc), tc, toEL);
6645952Ssaidi@eecs.umich.edu    DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x "
6655952Ssaidi@eecs.umich.edu            "elr:%#x newVec: %#x\n", name(), cpsr, curr_pc, ret_addr, new_pc);
6665952Ssaidi@eecs.umich.edu    PCState pc(new_pc);
6675952Ssaidi@eecs.umich.edu    pc.aarch64(!cpsr.width);
6685952Ssaidi@eecs.umich.edu    pc.nextAArch64(!cpsr.width);
6695952Ssaidi@eecs.umich.edu    tc->pcState(pc);
6705952Ssaidi@eecs.umich.edu
6715952Ssaidi@eecs.umich.edu    // If we have a valid instruction then use it to annotate this fault with
6725952Ssaidi@eecs.umich.edu    // extra information. This is used to generate the correct fault syndrome
6735952Ssaidi@eecs.umich.edu    // information
6745952Ssaidi@eecs.umich.edu    if (inst)
6755952Ssaidi@eecs.umich.edu        reinterpret_cast<ArmStaticInst *>(inst.get())->annotateFault(this);
6765952Ssaidi@eecs.umich.edu    // Save exception syndrome
6775952Ssaidi@eecs.umich.edu    if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ))
6785952Ssaidi@eecs.umich.edu        setSyndrome(tc, getSyndromeReg64());
6795952Ssaidi@eecs.umich.edu}
6805952Ssaidi@eecs.umich.edu
6815952Ssaidi@eecs.umich.eduvoid
6825952Ssaidi@eecs.umich.eduReset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
6835952Ssaidi@eecs.umich.edu{
6845952Ssaidi@eecs.umich.edu    if (FullSystem) {
6855952Ssaidi@eecs.umich.edu        tc->getCpuPtr()->clearInterrupts(tc->threadId());
6865952Ssaidi@eecs.umich.edu        tc->clearArchRegs();
6875952Ssaidi@eecs.umich.edu    }
6885952Ssaidi@eecs.umich.edu    if (!ArmSystem::highestELIs64(tc)) {
6895952Ssaidi@eecs.umich.edu        ArmFault::invoke(tc, inst);
6905952Ssaidi@eecs.umich.edu        tc->setMiscReg(MISCREG_VMPIDR,
6915952Ssaidi@eecs.umich.edu                       getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc));
6925952Ssaidi@eecs.umich.edu
6935952Ssaidi@eecs.umich.edu        // Unless we have SMC code to get us there, boot in HYP!
6945952Ssaidi@eecs.umich.edu        if (ArmSystem::haveVirtualization(tc) &&
6955952Ssaidi@eecs.umich.edu            !ArmSystem::haveSecurity(tc)) {
6965952Ssaidi@eecs.umich.edu            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
6975952Ssaidi@eecs.umich.edu            cpsr.mode = MODE_HYP;
6985952Ssaidi@eecs.umich.edu            tc->setMiscReg(MISCREG_CPSR, cpsr);
6995952Ssaidi@eecs.umich.edu        }
7005952Ssaidi@eecs.umich.edu    } else {
7017823Ssteve.reinhardt@amd.com        // Advance the PC to the IMPLEMENTATION DEFINED reset value
7025952Ssaidi@eecs.umich.edu        PCState pc = ArmSystem::resetAddr64(tc);
7035952Ssaidi@eecs.umich.edu        pc.aarch64(true);
7047823Ssteve.reinhardt@amd.com        pc.nextAArch64(true);
7055952Ssaidi@eecs.umich.edu        tc->pcState(pc);
7065952Ssaidi@eecs.umich.edu    }
7075952Ssaidi@eecs.umich.edu}
7085952Ssaidi@eecs.umich.edu
7095952Ssaidi@eecs.umich.eduvoid
7105952Ssaidi@eecs.umich.eduUndefinedInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
7115952Ssaidi@eecs.umich.edu{
7125952Ssaidi@eecs.umich.edu    if (FullSystem) {
7135952Ssaidi@eecs.umich.edu        ArmFault::invoke(tc, inst);
7145952Ssaidi@eecs.umich.edu        return;
7155952Ssaidi@eecs.umich.edu    }
7165952Ssaidi@eecs.umich.edu
7175952Ssaidi@eecs.umich.edu    // If the mnemonic isn't defined this has to be an unknown instruction.
7185952Ssaidi@eecs.umich.edu    assert(unknown || mnemonic != NULL);
7195952Ssaidi@eecs.umich.edu    if (disabled) {
7205952Ssaidi@eecs.umich.edu        panic("Attempted to execute disabled instruction "
7215952Ssaidi@eecs.umich.edu                "'%s' (inst 0x%08x)", mnemonic, machInst);
7225952Ssaidi@eecs.umich.edu    } else if (unknown) {
7235952Ssaidi@eecs.umich.edu        panic("Attempted to execute unknown instruction (inst 0x%08x)",
7245952Ssaidi@eecs.umich.edu              machInst);
7255952Ssaidi@eecs.umich.edu    } else {
7265952Ssaidi@eecs.umich.edu        panic("Attempted to execute unimplemented instruction "
7275952Ssaidi@eecs.umich.edu                "'%s' (inst 0x%08x)", mnemonic, machInst);
7285952Ssaidi@eecs.umich.edu    }
7295952Ssaidi@eecs.umich.edu}
7305952Ssaidi@eecs.umich.edu
7315952Ssaidi@eecs.umich.edubool
7325952Ssaidi@eecs.umich.eduUndefinedInstruction::routeToHyp(ThreadContext *tc) const
7335952Ssaidi@eecs.umich.edu{
7345952Ssaidi@eecs.umich.edu    bool toHyp;
7355952Ssaidi@eecs.umich.edu
7365952Ssaidi@eecs.umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
7375952Ssaidi@eecs.umich.edu    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
7385952Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
7395952Ssaidi@eecs.umich.edu
7405952Ssaidi@eecs.umich.edu    // if in Hyp mode then stay in Hyp mode
7415952Ssaidi@eecs.umich.edu    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
7425952Ssaidi@eecs.umich.edu    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
7435952Ssaidi@eecs.umich.edu    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
7445952Ssaidi@eecs.umich.edu    return toHyp;
7455952Ssaidi@eecs.umich.edu}
7465952Ssaidi@eecs.umich.edu
7475952Ssaidi@eecs.umich.eduuint32_t
7485952Ssaidi@eecs.umich.eduUndefinedInstruction::iss() const
7495952Ssaidi@eecs.umich.edu{
7505952Ssaidi@eecs.umich.edu    if (overrideEc == EC_INVALID)
7515952Ssaidi@eecs.umich.edu        return issRaw;
7525952Ssaidi@eecs.umich.edu
7535952Ssaidi@eecs.umich.edu    uint32_t new_iss = 0;
7545952Ssaidi@eecs.umich.edu    uint32_t op0, op1, op2, CRn, CRm, Rt, dir;
7555952Ssaidi@eecs.umich.edu
7565952Ssaidi@eecs.umich.edu    dir = bits(machInst, 21, 21);
7575952Ssaidi@eecs.umich.edu    op0 = bits(machInst, 20, 19);
7585952Ssaidi@eecs.umich.edu    op1 = bits(machInst, 18, 16);
7595952Ssaidi@eecs.umich.edu    CRn = bits(machInst, 15, 12);
7605952Ssaidi@eecs.umich.edu    CRm = bits(machInst, 11, 8);
7615952Ssaidi@eecs.umich.edu    op2 = bits(machInst, 7, 5);
7625952Ssaidi@eecs.umich.edu    Rt = bits(machInst, 4, 0);
7635952Ssaidi@eecs.umich.edu
7645952Ssaidi@eecs.umich.edu    new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 |
7655952Ssaidi@eecs.umich.edu            Rt << 5 | CRm << 1 | dir;
7665952Ssaidi@eecs.umich.edu
7675952Ssaidi@eecs.umich.edu    return new_iss;
7685952Ssaidi@eecs.umich.edu}
7695952Ssaidi@eecs.umich.edu
7705952Ssaidi@eecs.umich.eduvoid
7715952Ssaidi@eecs.umich.eduSupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
7725952Ssaidi@eecs.umich.edu{
7735952Ssaidi@eecs.umich.edu    if (FullSystem) {
7745952Ssaidi@eecs.umich.edu        ArmFault::invoke(tc, inst);
7755952Ssaidi@eecs.umich.edu        return;
7765952Ssaidi@eecs.umich.edu    }
7775952Ssaidi@eecs.umich.edu
7785952Ssaidi@eecs.umich.edu    // As of now, there isn't a 32 bit thumb version of this instruction.
7795952Ssaidi@eecs.umich.edu    assert(!machInst.bigThumb);
7805952Ssaidi@eecs.umich.edu    uint32_t callNum;
7815952Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
7825952Ssaidi@eecs.umich.edu    OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
7835952Ssaidi@eecs.umich.edu    if (opModeIs64(mode))
7845952Ssaidi@eecs.umich.edu        callNum = tc->readIntReg(INTREG_X8);
7855952Ssaidi@eecs.umich.edu    else
7865952Ssaidi@eecs.umich.edu        callNum = tc->readIntReg(INTREG_R7);
7875952Ssaidi@eecs.umich.edu    Fault fault;
7885952Ssaidi@eecs.umich.edu    tc->syscall(callNum, &fault);
7895952Ssaidi@eecs.umich.edu
7905952Ssaidi@eecs.umich.edu    // Advance the PC since that won't happen automatically.
7915952Ssaidi@eecs.umich.edu    PCState pc = tc->pcState();
7925952Ssaidi@eecs.umich.edu    assert(inst);
7935952Ssaidi@eecs.umich.edu    inst->advancePC(pc);
7945952Ssaidi@eecs.umich.edu    tc->pcState(pc);
7955952Ssaidi@eecs.umich.edu}
7965952Ssaidi@eecs.umich.edu
7975952Ssaidi@eecs.umich.edubool
7985952Ssaidi@eecs.umich.eduSupervisorCall::routeToHyp(ThreadContext *tc) const
7995952Ssaidi@eecs.umich.edu{
8005952Ssaidi@eecs.umich.edu    bool toHyp;
8015952Ssaidi@eecs.umich.edu
8025952Ssaidi@eecs.umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
8035952Ssaidi@eecs.umich.edu    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
8045952Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
8055952Ssaidi@eecs.umich.edu
8065952Ssaidi@eecs.umich.edu    // if in Hyp mode then stay in Hyp mode
8075952Ssaidi@eecs.umich.edu    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
8085952Ssaidi@eecs.umich.edu    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
8095952Ssaidi@eecs.umich.edu    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
8105952Ssaidi@eecs.umich.edu    return toHyp;
8115952Ssaidi@eecs.umich.edu}
8125952Ssaidi@eecs.umich.edu
8135952Ssaidi@eecs.umich.eduExceptionClass
8145952Ssaidi@eecs.umich.eduSupervisorCall::ec(ThreadContext *tc) const
8155952Ssaidi@eecs.umich.edu{
8165952Ssaidi@eecs.umich.edu    return (overrideEc != EC_INVALID) ? overrideEc :
8175952Ssaidi@eecs.umich.edu        (from64 ? EC_SVC_64 : vals.ec);
8185952Ssaidi@eecs.umich.edu}
8195952Ssaidi@eecs.umich.edu
8205952Ssaidi@eecs.umich.eduuint32_t
8215952Ssaidi@eecs.umich.eduSupervisorCall::iss() const
8225952Ssaidi@eecs.umich.edu{
8235952Ssaidi@eecs.umich.edu    // Even if we have a 24 bit imm from an arm32 instruction then we only use
8245952Ssaidi@eecs.umich.edu    // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC).
82510470Sandreas.hansson@arm.com    return issRaw & 0xFFFF;
8267823Ssteve.reinhardt@amd.com}
8275952Ssaidi@eecs.umich.edu
8285952Ssaidi@eecs.umich.eduuint32_t
8295952Ssaidi@eecs.umich.eduSecureMonitorCall::iss() const
8305952Ssaidi@eecs.umich.edu{
8315952Ssaidi@eecs.umich.edu    if (from64)
8325952Ssaidi@eecs.umich.edu        return bits(machInst, 20, 5);
8335952Ssaidi@eecs.umich.edu    return 0;
8345952Ssaidi@eecs.umich.edu}
8355952Ssaidi@eecs.umich.edu
8365952Ssaidi@eecs.umich.eduExceptionClass
8375952Ssaidi@eecs.umich.eduUndefinedInstruction::ec(ThreadContext *tc) const
8385952Ssaidi@eecs.umich.edu{
8395952Ssaidi@eecs.umich.edu    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
8405952Ssaidi@eecs.umich.edu}
8415952Ssaidi@eecs.umich.edu
8425952Ssaidi@eecs.umich.edu
8435952Ssaidi@eecs.umich.eduHypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) :
8445952Ssaidi@eecs.umich.edu        ArmFaultVals<HypervisorCall>(_machInst, _imm)
8455952Ssaidi@eecs.umich.edu{}
8465952Ssaidi@eecs.umich.edu
8475952Ssaidi@eecs.umich.eduExceptionClass
8485952Ssaidi@eecs.umich.eduHypervisorCall::ec(ThreadContext *tc) const
8495952Ssaidi@eecs.umich.edu{
8505952Ssaidi@eecs.umich.edu    return from64 ? EC_HVC_64 : vals.ec;
8515952Ssaidi@eecs.umich.edu}
8525952Ssaidi@eecs.umich.edu
8535952Ssaidi@eecs.umich.eduExceptionClass
8545952Ssaidi@eecs.umich.eduHypervisorTrap::ec(ThreadContext *tc) const
8555952Ssaidi@eecs.umich.edu{
8565952Ssaidi@eecs.umich.edu    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
8575952Ssaidi@eecs.umich.edu}
8585952Ssaidi@eecs.umich.edu
8595952Ssaidi@eecs.umich.edutemplate<class T>
8605952Ssaidi@eecs.umich.eduFaultOffset
8615952Ssaidi@eecs.umich.eduArmFaultVals<T>::offset(ThreadContext *tc)
8625952Ssaidi@eecs.umich.edu{
8635952Ssaidi@eecs.umich.edu    bool isHypTrap = false;
8645952Ssaidi@eecs.umich.edu
8655952Ssaidi@eecs.umich.edu    // Normally we just use the exception vector from the table at the top if
8665952Ssaidi@eecs.umich.edu    // this file, however if this exception has caused a transition to hype
8675952Ssaidi@eecs.umich.edu    // mode, and its an exception type that would only do this if it has been
8685952Ssaidi@eecs.umich.edu    // trapped then we use the hyp trap vector instead of the normal vector
8695952Ssaidi@eecs.umich.edu    if (vals.hypTrappable) {
8705952Ssaidi@eecs.umich.edu        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
8715952Ssaidi@eecs.umich.edu        if (cpsr.mode == MODE_HYP) {
8725952Ssaidi@eecs.umich.edu            CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
8735952Ssaidi@eecs.umich.edu            isHypTrap = spsr.mode != MODE_HYP;
8745952Ssaidi@eecs.umich.edu        }
8755952Ssaidi@eecs.umich.edu    }
8765952Ssaidi@eecs.umich.edu    return isHypTrap ? 0x14 : vals.offset;
8775952Ssaidi@eecs.umich.edu}
8785952Ssaidi@eecs.umich.edu
8795952Ssaidi@eecs.umich.edu// void
8805952Ssaidi@eecs.umich.edu// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx)
8815952Ssaidi@eecs.umich.edu// {
8825952Ssaidi@eecs.umich.edu//     ESR esr = 0;
8835952Ssaidi@eecs.umich.edu//     esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32;
8845952Ssaidi@eecs.umich.edu//     esr.il = !machInst.thumb;
8855952Ssaidi@eecs.umich.edu//     if (machInst.aarch64)
8865952Ssaidi@eecs.umich.edu//         esr.imm16 = bits(machInst.instBits, 20, 5);
8875952Ssaidi@eecs.umich.edu//     else if (machInst.thumb)
8885952Ssaidi@eecs.umich.edu//         esr.imm16 = bits(machInst.instBits, 7, 0);
8895952Ssaidi@eecs.umich.edu//     else
8905952Ssaidi@eecs.umich.edu//         esr.imm16 = bits(machInst.instBits, 15, 0);
8915952Ssaidi@eecs.umich.edu//     tc->setMiscReg(esr_idx, esr);
8925952Ssaidi@eecs.umich.edu// }
8935952Ssaidi@eecs.umich.edu
8945952Ssaidi@eecs.umich.eduvoid
8955952Ssaidi@eecs.umich.eduSecureMonitorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
8965952Ssaidi@eecs.umich.edu{
8975952Ssaidi@eecs.umich.edu    if (FullSystem) {
8985952Ssaidi@eecs.umich.edu        ArmFault::invoke(tc, inst);
8995952Ssaidi@eecs.umich.edu        return;
9005952Ssaidi@eecs.umich.edu    }
9015952Ssaidi@eecs.umich.edu}
9025952Ssaidi@eecs.umich.edu
9035952Ssaidi@eecs.umich.eduExceptionClass
9045952Ssaidi@eecs.umich.eduSecureMonitorCall::ec(ThreadContext *tc) const
9055952Ssaidi@eecs.umich.edu{
9065952Ssaidi@eecs.umich.edu    return (from64 ? EC_SMC_64 : vals.ec);
9075952Ssaidi@eecs.umich.edu}
9085952Ssaidi@eecs.umich.edu
9095952Ssaidi@eecs.umich.eduExceptionClass
9105952Ssaidi@eecs.umich.eduSupervisorTrap::ec(ThreadContext *tc) const
9115952Ssaidi@eecs.umich.edu{
9125952Ssaidi@eecs.umich.edu    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
9135952Ssaidi@eecs.umich.edu}
9145952Ssaidi@eecs.umich.edu
9155952Ssaidi@eecs.umich.eduExceptionClass
9165952Ssaidi@eecs.umich.eduSecureMonitorTrap::ec(ThreadContext *tc) const
9175952Ssaidi@eecs.umich.edu{
9185952Ssaidi@eecs.umich.edu    return (overrideEc != EC_INVALID) ? overrideEc :
9195952Ssaidi@eecs.umich.edu        (from64 ? EC_SMC_64 : vals.ec);
9205952Ssaidi@eecs.umich.edu}
9215952Ssaidi@eecs.umich.edu
9225952Ssaidi@eecs.umich.edutemplate<class T>
9235952Ssaidi@eecs.umich.eduvoid
9245952Ssaidi@eecs.umich.eduAbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
9255952Ssaidi@eecs.umich.edu{
9265952Ssaidi@eecs.umich.edu    if (tranMethod == ArmFault::UnknownTran) {
9275952Ssaidi@eecs.umich.edu        tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran
9285952Ssaidi@eecs.umich.edu                                             : ArmFault::VmsaTran;
9295952Ssaidi@eecs.umich.edu
9305952Ssaidi@eecs.umich.edu        if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) {
9315952Ssaidi@eecs.umich.edu            // See ARM ARM B3-1416
9325952Ssaidi@eecs.umich.edu            bool override_LPAE = false;
9335952Ssaidi@eecs.umich.edu            TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S);
9345952Ssaidi@eecs.umich.edu            TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS);
9355952Ssaidi@eecs.umich.edu            if (ttbcr_s.eae) {
9365952Ssaidi@eecs.umich.edu                override_LPAE = true;
9375952Ssaidi@eecs.umich.edu            } else {
9385952Ssaidi@eecs.umich.edu                // Unimplemented code option, not seen in testing.  May need
9395952Ssaidi@eecs.umich.edu                // extension according to the manual exceprt above.
9405952Ssaidi@eecs.umich.edu                DPRINTF(Faults, "Warning: Incomplete translation method "
9415952Ssaidi@eecs.umich.edu                        "override detected.\n");
9425952Ssaidi@eecs.umich.edu            }
9435952Ssaidi@eecs.umich.edu            if (override_LPAE)
9445952Ssaidi@eecs.umich.edu                tranMethod = ArmFault::LpaeTran;
9455952Ssaidi@eecs.umich.edu        }
9465952Ssaidi@eecs.umich.edu    }
9475952Ssaidi@eecs.umich.edu
9485952Ssaidi@eecs.umich.edu    if (source == ArmFault::AsynchronousExternalAbort) {
9495952Ssaidi@eecs.umich.edu        tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
9505952Ssaidi@eecs.umich.edu    }
9515952Ssaidi@eecs.umich.edu    // Get effective fault source encoding
9525952Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
9535952Ssaidi@eecs.umich.edu    FSR  fsr  = getFsr(tc);
9545952Ssaidi@eecs.umich.edu
9555952Ssaidi@eecs.umich.edu    // source must be determined BEFORE invoking generic routines which will
9565952Ssaidi@eecs.umich.edu    // try to set hsr etc. and are based upon source!
9575952Ssaidi@eecs.umich.edu    ArmFaultVals<T>::invoke(tc, inst);
9585952Ssaidi@eecs.umich.edu
9595952Ssaidi@eecs.umich.edu    if (!this->to64) {  // AArch32
9605952Ssaidi@eecs.umich.edu        if (cpsr.mode == MODE_HYP) {
9615952Ssaidi@eecs.umich.edu            tc->setMiscReg(T::HFarIndex, faultAddr);
9625952Ssaidi@eecs.umich.edu        } else if (stage2) {
9635952Ssaidi@eecs.umich.edu            tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf);
9645952Ssaidi@eecs.umich.edu            tc->setMiscReg(T::HFarIndex,  OVAddr);
9655952Ssaidi@eecs.umich.edu        } else {
9665952Ssaidi@eecs.umich.edu            tc->setMiscReg(T::FsrIndex, fsr);
9675952Ssaidi@eecs.umich.edu            tc->setMiscReg(T::FarIndex, faultAddr);
9685952Ssaidi@eecs.umich.edu        }
9695952Ssaidi@eecs.umich.edu        DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\
9705952Ssaidi@eecs.umich.edu                "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod);
9715952Ssaidi@eecs.umich.edu    } else {  // AArch64
9725952Ssaidi@eecs.umich.edu        // Set the FAR register.  Nothing else to do if we are in AArch64 state
9735952Ssaidi@eecs.umich.edu        // because the syndrome register has already been set inside invoke64()
9745952Ssaidi@eecs.umich.edu        if (stage2) {
9755952Ssaidi@eecs.umich.edu            // stage 2 fault, set HPFAR_EL2 to the faulting IPA
9765952Ssaidi@eecs.umich.edu            // and FAR_EL2 to the Original VA
9775952Ssaidi@eecs.umich.edu            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr);
9785952Ssaidi@eecs.umich.edu            tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
9795952Ssaidi@eecs.umich.edu
9805952Ssaidi@eecs.umich.edu            DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
9815952Ssaidi@eecs.umich.edu                    OVAddr, faultAddr);
9825952Ssaidi@eecs.umich.edu        } else {
9835952Ssaidi@eecs.umich.edu            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
9845952Ssaidi@eecs.umich.edu        }
9855952Ssaidi@eecs.umich.edu    }
9865952Ssaidi@eecs.umich.edu}
9875952Ssaidi@eecs.umich.edu
9885952Ssaidi@eecs.umich.edutemplate<class T>
9895952Ssaidi@eecs.umich.eduFSR
9905952Ssaidi@eecs.umich.eduAbortFault<T>::getFsr(ThreadContext *tc)
9915952Ssaidi@eecs.umich.edu{
9925952Ssaidi@eecs.umich.edu    FSR fsr = 0;
9935952Ssaidi@eecs.umich.edu
9945952Ssaidi@eecs.umich.edu    if (((CPSR) tc->readMiscRegNoEffect(MISCREG_CPSR)).width) {
9955952Ssaidi@eecs.umich.edu        // AArch32
9965952Ssaidi@eecs.umich.edu        assert(tranMethod != ArmFault::UnknownTran);
9975952Ssaidi@eecs.umich.edu        if (tranMethod == ArmFault::LpaeTran) {
9985952Ssaidi@eecs.umich.edu            srcEncoded = ArmFault::longDescFaultSources[source];
9995952Ssaidi@eecs.umich.edu            fsr.status = srcEncoded;
10005952Ssaidi@eecs.umich.edu            fsr.lpae   = 1;
10015952Ssaidi@eecs.umich.edu        } else {
10025952Ssaidi@eecs.umich.edu            srcEncoded = ArmFault::shortDescFaultSources[source];
10035952Ssaidi@eecs.umich.edu            fsr.fsLow  = bits(srcEncoded, 3, 0);
10045952Ssaidi@eecs.umich.edu            fsr.fsHigh = bits(srcEncoded, 4);
10055952Ssaidi@eecs.umich.edu            fsr.domain = static_cast<uint8_t>(domain);
10065952Ssaidi@eecs.umich.edu        }
10075952Ssaidi@eecs.umich.edu        fsr.wnr = (write ? 1 : 0);
10085952Ssaidi@eecs.umich.edu        fsr.ext = 0;
10095952Ssaidi@eecs.umich.edu    } else {
10105952Ssaidi@eecs.umich.edu        // AArch64
10115952Ssaidi@eecs.umich.edu        srcEncoded = ArmFault::aarch64FaultSources[source];
10125952Ssaidi@eecs.umich.edu    }
10135952Ssaidi@eecs.umich.edu    if (srcEncoded == ArmFault::FaultSourceInvalid) {
10145952Ssaidi@eecs.umich.edu        panic("Invalid fault source\n");
10155952Ssaidi@eecs.umich.edu    }
10165952Ssaidi@eecs.umich.edu    return fsr;
10175952Ssaidi@eecs.umich.edu}
10185952Ssaidi@eecs.umich.edu
10195952Ssaidi@eecs.umich.edutemplate<class T>
10205952Ssaidi@eecs.umich.edubool
10215952Ssaidi@eecs.umich.eduAbortFault<T>::abortDisable(ThreadContext *tc)
10225952Ssaidi@eecs.umich.edu{
10235952Ssaidi@eecs.umich.edu    if (ArmSystem::haveSecurity(tc)) {
10245952Ssaidi@eecs.umich.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
10255952Ssaidi@eecs.umich.edu        return (!scr.ns || scr.aw);
10265952Ssaidi@eecs.umich.edu    }
10275952Ssaidi@eecs.umich.edu    return true;
10285952Ssaidi@eecs.umich.edu}
10295952Ssaidi@eecs.umich.edu
10305952Ssaidi@eecs.umich.edutemplate<class T>
10315952Ssaidi@eecs.umich.eduvoid
10325952Ssaidi@eecs.umich.eduAbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val)
10335952Ssaidi@eecs.umich.edu{
10345952Ssaidi@eecs.umich.edu    switch (id)
10355952Ssaidi@eecs.umich.edu    {
10365952Ssaidi@eecs.umich.edu      case ArmFault::S1PTW:
10375952Ssaidi@eecs.umich.edu        s1ptw = val;
10385952Ssaidi@eecs.umich.edu        break;
10395952Ssaidi@eecs.umich.edu      case ArmFault::OVA:
10405952Ssaidi@eecs.umich.edu        OVAddr = val;
10415952Ssaidi@eecs.umich.edu        break;
10425952Ssaidi@eecs.umich.edu
10435952Ssaidi@eecs.umich.edu      // Just ignore unknown ID's
10445952Ssaidi@eecs.umich.edu      default:
10455952Ssaidi@eecs.umich.edu        break;
10465952Ssaidi@eecs.umich.edu    }
10475952Ssaidi@eecs.umich.edu}
10485952Ssaidi@eecs.umich.edu
10495952Ssaidi@eecs.umich.edutemplate<class T>
10505952Ssaidi@eecs.umich.eduuint32_t
10515952Ssaidi@eecs.umich.eduAbortFault<T>::iss() const
10525952Ssaidi@eecs.umich.edu{
10535952Ssaidi@eecs.umich.edu    uint32_t val;
10545952Ssaidi@eecs.umich.edu
10555952Ssaidi@eecs.umich.edu    val  = srcEncoded & 0x3F;
10565952Ssaidi@eecs.umich.edu    val |= write << 6;
10575952Ssaidi@eecs.umich.edu    val |= s1ptw << 7;
10585952Ssaidi@eecs.umich.edu    return (val);
10595952Ssaidi@eecs.umich.edu}
10605952Ssaidi@eecs.umich.edu
10615952Ssaidi@eecs.umich.edutemplate<class T>
10625952Ssaidi@eecs.umich.edubool
10635952Ssaidi@eecs.umich.eduAbortFault<T>::isMMUFault() const
10645952Ssaidi@eecs.umich.edu{
10655952Ssaidi@eecs.umich.edu    // NOTE: Not relying on LL information being aligned to lowest bits here
106610905Sandreas.sandberg@arm.com    return
10675952Ssaidi@eecs.umich.edu         (source == ArmFault::AlignmentFault)     ||
10685952Ssaidi@eecs.umich.edu        ((source >= ArmFault::TranslationLL) &&
10695952Ssaidi@eecs.umich.edu         (source <  ArmFault::TranslationLL + 4)) ||
10705952Ssaidi@eecs.umich.edu        ((source >= ArmFault::AccessFlagLL) &&
10715952Ssaidi@eecs.umich.edu         (source <  ArmFault::AccessFlagLL + 4))  ||
10725952Ssaidi@eecs.umich.edu        ((source >= ArmFault::DomainLL) &&
10735952Ssaidi@eecs.umich.edu         (source <  ArmFault::DomainLL + 4))      ||
10745952Ssaidi@eecs.umich.edu        ((source >= ArmFault::PermissionLL) &&
10755952Ssaidi@eecs.umich.edu         (source <  ArmFault::PermissionLL + 4));
10765952Ssaidi@eecs.umich.edu}
10775952Ssaidi@eecs.umich.edu
10785952Ssaidi@eecs.umich.eduExceptionClass
10795952Ssaidi@eecs.umich.eduPrefetchAbort::ec(ThreadContext *tc) const
10805952Ssaidi@eecs.umich.edu{
10815952Ssaidi@eecs.umich.edu    if (to64) {
10825952Ssaidi@eecs.umich.edu        // AArch64
10835952Ssaidi@eecs.umich.edu        if (toEL == fromEL)
10845952Ssaidi@eecs.umich.edu            return EC_PREFETCH_ABORT_CURR_EL;
10855952Ssaidi@eecs.umich.edu        else
10865952Ssaidi@eecs.umich.edu            return EC_PREFETCH_ABORT_LOWER_EL;
10875952Ssaidi@eecs.umich.edu    } else {
10885952Ssaidi@eecs.umich.edu        // AArch32
10895952Ssaidi@eecs.umich.edu        // Abort faults have different EC codes depending on whether
10905952Ssaidi@eecs.umich.edu        // the fault originated within HYP mode, or not. So override
10915952Ssaidi@eecs.umich.edu        // the method and add the extra adjustment of the EC value.
10925952Ssaidi@eecs.umich.edu
10935952Ssaidi@eecs.umich.edu        ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec;
10945952Ssaidi@eecs.umich.edu
10955952Ssaidi@eecs.umich.edu        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
10965952Ssaidi@eecs.umich.edu        if (spsr.mode == MODE_HYP) {
10975952Ssaidi@eecs.umich.edu            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
10985952Ssaidi@eecs.umich.edu        }
10995952Ssaidi@eecs.umich.edu        return ec;
11005952Ssaidi@eecs.umich.edu    }
11015952Ssaidi@eecs.umich.edu}
11025952Ssaidi@eecs.umich.edu
11035952Ssaidi@eecs.umich.edubool
11045952Ssaidi@eecs.umich.eduPrefetchAbort::routeToMonitor(ThreadContext *tc) const
11055952Ssaidi@eecs.umich.edu{
11065952Ssaidi@eecs.umich.edu    SCR scr = 0;
11075952Ssaidi@eecs.umich.edu    if (from64)
11085952Ssaidi@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
11095952Ssaidi@eecs.umich.edu    else
11105952Ssaidi@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
11115952Ssaidi@eecs.umich.edu
11125952Ssaidi@eecs.umich.edu    return scr.ea && !isMMUFault();
11135952Ssaidi@eecs.umich.edu}
11145952Ssaidi@eecs.umich.edu
11155952Ssaidi@eecs.umich.edubool
11165952Ssaidi@eecs.umich.eduPrefetchAbort::routeToHyp(ThreadContext *tc) const
11175952Ssaidi@eecs.umich.edu{
11185952Ssaidi@eecs.umich.edu    bool toHyp;
11195952Ssaidi@eecs.umich.edu
11205952Ssaidi@eecs.umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
11215952Ssaidi@eecs.umich.edu    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
11225952Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
11235952Ssaidi@eecs.umich.edu    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
11245952Ssaidi@eecs.umich.edu
11255952Ssaidi@eecs.umich.edu    // if in Hyp mode then stay in Hyp mode
11265952Ssaidi@eecs.umich.edu    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
11275952Ssaidi@eecs.umich.edu    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
11285952Ssaidi@eecs.umich.edu    toHyp |= (stage2 ||
11295952Ssaidi@eecs.umich.edu                ( (source ==               DebugEvent) && hdcr.tde && (cpsr.mode !=  MODE_HYP)) ||
11305952Ssaidi@eecs.umich.edu                ( (source == SynchronousExternalAbort) && hcr.tge  && (cpsr.mode == MODE_USER))
11315952Ssaidi@eecs.umich.edu             ) && !inSecureState(tc);
11325952Ssaidi@eecs.umich.edu    return toHyp;
11335952Ssaidi@eecs.umich.edu}
11345952Ssaidi@eecs.umich.edu
11355952Ssaidi@eecs.umich.eduExceptionClass
11365952Ssaidi@eecs.umich.eduDataAbort::ec(ThreadContext *tc) const
11375952Ssaidi@eecs.umich.edu{
11385952Ssaidi@eecs.umich.edu    if (to64) {
11395952Ssaidi@eecs.umich.edu        // AArch64
11405952Ssaidi@eecs.umich.edu        if (source == ArmFault::AsynchronousExternalAbort) {
11415952Ssaidi@eecs.umich.edu            panic("Asynchronous External Abort should be handled with "
11425952Ssaidi@eecs.umich.edu                    "SystemErrors (SErrors)!");
11435952Ssaidi@eecs.umich.edu        }
11445952Ssaidi@eecs.umich.edu        if (toEL == fromEL)
11455952Ssaidi@eecs.umich.edu            return EC_DATA_ABORT_CURR_EL;
11465952Ssaidi@eecs.umich.edu        else
11475952Ssaidi@eecs.umich.edu            return EC_DATA_ABORT_LOWER_EL;
11485952Ssaidi@eecs.umich.edu    } else {
11495952Ssaidi@eecs.umich.edu        // AArch32
11505952Ssaidi@eecs.umich.edu        // Abort faults have different EC codes depending on whether
11515952Ssaidi@eecs.umich.edu        // the fault originated within HYP mode, or not. So override
11525952Ssaidi@eecs.umich.edu        // the method and add the extra adjustment of the EC value.
11535952Ssaidi@eecs.umich.edu
11545952Ssaidi@eecs.umich.edu        ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec;
11555952Ssaidi@eecs.umich.edu
11565952Ssaidi@eecs.umich.edu        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
11575952Ssaidi@eecs.umich.edu        if (spsr.mode == MODE_HYP) {
11585952Ssaidi@eecs.umich.edu            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
11595952Ssaidi@eecs.umich.edu        }
11605952Ssaidi@eecs.umich.edu        return ec;
11615952Ssaidi@eecs.umich.edu    }
11625952Ssaidi@eecs.umich.edu}
11635952Ssaidi@eecs.umich.edu
11645952Ssaidi@eecs.umich.edubool
11655952Ssaidi@eecs.umich.eduDataAbort::routeToMonitor(ThreadContext *tc) const
11665952Ssaidi@eecs.umich.edu{
11675952Ssaidi@eecs.umich.edu    SCR scr = 0;
11685952Ssaidi@eecs.umich.edu    if (from64)
11695952Ssaidi@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
11705952Ssaidi@eecs.umich.edu    else
11715952Ssaidi@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
11725952Ssaidi@eecs.umich.edu
11735952Ssaidi@eecs.umich.edu    return scr.ea && !isMMUFault();
11745952Ssaidi@eecs.umich.edu}
11755952Ssaidi@eecs.umich.edu
11765952Ssaidi@eecs.umich.edubool
11775952Ssaidi@eecs.umich.eduDataAbort::routeToHyp(ThreadContext *tc) const
11785952Ssaidi@eecs.umich.edu{
11795952Ssaidi@eecs.umich.edu    bool toHyp;
11805952Ssaidi@eecs.umich.edu
11815952Ssaidi@eecs.umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
11825952Ssaidi@eecs.umich.edu    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
11835952Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
11845952Ssaidi@eecs.umich.edu    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
11855952Ssaidi@eecs.umich.edu
11865952Ssaidi@eecs.umich.edu    // if in Hyp mode then stay in Hyp mode
11875952Ssaidi@eecs.umich.edu    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
11885952Ssaidi@eecs.umich.edu    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
11895952Ssaidi@eecs.umich.edu    toHyp |= (stage2 ||
11905952Ssaidi@eecs.umich.edu                ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) ||
11915952Ssaidi@eecs.umich.edu                                               ((source == DebugEvent) && hdcr.tde) )
11925952Ssaidi@eecs.umich.edu                ) ||
11935952Ssaidi@eecs.umich.edu                ( (cpsr.mode == MODE_USER) && hcr.tge &&
11945952Ssaidi@eecs.umich.edu                  ((source == AlignmentFault)            ||
11955952Ssaidi@eecs.umich.edu                   (source == SynchronousExternalAbort))
11965952Ssaidi@eecs.umich.edu                )
11975952Ssaidi@eecs.umich.edu             ) && !inSecureState(tc);
11985952Ssaidi@eecs.umich.edu    return toHyp;
11995952Ssaidi@eecs.umich.edu}
12005952Ssaidi@eecs.umich.edu
12015952Ssaidi@eecs.umich.eduuint32_t
12025952Ssaidi@eecs.umich.eduDataAbort::iss() const
12035952Ssaidi@eecs.umich.edu{
12045952Ssaidi@eecs.umich.edu    uint32_t val;
12055952Ssaidi@eecs.umich.edu
12065952Ssaidi@eecs.umich.edu    // Add on the data abort specific fields to the generic abort ISS value
12075952Ssaidi@eecs.umich.edu    val  = AbortFault<DataAbort>::iss();
12085952Ssaidi@eecs.umich.edu    // ISS is valid if not caused by a stage 1 page table walk, and when taken
12095952Ssaidi@eecs.umich.edu    // to AArch64 only when directed to EL2
12105952Ssaidi@eecs.umich.edu    if (!s1ptw && (!to64 || toEL == EL2)) {
12115952Ssaidi@eecs.umich.edu        val |= isv << 24;
121210905Sandreas.sandberg@arm.com        if (isv) {
121310905Sandreas.sandberg@arm.com            val |= sas << 22;
12145952Ssaidi@eecs.umich.edu            val |= sse << 21;
12155952Ssaidi@eecs.umich.edu            val |= srt << 16;
12165952Ssaidi@eecs.umich.edu            // AArch64 only. These assignments are safe on AArch32 as well
12175952Ssaidi@eecs.umich.edu            // because these vars are initialized to false
12185952Ssaidi@eecs.umich.edu            val |= sf << 15;
12195952Ssaidi@eecs.umich.edu            val |= ar << 14;
122010905Sandreas.sandberg@arm.com        }
12215952Ssaidi@eecs.umich.edu    }
12225952Ssaidi@eecs.umich.edu    return (val);
12235952Ssaidi@eecs.umich.edu}
122410905Sandreas.sandberg@arm.com
122510905Sandreas.sandberg@arm.comvoid
12265952Ssaidi@eecs.umich.eduDataAbort::annotate(AnnotationIDs id, uint64_t val)
12275952Ssaidi@eecs.umich.edu{
12285952Ssaidi@eecs.umich.edu    AbortFault<DataAbort>::annotate(id, val);
122910905Sandreas.sandberg@arm.com    switch (id)
123010905Sandreas.sandberg@arm.com    {
12315952Ssaidi@eecs.umich.edu      case SAS:
12325952Ssaidi@eecs.umich.edu        isv = true;
12335952Ssaidi@eecs.umich.edu        sas = val;
12345952Ssaidi@eecs.umich.edu        break;
12355952Ssaidi@eecs.umich.edu      case SSE:
12365952Ssaidi@eecs.umich.edu        isv = true;
123710905Sandreas.sandberg@arm.com        sse = val;
123810905Sandreas.sandberg@arm.com        break;
12395952Ssaidi@eecs.umich.edu      case SRT:
12405952Ssaidi@eecs.umich.edu        isv = true;
12415952Ssaidi@eecs.umich.edu        srt = val;
12425952Ssaidi@eecs.umich.edu        break;
12435952Ssaidi@eecs.umich.edu      case SF:
12445952Ssaidi@eecs.umich.edu        isv = true;
12455952Ssaidi@eecs.umich.edu        sf  = val;
124610905Sandreas.sandberg@arm.com        break;
124710905Sandreas.sandberg@arm.com      case AR:
12485952Ssaidi@eecs.umich.edu        isv = true;
12495952Ssaidi@eecs.umich.edu        ar  = val;
12505952Ssaidi@eecs.umich.edu        break;
12515952Ssaidi@eecs.umich.edu      // Just ignore unknown ID's
12525952Ssaidi@eecs.umich.edu      default:
12535952Ssaidi@eecs.umich.edu        break;
12545952Ssaidi@eecs.umich.edu    }
12555952Ssaidi@eecs.umich.edu}
12565952Ssaidi@eecs.umich.edu
125710905Sandreas.sandberg@arm.comvoid
125810905Sandreas.sandberg@arm.comVirtualDataAbort::invoke(ThreadContext *tc, const StaticInstPtr &inst)
125910905Sandreas.sandberg@arm.com{
12605952Ssaidi@eecs.umich.edu    AbortFault<VirtualDataAbort>::invoke(tc, inst);
12615952Ssaidi@eecs.umich.edu    HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
12625952Ssaidi@eecs.umich.edu    hcr.va = 0;
12635952Ssaidi@eecs.umich.edu    tc->setMiscRegNoEffect(MISCREG_HCR, hcr);
12645952Ssaidi@eecs.umich.edu}
12655952Ssaidi@eecs.umich.edu
12665952Ssaidi@eecs.umich.edubool
12675952Ssaidi@eecs.umich.eduInterrupt::routeToMonitor(ThreadContext *tc) const
126810905Sandreas.sandberg@arm.com{
12695952Ssaidi@eecs.umich.edu    assert(ArmSystem::haveSecurity(tc));
127010905Sandreas.sandberg@arm.com    SCR scr = 0;
127110905Sandreas.sandberg@arm.com    if (from64)
127210905Sandreas.sandberg@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
12735952Ssaidi@eecs.umich.edu    else
12745952Ssaidi@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
12755952Ssaidi@eecs.umich.edu    return scr.irq;
12765952Ssaidi@eecs.umich.edu}
12775952Ssaidi@eecs.umich.edu
12785952Ssaidi@eecs.umich.edubool
12795952Ssaidi@eecs.umich.eduInterrupt::routeToHyp(ThreadContext *tc) const
12805952Ssaidi@eecs.umich.edu{
12815952Ssaidi@eecs.umich.edu    bool toHyp;
12825952Ssaidi@eecs.umich.edu
12835952Ssaidi@eecs.umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
12845952Ssaidi@eecs.umich.edu    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
12855952Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
12865952Ssaidi@eecs.umich.edu    // Determine whether IRQs are routed to Hyp mode.
12875952Ssaidi@eecs.umich.edu    toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) ||
128810905Sandreas.sandberg@arm.com            (cpsr.mode == MODE_HYP);
12895952Ssaidi@eecs.umich.edu    return toHyp;
12905952Ssaidi@eecs.umich.edu}
129110905Sandreas.sandberg@arm.com
129210905Sandreas.sandberg@arm.combool
129310377Sandreas.hansson@arm.comInterrupt::abortDisable(ThreadContext *tc)
12945952Ssaidi@eecs.umich.edu{
12955952Ssaidi@eecs.umich.edu    if (ArmSystem::haveSecurity(tc)) {
12965952Ssaidi@eecs.umich.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
12975952Ssaidi@eecs.umich.edu        return (!scr.ns || scr.aw);
129810905Sandreas.sandberg@arm.com    }
12995952Ssaidi@eecs.umich.edu    return true;
13005952Ssaidi@eecs.umich.edu}
13015952Ssaidi@eecs.umich.edu
13025952Ssaidi@eecs.umich.eduVirtualInterrupt::VirtualInterrupt()
130310905Sandreas.sandberg@arm.com{}
130410905Sandreas.sandberg@arm.com
130510905Sandreas.sandberg@arm.combool
13065952Ssaidi@eecs.umich.eduFastInterrupt::routeToMonitor(ThreadContext *tc) const
13075952Ssaidi@eecs.umich.edu{
130810905Sandreas.sandberg@arm.com    assert(ArmSystem::haveSecurity(tc));
13095952Ssaidi@eecs.umich.edu    SCR scr = 0;
13105952Ssaidi@eecs.umich.edu    if (from64)
13115952Ssaidi@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
13125952Ssaidi@eecs.umich.edu    else
13135952Ssaidi@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
13145952Ssaidi@eecs.umich.edu    return scr.fiq;
13155952Ssaidi@eecs.umich.edu}
131610905Sandreas.sandberg@arm.com
13175952Ssaidi@eecs.umich.edubool
131810905Sandreas.sandberg@arm.comFastInterrupt::routeToHyp(ThreadContext *tc) const
131910905Sandreas.sandberg@arm.com{
13205952Ssaidi@eecs.umich.edu    bool toHyp;
13215952Ssaidi@eecs.umich.edu
13225952Ssaidi@eecs.umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
13235952Ssaidi@eecs.umich.edu    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
13245952Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
132510905Sandreas.sandberg@arm.com    // Determine whether IRQs are routed to Hyp mode.
13265952Ssaidi@eecs.umich.edu    toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) ||
13275952Ssaidi@eecs.umich.edu            (cpsr.mode == MODE_HYP);
13285952Ssaidi@eecs.umich.edu    return toHyp;
13295952Ssaidi@eecs.umich.edu}
133010905Sandreas.sandberg@arm.com
133110905Sandreas.sandberg@arm.combool
133210905Sandreas.sandberg@arm.comFastInterrupt::abortDisable(ThreadContext *tc)
13335952Ssaidi@eecs.umich.edu{
13345952Ssaidi@eecs.umich.edu    if (ArmSystem::haveSecurity(tc)) {
13355952Ssaidi@eecs.umich.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
13365952Ssaidi@eecs.umich.edu        return (!scr.ns || scr.aw);
13375952Ssaidi@eecs.umich.edu    }
13385952Ssaidi@eecs.umich.edu    return true;
13395952Ssaidi@eecs.umich.edu}
134010905Sandreas.sandberg@arm.com
13415952Ssaidi@eecs.umich.edubool
134210905Sandreas.sandberg@arm.comFastInterrupt::fiqDisable(ThreadContext *tc)
134310905Sandreas.sandberg@arm.com{
13445952Ssaidi@eecs.umich.edu    if (ArmSystem::haveVirtualization(tc)) {
13455952Ssaidi@eecs.umich.edu        return true;
13465952Ssaidi@eecs.umich.edu    } else if (ArmSystem::haveSecurity(tc)) {
13475952Ssaidi@eecs.umich.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
13485952Ssaidi@eecs.umich.edu        return (!scr.ns || scr.fw);
13495952Ssaidi@eecs.umich.edu    }
13505952Ssaidi@eecs.umich.edu    return true;
135110905Sandreas.sandberg@arm.com}
135210905Sandreas.sandberg@arm.com
135310905Sandreas.sandberg@arm.comVirtualFastInterrupt::VirtualFastInterrupt()
13545952Ssaidi@eecs.umich.edu{}
13555952Ssaidi@eecs.umich.edu
13565952Ssaidi@eecs.umich.eduvoid
13575952Ssaidi@eecs.umich.eduPCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
13585952Ssaidi@eecs.umich.edu{
135910905Sandreas.sandberg@arm.com    ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
136010905Sandreas.sandberg@arm.com    assert(from64);
136110905Sandreas.sandberg@arm.com    // Set the FAR
13625952Ssaidi@eecs.umich.edu    tc->setMiscReg(getFaultAddrReg64(), faultPC);
13635952Ssaidi@eecs.umich.edu}
13645952Ssaidi@eecs.umich.edu
13655952Ssaidi@eecs.umich.eduSPAlignmentFault::SPAlignmentFault()
13665952Ssaidi@eecs.umich.edu{}
13675952Ssaidi@eecs.umich.edu
13685952Ssaidi@eecs.umich.eduSystemError::SystemError()
13695952Ssaidi@eecs.umich.edu{}
13705952Ssaidi@eecs.umich.edu
137110470Sandreas.hansson@arm.comvoid
137210905Sandreas.sandberg@arm.comSystemError::invoke(ThreadContext *tc, const StaticInstPtr &inst)
13735952Ssaidi@eecs.umich.edu{
13745952Ssaidi@eecs.umich.edu    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
13755952Ssaidi@eecs.umich.edu    ArmFault::invoke(tc, inst);
13765952Ssaidi@eecs.umich.edu}
13775952Ssaidi@eecs.umich.edu
13785952Ssaidi@eecs.umich.edubool
13795952Ssaidi@eecs.umich.eduSystemError::routeToMonitor(ThreadContext *tc) const
138010905Sandreas.sandberg@arm.com{
13815952Ssaidi@eecs.umich.edu    assert(ArmSystem::haveSecurity(tc));
13825952Ssaidi@eecs.umich.edu    assert(from64);
13835952Ssaidi@eecs.umich.edu    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
13845952Ssaidi@eecs.umich.edu    return scr.ea;
13855952Ssaidi@eecs.umich.edu}
13865952Ssaidi@eecs.umich.edu
13875952Ssaidi@eecs.umich.edubool
13885952Ssaidi@eecs.umich.eduSystemError::routeToHyp(ThreadContext *tc) const
13895952Ssaidi@eecs.umich.edu{
13905952Ssaidi@eecs.umich.edu    bool toHyp;
13915952Ssaidi@eecs.umich.edu    assert(from64);
139210905Sandreas.sandberg@arm.com
13935952Ssaidi@eecs.umich.edu    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
13945952Ssaidi@eecs.umich.edu    HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
13955952Ssaidi@eecs.umich.edu
13965952Ssaidi@eecs.umich.edu    toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) ||
13975952Ssaidi@eecs.umich.edu            (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc));
13985952Ssaidi@eecs.umich.edu    return toHyp;
13995952Ssaidi@eecs.umich.edu}
14005952Ssaidi@eecs.umich.edu
14015952Ssaidi@eecs.umich.edu
14025952Ssaidi@eecs.umich.eduSoftwareBreakpoint::SoftwareBreakpoint(ExtMachInst _mach_inst, uint32_t _iss)
14035952Ssaidi@eecs.umich.edu    : ArmFaultVals<SoftwareBreakpoint>(_mach_inst, _iss)
14045952Ssaidi@eecs.umich.edu{}
14055952Ssaidi@eecs.umich.edu
14065952Ssaidi@eecs.umich.edubool
14075952Ssaidi@eecs.umich.eduSoftwareBreakpoint::routeToHyp(ThreadContext *tc) const
14085952Ssaidi@eecs.umich.edu{
14095952Ssaidi@eecs.umich.edu    assert(from64);
14105952Ssaidi@eecs.umich.edu
1411    const bool have_el2 = ArmSystem::haveVirtualization(tc);
1412
1413    const HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
1414    const HDCR mdcr  = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
1415
1416    return have_el2 && !inSecureState(tc) && fromEL <= EL1 &&
1417        (hcr.tge || mdcr.tde);
1418}
1419
1420void
1421ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
1422    DPRINTF(Faults, "Invoking ArmSev Fault\n");
1423    if (!FullSystem)
1424        return;
1425
1426    // Set sev_mailbox to 1, clear the pending interrupt from remote
1427    // SEV execution and let pipeline continue as pcState is still
1428    // valid.
1429    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
1430    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0);
1431}
1432
1433// Instantiate all the templates to make the linker happy
1434template class ArmFaultVals<Reset>;
1435template class ArmFaultVals<UndefinedInstruction>;
1436template class ArmFaultVals<SupervisorCall>;
1437template class ArmFaultVals<SecureMonitorCall>;
1438template class ArmFaultVals<HypervisorCall>;
1439template class ArmFaultVals<PrefetchAbort>;
1440template class ArmFaultVals<DataAbort>;
1441template class ArmFaultVals<VirtualDataAbort>;
1442template class ArmFaultVals<HypervisorTrap>;
1443template class ArmFaultVals<Interrupt>;
1444template class ArmFaultVals<VirtualInterrupt>;
1445template class ArmFaultVals<FastInterrupt>;
1446template class ArmFaultVals<VirtualFastInterrupt>;
1447template class ArmFaultVals<SupervisorTrap>;
1448template class ArmFaultVals<SecureMonitorTrap>;
1449template class ArmFaultVals<PCAlignmentFault>;
1450template class ArmFaultVals<SPAlignmentFault>;
1451template class ArmFaultVals<SystemError>;
1452template class ArmFaultVals<SoftwareBreakpoint>;
1453template class ArmFaultVals<ArmSev>;
1454template class AbortFault<PrefetchAbort>;
1455template class AbortFault<DataAbort>;
1456template class AbortFault<VirtualDataAbort>;
1457
1458
1459IllegalInstSetStateFault::IllegalInstSetStateFault()
1460{}
1461
1462
1463} // namespace ArmISA
1464