faults.cc revision 11877
17405SAli.Saidi@ARM.com/*
212667Schuan.zhu@arm.com * Copyright (c) 2010, 2012-2014, 2016 ARM Limited
37405SAli.Saidi@ARM.com * All rights reserved
47405SAli.Saidi@ARM.com *
57405SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall
67405SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual
77405SAli.Saidi@ARM.com * property including but not limited to intellectual property relating
87405SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software
97405SAli.Saidi@ARM.com * licensed hereunder.  You may use the software subject to the license
107405SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated
117405SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software,
127405SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form.
137405SAli.Saidi@ARM.com *
147405SAli.Saidi@ARM.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
157405SAli.Saidi@ARM.com * Copyright (c) 2007-2008 The Florida State University
167405SAli.Saidi@ARM.com * All rights reserved.
177405SAli.Saidi@ARM.com *
187405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
197405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
207405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
217405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
227405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
237405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
247405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
257405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
267405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
277405SAli.Saidi@ARM.com * this software without specific prior written permission.
287405SAli.Saidi@ARM.com *
297405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
307405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
317405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
327405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
337405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
347405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
357405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
367405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
377405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
387405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
397405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
407405SAli.Saidi@ARM.com *
417405SAli.Saidi@ARM.com * Authors: Ali Saidi
4210461SAndreas.Sandberg@ARM.com *          Gabe Black
439050Schander.sudanthi@arm.com *          Giacomo Gabrielli
4412406Sgabeblack@google.com *          Thomas Grocutt
4512605Sgiacomo.travaglini@arm.com */
4611793Sbrandon.potter@amd.com
478887Sgeoffrey.blake@arm.com#include "arch/arm/faults.hh"
488232Snate@binkert.org
498232Snate@binkert.org#include "arch/arm/insts/static_inst.hh"
5010844Sandreas.sandberg@arm.com#include "arch/arm/system.hh"
5113531Sjairo.balart@metempsy.com#include "arch/arm/utility.hh"
5213531Sjairo.balart@metempsy.com#include "base/compiler.hh"
539384SAndreas.Sandberg@arm.com#include "base/trace.hh"
547678Sgblack@eecs.umich.edu#include "cpu/base.hh"
558059SAli.Saidi@ARM.com#include "cpu/thread_context.hh"
568284SAli.Saidi@ARM.com#include "debug/Faults.hh"
577405SAli.Saidi@ARM.com#include "sim/full_system.hh"
587405SAli.Saidi@ARM.com
597405SAli.Saidi@ARM.comnamespace ArmISA
607405SAli.Saidi@ARM.com{
619384SAndreas.Sandberg@arm.com
6210461SAndreas.Sandberg@ARM.comuint8_t ArmFault::shortDescFaultSources[] = {
6310461SAndreas.Sandberg@ARM.com    0x01,  // AlignmentFault
6411165SRekai.GonzalezAlberquilla@arm.com    0x04,  // InstructionCacheMaintenance
6512109SRekai.GonzalezAlberquilla@arm.com    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
6612714Sgiacomo.travaglini@arm.com    0x0c,  // SynchExtAbtOnTranslTableWalkL1
6712714Sgiacomo.travaglini@arm.com    0x0e,  // SynchExtAbtOnTranslTableWalkL2
689384SAndreas.Sandberg@arm.com    0xff,  // SynchExtAbtOnTranslTableWalkL3 (INVALID)
6911770SCurtis.Dunham@arm.com    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
7010037SARM gem5 Developers    0x1c,  // SynchPtyErrOnTranslTableWalkL1
7110461SAndreas.Sandberg@ARM.com    0x1e,  // SynchPtyErrOnTranslTableWalkL2
7210461SAndreas.Sandberg@ARM.com    0xff,  // SynchPtyErrOnTranslTableWalkL3 (INVALID)
7310461SAndreas.Sandberg@ARM.com    0xff,  // TranslationL0 (INVALID)
7410461SAndreas.Sandberg@ARM.com    0x05,  // TranslationL1
7510461SAndreas.Sandberg@ARM.com    0x07,  // TranslationL2
7610461SAndreas.Sandberg@ARM.com    0xff,  // TranslationL3 (INVALID)
7710609Sandreas.sandberg@arm.com    0xff,  // AccessFlagL0 (INVALID)
7810609Sandreas.sandberg@arm.com    0x03,  // AccessFlagL1
7910609Sandreas.sandberg@arm.com    0x06,  // AccessFlagL2
8010037SARM gem5 Developers    0xff,  // AccessFlagL3 (INVALID)
8110037SARM gem5 Developers    0xff,  // DomainL0 (INVALID)
8210037SARM gem5 Developers    0x09,  // DomainL1
8310037SARM gem5 Developers    0x0b,  // DomainL2
8411771SCurtis.Dunham@arm.com    0xff,  // DomainL3 (INVALID)
8510037SARM gem5 Developers    0xff,  // PermissionL0 (INVALID)
8610037SARM gem5 Developers    0x0d,  // PermissionL1
8713173Sgiacomo.travaglini@arm.com    0x0f,  // PermissionL2
8810037SARM gem5 Developers    0xff,  // PermissionL3 (INVALID)
8910037SARM gem5 Developers    0x02,  // DebugEvent
9013114Sgiacomo.travaglini@arm.com    0x08,  // SynchronousExternalAbort
9110037SARM gem5 Developers    0x10,  // TLBConflictAbort
9211771SCurtis.Dunham@arm.com    0x19,  // SynchPtyErrOnMemoryAccess
9310037SARM gem5 Developers    0x16,  // AsynchronousExternalAbort
9413499Sgiacomo.travaglini@arm.com    0x18,  // AsynchPtyErrOnMemoryAccess
9510037SARM gem5 Developers    0xff,  // AddressSizeL0 (INVALID)
9613114Sgiacomo.travaglini@arm.com    0xff,  // AddressSizeL1 (INVALID)
9710037SARM gem5 Developers    0xff,  // AddressSizeL2 (INVALID)
9810037SARM gem5 Developers    0xff,  // AddressSizeL3 (INVALID)
9913531Sjairo.balart@metempsy.com    0x40,  // PrefetchTLBMiss
10013531Sjairo.balart@metempsy.com    0x80   // PrefetchUncacheable
10113531Sjairo.balart@metempsy.com};
10213531Sjairo.balart@metempsy.com
10313531Sjairo.balart@metempsy.comstatic_assert(sizeof(ArmFault::shortDescFaultSources) ==
10413531Sjairo.balart@metempsy.com              ArmFault::NumFaultSources,
10513531Sjairo.balart@metempsy.com              "Invalid size of ArmFault::shortDescFaultSources[]");
10612477SCurtis.Dunham@arm.com
10710037SARM gem5 Developersuint8_t ArmFault::longDescFaultSources[] = {
10810037SARM gem5 Developers    0x21,  // AlignmentFault
1099384SAndreas.Sandberg@arm.com    0xff,  // InstructionCacheMaintenance (INVALID)
1109384SAndreas.Sandberg@arm.com    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
1119384SAndreas.Sandberg@arm.com    0x15,  // SynchExtAbtOnTranslTableWalkL1
11212479SCurtis.Dunham@arm.com    0x16,  // SynchExtAbtOnTranslTableWalkL2
11312479SCurtis.Dunham@arm.com    0x17,  // SynchExtAbtOnTranslTableWalkL3
1149384SAndreas.Sandberg@arm.com    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
1159384SAndreas.Sandberg@arm.com    0x1d,  // SynchPtyErrOnTranslTableWalkL1
1169384SAndreas.Sandberg@arm.com    0x1e,  // SynchPtyErrOnTranslTableWalkL2
1179384SAndreas.Sandberg@arm.com    0x1f,  // SynchPtyErrOnTranslTableWalkL3
1189384SAndreas.Sandberg@arm.com    0xff,  // TranslationL0 (INVALID)
1199384SAndreas.Sandberg@arm.com    0x05,  // TranslationL1
1207427Sgblack@eecs.umich.edu    0x06,  // TranslationL2
1217427Sgblack@eecs.umich.edu    0x07,  // TranslationL3
1227427Sgblack@eecs.umich.edu    0xff,  // AccessFlagL0 (INVALID)
1239385SAndreas.Sandberg@arm.com    0x09,  // AccessFlagL1
1249385SAndreas.Sandberg@arm.com    0x0a,  // AccessFlagL2
1257427Sgblack@eecs.umich.edu    0x0b,  // AccessFlagL3
1267427Sgblack@eecs.umich.edu    0xff,  // DomainL0 (INVALID)
12710037SARM gem5 Developers    0x3d,  // DomainL1
12813114Sgiacomo.travaglini@arm.com    0x3e,  // DomainL2
12910037SARM gem5 Developers    0xff,  // DomainL3 (RESERVED)
13013114Sgiacomo.travaglini@arm.com    0xff,  // PermissionL0 (INVALID)
13113114Sgiacomo.travaglini@arm.com    0x0d,  // PermissionL1
13213114Sgiacomo.travaglini@arm.com    0x0e,  // PermissionL2
13313114Sgiacomo.travaglini@arm.com    0x0f,  // PermissionL3
13413114Sgiacomo.travaglini@arm.com    0x22,  // DebugEvent
13512690Sgiacomo.travaglini@arm.com    0x10,  // SynchronousExternalAbort
13610037SARM gem5 Developers    0x30,  // TLBConflictAbort
1377427Sgblack@eecs.umich.edu    0x18,  // SynchPtyErrOnMemoryAccess
1387427Sgblack@eecs.umich.edu    0x11,  // AsynchronousExternalAbort
13910037SARM gem5 Developers    0x19,  // AsynchPtyErrOnMemoryAccess
1407427Sgblack@eecs.umich.edu    0xff,  // AddressSizeL0 (INVALID)
1417427Sgblack@eecs.umich.edu    0xff,  // AddressSizeL1 (INVALID)
1427427Sgblack@eecs.umich.edu    0xff,  // AddressSizeL2 (INVALID)
1437427Sgblack@eecs.umich.edu    0xff,  // AddressSizeL3 (INVALID)
1447427Sgblack@eecs.umich.edu    0x40,  // PrefetchTLBMiss
1457427Sgblack@eecs.umich.edu    0x80   // PrefetchUncacheable
1467427Sgblack@eecs.umich.edu};
1477427Sgblack@eecs.umich.edu
1487427Sgblack@eecs.umich.edustatic_assert(sizeof(ArmFault::longDescFaultSources) ==
1497427Sgblack@eecs.umich.edu              ArmFault::NumFaultSources,
1507427Sgblack@eecs.umich.edu              "Invalid size of ArmFault::longDescFaultSources[]");
1517427Sgblack@eecs.umich.edu
1527427Sgblack@eecs.umich.eduuint8_t ArmFault::aarch64FaultSources[] = {
1537427Sgblack@eecs.umich.edu    0x21,  // AlignmentFault
1547427Sgblack@eecs.umich.edu    0xff,  // InstructionCacheMaintenance (INVALID)
1557427Sgblack@eecs.umich.edu    0x14,  // SynchExtAbtOnTranslTableWalkL0
1567427Sgblack@eecs.umich.edu    0x15,  // SynchExtAbtOnTranslTableWalkL1
1577427Sgblack@eecs.umich.edu    0x16,  // SynchExtAbtOnTranslTableWalkL2
1587427Sgblack@eecs.umich.edu    0x17,  // SynchExtAbtOnTranslTableWalkL3
1597427Sgblack@eecs.umich.edu    0x1c,  // SynchPtyErrOnTranslTableWalkL0
1607427Sgblack@eecs.umich.edu    0x1d,  // SynchPtyErrOnTranslTableWalkL1
1617427Sgblack@eecs.umich.edu    0x1e,  // SynchPtyErrOnTranslTableWalkL2
1627427Sgblack@eecs.umich.edu    0x1f,  // SynchPtyErrOnTranslTableWalkL3
1637436Sdam.sunwoo@arm.com    0x04,  // TranslationL0
1647436Sdam.sunwoo@arm.com    0x05,  // TranslationL1
16510037SARM gem5 Developers    0x06,  // TranslationL2
16610037SARM gem5 Developers    0x07,  // TranslationL3
1677436Sdam.sunwoo@arm.com    0x08,  // AccessFlagL0
1687436Sdam.sunwoo@arm.com    0x09,  // AccessFlagL1
1697436Sdam.sunwoo@arm.com    0x0a,  // AccessFlagL2
1707436Sdam.sunwoo@arm.com    0x0b,  // AccessFlagL3
1717436Sdam.sunwoo@arm.com    // @todo: Section & Page Domain Fault in AArch64?
1727436Sdam.sunwoo@arm.com    0xff,  // DomainL0 (INVALID)
1737436Sdam.sunwoo@arm.com    0xff,  // DomainL1 (INVALID)
1747436Sdam.sunwoo@arm.com    0xff,  // DomainL2 (INVALID)
1757436Sdam.sunwoo@arm.com    0xff,  // DomainL3 (INVALID)
1767436Sdam.sunwoo@arm.com    0x0c,  // PermissionL0
1777436Sdam.sunwoo@arm.com    0x0d,  // PermissionL1
1787436Sdam.sunwoo@arm.com    0x0e,  // PermissionL2
17913393Sgiacomo.travaglini@arm.com    0x0f,  // PermissionL3
18010037SARM gem5 Developers    0xff,  // DebugEvent (INVALID)
1817436Sdam.sunwoo@arm.com    0x10,  // SynchronousExternalAbort
1827436Sdam.sunwoo@arm.com    0x30,  // TLBConflictAbort
1837436Sdam.sunwoo@arm.com    0x18,  // SynchPtyErrOnMemoryAccess
1847436Sdam.sunwoo@arm.com    0xff,  // AsynchronousExternalAbort (INVALID)
1857436Sdam.sunwoo@arm.com    0xff,  // AsynchPtyErrOnMemoryAccess (INVALID)
1867436Sdam.sunwoo@arm.com    0x00,  // AddressSizeL0
1877436Sdam.sunwoo@arm.com    0x01,  // AddressSizeL1
1887436Sdam.sunwoo@arm.com    0x02,  // AddressSizeL2
1897436Sdam.sunwoo@arm.com    0x03,  // AddressSizeL3
1907436Sdam.sunwoo@arm.com    0x40,  // PrefetchTLBMiss
1917436Sdam.sunwoo@arm.com    0x80   // PrefetchUncacheable
1927436Sdam.sunwoo@arm.com};
1937436Sdam.sunwoo@arm.com
1947436Sdam.sunwoo@arm.comstatic_assert(sizeof(ArmFault::aarch64FaultSources) ==
1957436Sdam.sunwoo@arm.com              ArmFault::NumFaultSources,
1967436Sdam.sunwoo@arm.com              "Invalid size of ArmFault::aarch64FaultSources[]");
19713393Sgiacomo.travaglini@arm.com
19813393Sgiacomo.travaglini@arm.com// Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode,
19913393Sgiacomo.travaglini@arm.com//         {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap,
20013393Sgiacomo.travaglini@arm.com//         {A, F} disable, class, stat
20113393Sgiacomo.travaglini@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals = {
20213393Sgiacomo.travaglini@arm.com    // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED
20313393Sgiacomo.travaglini@arm.com    // location in AArch64)
20413393Sgiacomo.travaglini@arm.com    "Reset",                 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
20513393Sgiacomo.travaglini@arm.com    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
20613393Sgiacomo.travaglini@arm.com};
20713393Sgiacomo.travaglini@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals = {
20813393Sgiacomo.travaglini@arm.com    "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
20913393Sgiacomo.travaglini@arm.com    4, 2, 0, 0, true,  false, false, EC_UNKNOWN, FaultStat()
21013393Sgiacomo.travaglini@arm.com};
21113393Sgiacomo.travaglini@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals = {
21213393Sgiacomo.travaglini@arm.com    "Supervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
21313396Sgiacomo.travaglini@arm.com    4, 2, 4, 2, true,  false, false, EC_SVC_TO_HYP, FaultStat()
21413396Sgiacomo.travaglini@arm.com};
21513396Sgiacomo.travaglini@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals = {
21613396Sgiacomo.travaglini@arm.com    "Secure Monitor Call",   0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON,
21713393Sgiacomo.travaglini@arm.com    4, 4, 4, 4, false, true,  true,  EC_SMC_TO_HYP, FaultStat()
21813393Sgiacomo.travaglini@arm.com};
21913393Sgiacomo.travaglini@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals = {
22013393Sgiacomo.travaglini@arm.com    "Hypervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
22113393Sgiacomo.travaglini@arm.com    4, 4, 4, 4, true,  false, false, EC_HVC, FaultStat()
22213393Sgiacomo.travaglini@arm.com};
22313393Sgiacomo.travaglini@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals = {
22413393Sgiacomo.travaglini@arm.com    "Prefetch Abort",        0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
22513393Sgiacomo.travaglini@arm.com    4, 4, 0, 0, true,  true,  false, EC_PREFETCH_ABORT_TO_HYP, FaultStat()
22613393Sgiacomo.travaglini@arm.com};
22713393Sgiacomo.travaglini@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals = {
22813393Sgiacomo.travaglini@arm.com    "Data Abort",            0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
22913393Sgiacomo.travaglini@arm.com    8, 8, 0, 0, true,  true,  false, EC_DATA_ABORT_TO_HYP, FaultStat()
23013393Sgiacomo.travaglini@arm.com};
23113393Sgiacomo.travaglini@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals = {
23213393Sgiacomo.travaglini@arm.com    "Virtual Data Abort",    0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
23313393Sgiacomo.travaglini@arm.com    8, 8, 0, 0, true,  true,  false, EC_INVALID, FaultStat()
23413393Sgiacomo.travaglini@arm.com};
2357644Sali.saidi@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals = {
2368147SAli.Saidi@ARM.com    // @todo: double check these values
2379385SAndreas.Sandberg@arm.com    "Hypervisor Trap",       0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2389385SAndreas.Sandberg@arm.com    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
23910037SARM gem5 Developers};
24010037SARM gem5 Developerstemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals = {
24110037SARM gem5 Developers    "IRQ",                   0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
24210037SARM gem5 Developers    4, 4, 0, 0, false, true,  false, EC_UNKNOWN, FaultStat()
24310037SARM gem5 Developers};
24410037SARM gem5 Developerstemplate<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals = {
24510037SARM gem5 Developers    "Virtual IRQ",           0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
24610037SARM gem5 Developers    4, 4, 0, 0, false, true,  false, EC_INVALID, FaultStat()
24710037SARM gem5 Developers};
24810037SARM gem5 Developerstemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals = {
24910037SARM gem5 Developers    "FIQ",                   0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
25010037SARM gem5 Developers    4, 4, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
25110037SARM gem5 Developers};
25210037SARM gem5 Developerstemplate<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals = {
25310037SARM gem5 Developers    "Virtual FIQ",           0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
25410037SARM gem5 Developers    4, 4, 0, 0, false, true,  true,  EC_INVALID, FaultStat()
2558147SAli.Saidi@ARM.com};
2567427Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals = {
2577427Sgblack@eecs.umich.edu    // Some dummy values (SupervisorTrap is AArch64-only)
2587427Sgblack@eecs.umich.edu    "Supervisor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
25910037SARM gem5 Developers    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
26010037SARM gem5 Developers};
26110037SARM gem5 Developerstemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals = {
26210037SARM gem5 Developers    // Some dummy values (SecureMonitorTrap is AArch64-only)
26313396Sgiacomo.travaglini@arm.com    "Secure Monitor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_MON,
26410037SARM gem5 Developers    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
26510037SARM gem5 Developers};
26610037SARM gem5 Developerstemplate<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals = {
26710037SARM gem5 Developers    // Some dummy values (PCAlignmentFault is AArch64-only)
26810037SARM gem5 Developers    "PC Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
26910037SARM gem5 Developers    0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT, FaultStat()
27010037SARM gem5 Developers};
27110037SARM gem5 Developerstemplate<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals = {
27210037SARM gem5 Developers    // Some dummy values (SPAlignmentFault is AArch64-only)
27310037SARM gem5 Developers    "SP Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
27410037SARM gem5 Developers    0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT, FaultStat()
27510037SARM gem5 Developers};
27610037SARM gem5 Developerstemplate<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals = {
27710037SARM gem5 Developers    // Some dummy values (SError is AArch64-only)
27810037SARM gem5 Developers    "SError",                0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC,
27910037SARM gem5 Developers    0, 0, 0, 0, false, true,  true,  EC_SERROR, FaultStat()
28010037SARM gem5 Developers};
28110037SARM gem5 Developerstemplate<> ArmFault::FaultVals ArmFaultVals<FlushPipe>::vals = {
28210037SARM gem5 Developers    // Some dummy values
28310037SARM gem5 Developers    "Pipe Flush",            0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
28410037SARM gem5 Developers    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
28510037SARM gem5 Developers};
28610037SARM gem5 Developerstemplate<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals = {
28710037SARM gem5 Developers    // Some dummy values
28810037SARM gem5 Developers    "ArmSev Flush",          0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
28910037SARM gem5 Developers    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
29010037SARM gem5 Developers};
29110037SARM gem5 Developerstemplate<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals = {
29210037SARM gem5 Developers    // Some dummy values (SPAlignmentFault is AArch64-only)
29310037SARM gem5 Developers    "Illegal Inst Set State Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
29410037SARM gem5 Developers    0, 0, 0, 0, true, false, false, EC_ILLEGAL_INST, FaultStat()
29511770SCurtis.Dunham@arm.com};
29610037SARM gem5 Developers
29711574SCurtis.Dunham@arm.comAddr
29811770SCurtis.Dunham@arm.comArmFault::getVector(ThreadContext *tc)
29911770SCurtis.Dunham@arm.com{
30010037SARM gem5 Developers    Addr base;
30111770SCurtis.Dunham@arm.com
30211770SCurtis.Dunham@arm.com    // ARM ARM issue C B1.8.1
30310037SARM gem5 Developers    bool haveSecurity = ArmSystem::haveSecurity(tc);
30410037SARM gem5 Developers
30510037SARM gem5 Developers    // panic if SCTLR.VE because I have no idea what to do with vectored
30613114Sgiacomo.travaglini@arm.com    // interrupts
30710037SARM gem5 Developers    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
30813114Sgiacomo.travaglini@arm.com    assert(!sctlr.ve);
30913114Sgiacomo.travaglini@arm.com    // Check for invalid modes
31013114Sgiacomo.travaglini@arm.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
31113114Sgiacomo.travaglini@arm.com    assert(haveSecurity                      || cpsr.mode != MODE_MON);
31213114Sgiacomo.travaglini@arm.com    assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
31313114Sgiacomo.travaglini@arm.com
31413114Sgiacomo.travaglini@arm.com    switch (cpsr.mode)
31513114Sgiacomo.travaglini@arm.com    {
31613114Sgiacomo.travaglini@arm.com      case MODE_MON:
31713114Sgiacomo.travaglini@arm.com        base = tc->readMiscReg(MISCREG_MVBAR);
31813114Sgiacomo.travaglini@arm.com        break;
31913114Sgiacomo.travaglini@arm.com      case MODE_HYP:
32013114Sgiacomo.travaglini@arm.com        base = tc->readMiscReg(MISCREG_HVBAR);
32113114Sgiacomo.travaglini@arm.com        break;
32213114Sgiacomo.travaglini@arm.com      default:
32313114Sgiacomo.travaglini@arm.com        if (sctlr.v) {
32413114Sgiacomo.travaglini@arm.com            base = HighVecs;
32513114Sgiacomo.travaglini@arm.com        } else {
32613114Sgiacomo.travaglini@arm.com            base = haveSecurity ? tc->readMiscReg(MISCREG_VBAR) : 0;
32713499Sgiacomo.travaglini@arm.com        }
32813499Sgiacomo.travaglini@arm.com        break;
32913499Sgiacomo.travaglini@arm.com    }
33013499Sgiacomo.travaglini@arm.com    return base + offset(tc);
33113114Sgiacomo.travaglini@arm.com}
33213114Sgiacomo.travaglini@arm.com
33313114Sgiacomo.travaglini@arm.comAddr
33413114Sgiacomo.travaglini@arm.comArmFault::getVector64(ThreadContext *tc)
33513114Sgiacomo.travaglini@arm.com{
33610037SARM gem5 Developers    Addr vbar;
33710037SARM gem5 Developers    switch (toEL) {
33810037SARM gem5 Developers      case EL3:
33910461SAndreas.Sandberg@ARM.com        assert(ArmSystem::haveSecurity(tc));
34010461SAndreas.Sandberg@ARM.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL3);
34110461SAndreas.Sandberg@ARM.com        break;
34210461SAndreas.Sandberg@ARM.com      case EL2:
34310037SARM gem5 Developers        assert(ArmSystem::haveVirtualization(tc));
34410037SARM gem5 Developers        vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
34510037SARM gem5 Developers        break;
34610037SARM gem5 Developers      case EL1:
34710037SARM gem5 Developers        vbar = tc->readMiscReg(MISCREG_VBAR_EL1);
34813116Sgiacomo.travaglini@arm.com        break;
34910037SARM gem5 Developers      default:
35010461SAndreas.Sandberg@ARM.com        panic("Invalid target exception level");
35110461SAndreas.Sandberg@ARM.com        break;
35210461SAndreas.Sandberg@ARM.com    }
35310461SAndreas.Sandberg@ARM.com    return vbar + offset64();
35410461SAndreas.Sandberg@ARM.com}
35510037SARM gem5 Developers
35610037SARM gem5 DevelopersMiscRegIndex
35710037SARM gem5 DevelopersArmFault::getSyndromeReg64() const
35810037SARM gem5 Developers{
35910037SARM gem5 Developers    switch (toEL) {
36011574SCurtis.Dunham@arm.com      case EL1:
36110037SARM gem5 Developers        return MISCREG_ESR_EL1;
36210037SARM gem5 Developers      case EL2:
36310037SARM gem5 Developers        return MISCREG_ESR_EL2;
36411574SCurtis.Dunham@arm.com      case EL3:
36510037SARM gem5 Developers        return MISCREG_ESR_EL3;
36610037SARM gem5 Developers      default:
36710037SARM gem5 Developers        panic("Invalid exception level");
36810037SARM gem5 Developers        break;
36910037SARM gem5 Developers    }
37010037SARM gem5 Developers}
37110037SARM gem5 Developers
37213114Sgiacomo.travaglini@arm.comMiscRegIndex
37313173Sgiacomo.travaglini@arm.comArmFault::getFaultAddrReg64() const
37413173Sgiacomo.travaglini@arm.com{
37513173Sgiacomo.travaglini@arm.com    switch (toEL) {
37613173Sgiacomo.travaglini@arm.com      case EL1:
37710037SARM gem5 Developers        return MISCREG_FAR_EL1;
37810037SARM gem5 Developers      case EL2:
37912972Sandreas.sandberg@arm.com        return MISCREG_FAR_EL2;
38012972Sandreas.sandberg@arm.com      case EL3:
38112972Sandreas.sandberg@arm.com        return MISCREG_FAR_EL3;
38212972Sandreas.sandberg@arm.com      default:
38312972Sandreas.sandberg@arm.com        panic("Invalid exception level");
38413531Sjairo.balart@metempsy.com        break;
38513531Sjairo.balart@metempsy.com    }
38613531Sjairo.balart@metempsy.com}
38713531Sjairo.balart@metempsy.com
38813531Sjairo.balart@metempsy.comvoid
38913531Sjairo.balart@metempsy.comArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
39013531Sjairo.balart@metempsy.com{
39112972Sandreas.sandberg@arm.com    uint32_t value;
39212972Sandreas.sandberg@arm.com    uint32_t exc_class = (uint32_t) ec(tc);
39312972Sandreas.sandberg@arm.com    uint32_t issVal = iss();
39413581Sgabeblack@google.com    assert(!from64 || ArmSystem::highestELIs64(tc));
39510035Sandreas.hansson@arm.com
3967405SAli.Saidi@ARM.com    value = exc_class << 26;
3977405SAli.Saidi@ARM.com
3987614Sminkyu.jeong@arm.com    // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24,
39912478SCurtis.Dunham@arm.com    // 0x25) for which the ISS information is not valid (ARMv7).
40012478SCurtis.Dunham@arm.com    // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not
40112478SCurtis.Dunham@arm.com    // valid it is treated as RES1.
40212478SCurtis.Dunham@arm.com    if (to64) {
40312478SCurtis.Dunham@arm.com        value |= 1 << 25;
40412478SCurtis.Dunham@arm.com    } else if ((bits(exc_class, 5, 3) != 4) ||
40512478SCurtis.Dunham@arm.com               (bits(exc_class, 2) && bits(issVal, 24))) {
40612478SCurtis.Dunham@arm.com        if (!machInst.thumb || machInst.bigThumb)
40712478SCurtis.Dunham@arm.com            value |= 1 << 25;
40812478SCurtis.Dunham@arm.com    }
40912478SCurtis.Dunham@arm.com    // Condition code valid for EC[5:4] nonzero
41012478SCurtis.Dunham@arm.com    if (!from64 && ((bits(exc_class, 5, 4) == 0) &&
41112478SCurtis.Dunham@arm.com                    (bits(exc_class, 3, 0) != 0))) {
41212478SCurtis.Dunham@arm.com        if (!machInst.thumb) {
41312478SCurtis.Dunham@arm.com            uint32_t      cond;
41412478SCurtis.Dunham@arm.com            ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode;
4157405SAli.Saidi@ARM.com            // If its on unconditional instruction report with a cond code of
4167405SAli.Saidi@ARM.com            // 0xE, ie the unconditional code
4177405SAli.Saidi@ARM.com            cond  = (condCode == COND_UC) ? COND_AL : condCode;
41813581Sgabeblack@google.com            value |= cond << 20;
4197405SAli.Saidi@ARM.com            value |= 1    << 24;
4207405SAli.Saidi@ARM.com        }
42110037SARM gem5 Developers        value |= bits(issVal, 19, 0);
42210037SARM gem5 Developers    } else {
42310037SARM gem5 Developers        value |= issVal;
4249050Schander.sudanthi@arm.com    }
4257405SAli.Saidi@ARM.com    tc->setMiscReg(syndrome_reg, value);
42610037SARM gem5 Developers}
42710037SARM gem5 Developers
4287720Sgblack@eecs.umich.eduvoid
4297720Sgblack@eecs.umich.eduArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
4307405SAli.Saidi@ARM.com{
4317405SAli.Saidi@ARM.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
4327757SAli.Saidi@ARM.com
43310037SARM gem5 Developers    if (ArmSystem::highestELIs64(tc)) {  // ARMv8
43410037SARM gem5 Developers        // Determine source exception level and mode
43510037SARM gem5 Developers        fromMode = (OperatingMode) (uint8_t) cpsr.mode;
43610037SARM gem5 Developers        fromEL = opModeToEL(fromMode);
43710037SARM gem5 Developers        if (opModeIs64(fromMode))
43810037SARM gem5 Developers            from64 = true;
43910037SARM gem5 Developers
44010037SARM gem5 Developers        // Determine target exception level
44110037SARM gem5 Developers        if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc))
44210037SARM gem5 Developers            toEL = EL3;
44310037SARM gem5 Developers        else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc))
44410037SARM gem5 Developers            toEL = EL2;
44510037SARM gem5 Developers        else
44610037SARM gem5 Developers            toEL = opModeToEL(nextMode());
44710037SARM gem5 Developers        if (fromEL > toEL)
44810037SARM gem5 Developers            toEL = fromEL;
44910037SARM gem5 Developers
45010037SARM gem5 Developers        if (toEL == ArmSystem::highestEL(tc) || ELIs64(tc, toEL)) {
45110037SARM gem5 Developers            // Invoke exception handler in AArch64 state
45210037SARM gem5 Developers            to64 = true;
45310037SARM gem5 Developers            invoke64(tc, inst);
45410037SARM gem5 Developers            return;
45510037SARM gem5 Developers        }
45610037SARM gem5 Developers    }
45710037SARM gem5 Developers
45810037SARM gem5 Developers    // ARMv7 (ARM ARM issue C B1.9)
45910037SARM gem5 Developers
46010037SARM gem5 Developers    bool have_security       = ArmSystem::haveSecurity(tc);
46110037SARM gem5 Developers    bool have_virtualization = ArmSystem::haveVirtualization(tc);
46210037SARM gem5 Developers
46310037SARM gem5 Developers    FaultBase::invoke(tc);
46410037SARM gem5 Developers    if (!FullSystem)
46510037SARM gem5 Developers        return;
46612667Schuan.zhu@arm.com    countStat()++;
46710037SARM gem5 Developers
46810037SARM gem5 Developers    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
46910037SARM gem5 Developers    SCR scr = tc->readMiscReg(MISCREG_SCR);
47010037SARM gem5 Developers    CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR);
47110037SARM gem5 Developers    saved_cpsr.nz = tc->readCCReg(CCREG_NZ);
47210037SARM gem5 Developers    saved_cpsr.c = tc->readCCReg(CCREG_C);
47313581Sgabeblack@google.com    saved_cpsr.v = tc->readCCReg(CCREG_V);
47410037SARM gem5 Developers    saved_cpsr.ge = tc->readCCReg(CCREG_GE);
47510037SARM gem5 Developers
47610037SARM gem5 Developers    Addr curPc M5_VAR_USED = tc->pcState().pc();
47710037SARM gem5 Developers    ITSTATE it = tc->pcState().itstate();
47810037SARM gem5 Developers    saved_cpsr.it2 = it.top6;
4798284SAli.Saidi@ARM.com    saved_cpsr.it1 = it.bottom2;
48010037SARM gem5 Developers
48113550Sgiacomo.travaglini@arm.com    // if we have a valid instruction then use it to annotate this fault with
48210037SARM gem5 Developers    // extra information. This is used to generate the correct fault syndrome
48313550Sgiacomo.travaglini@arm.com    // information
48410037SARM gem5 Developers    if (inst) {
48510037SARM gem5 Developers        ArmStaticInst *armInst = reinterpret_cast<ArmStaticInst *>(inst.get());
48610037SARM gem5 Developers        armInst->annotateFault(this);
48710037SARM gem5 Developers    }
48810037SARM gem5 Developers
48910037SARM gem5 Developers    if (have_security && routeToMonitor(tc))
49010037SARM gem5 Developers        cpsr.mode = MODE_MON;
49110037SARM gem5 Developers    else if (have_virtualization && routeToHyp(tc))
49210037SARM gem5 Developers        cpsr.mode = MODE_HYP;
49310037SARM gem5 Developers    else
49410037SARM gem5 Developers        cpsr.mode = nextMode();
4959050Schander.sudanthi@arm.com
4968284SAli.Saidi@ARM.com    // Ensure Secure state if initially in Monitor mode
49710037SARM gem5 Developers    if (have_security && saved_cpsr.mode == MODE_MON) {
49810037SARM gem5 Developers        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
49910037SARM gem5 Developers        if (scr.ns) {
50010037SARM gem5 Developers            scr.ns = 0;
50110037SARM gem5 Developers            tc->setMiscRegNoEffect(MISCREG_SCR, scr);
50210037SARM gem5 Developers        }
50310037SARM gem5 Developers    }
5047405SAli.Saidi@ARM.com
5057731SAli.Saidi@ARM.com    // some bits are set differently if we have been routed to hyp mode
5068468Swade.walker@arm.com    if (cpsr.mode == MODE_HYP) {
5078468Swade.walker@arm.com        SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR);
5088468Swade.walker@arm.com        cpsr.t = hsctlr.te;
5097405SAli.Saidi@ARM.com        cpsr.e = hsctlr.ee;
5107731SAli.Saidi@ARM.com        if (!scr.ea)  {cpsr.a = 1;}
5117405SAli.Saidi@ARM.com        if (!scr.fiq) {cpsr.f = 1;}
5127405SAli.Saidi@ARM.com        if (!scr.irq) {cpsr.i = 1;}
51311809Sbaz21@cam.ac.uk    } else if (cpsr.mode == MODE_MON) {
51411809Sbaz21@cam.ac.uk        // Special case handling when entering monitor mode
5159130Satgutier@umich.edu        cpsr.t = sctlr.te;
5169130Satgutier@umich.edu        cpsr.e = sctlr.ee;
5179130Satgutier@umich.edu        cpsr.a = 1;
5189130Satgutier@umich.edu        cpsr.f = 1;
5199814Sandreas.hansson@arm.com        cpsr.i = 1;
5209130Satgutier@umich.edu    } else {
5219130Satgutier@umich.edu        cpsr.t = sctlr.te;
5229130Satgutier@umich.edu        cpsr.e = sctlr.ee;
5239130Satgutier@umich.edu
5249130Satgutier@umich.edu        // The *Disable functions are virtual and different per fault
5259130Satgutier@umich.edu        cpsr.a = cpsr.a | abortDisable(tc);
5269130Satgutier@umich.edu        cpsr.f = cpsr.f | fiqDisable(tc);
5279130Satgutier@umich.edu        cpsr.i = 1;
5289130Satgutier@umich.edu    }
5299130Satgutier@umich.edu    cpsr.it1 = cpsr.it2 = 0;
5309130Satgutier@umich.edu    cpsr.j = 0;
5319130Satgutier@umich.edu    tc->setMiscReg(MISCREG_CPSR, cpsr);
5329130Satgutier@umich.edu
5339130Satgutier@umich.edu    // Make sure mailbox sets to one always
5349130Satgutier@umich.edu    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
5359130Satgutier@umich.edu
5369130Satgutier@umich.edu    // Clear the exclusive monitor
5379130Satgutier@umich.edu    tc->setMiscReg(MISCREG_LOCKFLAG, 0);
5389130Satgutier@umich.edu
5399130Satgutier@umich.edu    if (cpsr.mode == MODE_HYP) {
5409130Satgutier@umich.edu        tc->setMiscReg(MISCREG_ELR_HYP, curPc +
5419130Satgutier@umich.edu                (saved_cpsr.t ? thumbPcOffset(true)  : armPcOffset(true)));
5427583SAli.Saidi@arm.com    } else {
5437583SAli.Saidi@arm.com        tc->setIntReg(INTREG_LR, curPc +
5447583SAli.Saidi@arm.com                (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false)));
54510461SAndreas.Sandberg@ARM.com    }
54610461SAndreas.Sandberg@ARM.com
54710461SAndreas.Sandberg@ARM.com    switch (cpsr.mode) {
54810461SAndreas.Sandberg@ARM.com      case MODE_FIQ:
54910461SAndreas.Sandberg@ARM.com        tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
55010461SAndreas.Sandberg@ARM.com        break;
55110461SAndreas.Sandberg@ARM.com      case MODE_IRQ:
5528302SAli.Saidi@ARM.com        tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
5538302SAli.Saidi@ARM.com        break;
5547783SGiacomo.Gabrielli@arm.com      case MODE_SVC:
5557783SGiacomo.Gabrielli@arm.com        tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
5567783SGiacomo.Gabrielli@arm.com        break;
5577783SGiacomo.Gabrielli@arm.com      case MODE_MON:
55810037SARM gem5 Developers        assert(have_security);
55910037SARM gem5 Developers        tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr);
56010037SARM gem5 Developers        break;
56110037SARM gem5 Developers      case MODE_ABORT:
56210037SARM gem5 Developers        tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
56310037SARM gem5 Developers        break;
56410037SARM gem5 Developers      case MODE_UNDEFINED:
56510037SARM gem5 Developers        tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
56610037SARM gem5 Developers        if (ec(tc) != EC_UNKNOWN)
56710037SARM gem5 Developers            setSyndrome(tc, MISCREG_HSR);
56810037SARM gem5 Developers        break;
56910037SARM gem5 Developers      case MODE_HYP:
57010037SARM gem5 Developers        assert(have_virtualization);
57110037SARM gem5 Developers        tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr);
57210037SARM gem5 Developers        setSyndrome(tc, MISCREG_HSR);
57310037SARM gem5 Developers        break;
57410037SARM gem5 Developers      default:
57510037SARM gem5 Developers        panic("unknown Mode\n");
57610037SARM gem5 Developers    }
57710037SARM gem5 Developers
57810037SARM gem5 Developers    Addr newPc = getVector(tc);
57910037SARM gem5 Developers    DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n",
58010037SARM gem5 Developers            name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc);
58110037SARM gem5 Developers    PCState pc(newPc);
58210037SARM gem5 Developers    pc.thumb(cpsr.t);
58310037SARM gem5 Developers    pc.nextThumb(pc.thumb());
58410037SARM gem5 Developers    pc.jazelle(cpsr.j);
58510037SARM gem5 Developers    pc.nextJazelle(pc.jazelle());
58610037SARM gem5 Developers    pc.aarch64(!cpsr.width);
58710037SARM gem5 Developers    pc.nextAArch64(!cpsr.width);
58810037SARM gem5 Developers    tc->pcState(pc);
58910037SARM gem5 Developers}
59010338SCurtis.Dunham@arm.com
59110338SCurtis.Dunham@arm.comvoid
59210338SCurtis.Dunham@arm.comArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
59310037SARM gem5 Developers{
59410037SARM gem5 Developers    // Determine actual misc. register indices for ELR_ELx and SPSR_ELx
59510037SARM gem5 Developers    MiscRegIndex elr_idx, spsr_idx;
59610037SARM gem5 Developers    switch (toEL) {
59710037SARM gem5 Developers      case EL1:
59810037SARM gem5 Developers        elr_idx = MISCREG_ELR_EL1;
59910037SARM gem5 Developers        spsr_idx = MISCREG_SPSR_EL1;
60010037SARM gem5 Developers        break;
60110037SARM gem5 Developers      case EL2:
60210037SARM gem5 Developers        assert(ArmSystem::haveVirtualization(tc));
60310037SARM gem5 Developers        elr_idx = MISCREG_ELR_EL2;
60410037SARM gem5 Developers        spsr_idx = MISCREG_SPSR_EL2;
60510037SARM gem5 Developers        break;
60610037SARM gem5 Developers      case EL3:
60710037SARM gem5 Developers        assert(ArmSystem::haveSecurity(tc));
60810037SARM gem5 Developers        elr_idx = MISCREG_ELR_EL3;
60910037SARM gem5 Developers        spsr_idx = MISCREG_SPSR_EL3;
61010037SARM gem5 Developers        break;
61110037SARM gem5 Developers      default:
61210037SARM gem5 Developers        panic("Invalid target exception level");
61310037SARM gem5 Developers        break;
61410037SARM gem5 Developers    }
61510037SARM gem5 Developers
61610037SARM gem5 Developers    // Save process state into SPSR_ELx
61710037SARM gem5 Developers    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
61810037SARM gem5 Developers    CPSR spsr = cpsr;
61910037SARM gem5 Developers    spsr.nz = tc->readCCReg(CCREG_NZ);
62010037SARM gem5 Developers    spsr.c = tc->readCCReg(CCREG_C);
6218549Sdaniel.johnson@arm.com    spsr.v = tc->readCCReg(CCREG_V);
6228868SMatt.Horsnell@arm.com    if (from64) {
6238868SMatt.Horsnell@arm.com        // Force some bitfields to 0
6248868SMatt.Horsnell@arm.com        spsr.q = 0;
6258868SMatt.Horsnell@arm.com        spsr.it1 = 0;
6268868SMatt.Horsnell@arm.com        spsr.j = 0;
6278868SMatt.Horsnell@arm.com        spsr.res0_23_22 = 0;
6288868SMatt.Horsnell@arm.com        spsr.ge = 0;
6298868SMatt.Horsnell@arm.com        spsr.it2 = 0;
6308868SMatt.Horsnell@arm.com        spsr.t = 0;
63110461SAndreas.Sandberg@ARM.com    } else {
6328868SMatt.Horsnell@arm.com        spsr.ge = tc->readCCReg(CCREG_GE);
63310461SAndreas.Sandberg@ARM.com        ITSTATE it = tc->pcState().itstate();
63410037SARM gem5 Developers        spsr.it2 = it.top6;
6358868SMatt.Horsnell@arm.com        spsr.it1 = it.bottom2;
63610037SARM gem5 Developers        // Force some bitfields to 0
63711150Smitch.hayenga@arm.com        spsr.res0_23_22 = 0;
63810037SARM gem5 Developers        spsr.ss = 0;
63910037SARM gem5 Developers    }
64010037SARM gem5 Developers    tc->setMiscReg(spsr_idx, spsr);
64110037SARM gem5 Developers
64211150Smitch.hayenga@arm.com    // Save preferred return address into ELR_ELx
64310037SARM gem5 Developers    Addr curr_pc = tc->pcState().pc();
64410037SARM gem5 Developers    Addr ret_addr = curr_pc;
64510037SARM gem5 Developers    if (from64)
64610037SARM gem5 Developers        ret_addr += armPcElrOffset();
64710037SARM gem5 Developers    else
64810037SARM gem5 Developers        ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset();
64910037SARM gem5 Developers    tc->setMiscReg(elr_idx, ret_addr);
65013581Sgabeblack@google.com
65110037SARM gem5 Developers    // Update process state
65210037SARM gem5 Developers    OperatingMode64 mode = 0;
65310037SARM gem5 Developers    mode.spX = 1;
65410037SARM gem5 Developers    mode.el = toEL;
65510037SARM gem5 Developers    mode.width = 0;
65610037SARM gem5 Developers    cpsr.mode = mode;
65710037SARM gem5 Developers    cpsr.daif = 0xf;
65810037SARM gem5 Developers    cpsr.il = 0;
65913581Sgabeblack@google.com    cpsr.ss = 0;
66010037SARM gem5 Developers    tc->setMiscReg(MISCREG_CPSR, cpsr);
66110037SARM gem5 Developers
66210037SARM gem5 Developers    // Set PC to start of exception handler
66310037SARM gem5 Developers    Addr new_pc = purifyTaggedAddr(getVector64(tc), tc, toEL);
66410037SARM gem5 Developers    DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x "
66510037SARM gem5 Developers            "elr:%#x newVec: %#x\n", name(), cpsr, curr_pc, ret_addr, new_pc);
66610037SARM gem5 Developers    PCState pc(new_pc);
66710037SARM gem5 Developers    pc.aarch64(!cpsr.width);
66810037SARM gem5 Developers    pc.nextAArch64(!cpsr.width);
66910037SARM gem5 Developers    tc->pcState(pc);
67010844Sandreas.sandberg@arm.com
67111772SCurtis.Dunham@arm.com    // If we have a valid instruction then use it to annotate this fault with
67211772SCurtis.Dunham@arm.com    // extra information. This is used to generate the correct fault syndrome
67311772SCurtis.Dunham@arm.com    // information
67411772SCurtis.Dunham@arm.com    if (inst)
67511774SCurtis.Dunham@arm.com        reinterpret_cast<ArmStaticInst *>(inst.get())->annotateFault(this);
67611774SCurtis.Dunham@arm.com    // Save exception syndrome
67711774SCurtis.Dunham@arm.com    if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ))
67811774SCurtis.Dunham@arm.com        setSyndrome(tc, getSyndromeReg64());
67911774SCurtis.Dunham@arm.com}
68011774SCurtis.Dunham@arm.com
68111774SCurtis.Dunham@arm.comvoid
68211773SCurtis.Dunham@arm.comReset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
68313531Sjairo.balart@metempsy.com{
68413531Sjairo.balart@metempsy.com    if (FullSystem) {
68513531Sjairo.balart@metempsy.com        tc->getCpuPtr()->clearInterrupts(tc->threadId());
68613531Sjairo.balart@metempsy.com        tc->clearArchRegs();
68713531Sjairo.balart@metempsy.com    }
68811773SCurtis.Dunham@arm.com    if (!ArmSystem::highestELIs64(tc)) {
68911773SCurtis.Dunham@arm.com        ArmFault::invoke(tc, inst);
69011772SCurtis.Dunham@arm.com        tc->setMiscReg(MISCREG_VMPIDR,
69110037SARM gem5 Developers                       getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc));
69212816Sgiacomo.travaglini@arm.com
69312816Sgiacomo.travaglini@arm.com        // Unless we have SMC code to get us there, boot in HYP!
69412816Sgiacomo.travaglini@arm.com        if (ArmSystem::haveVirtualization(tc) &&
69510844Sandreas.sandberg@arm.com            !ArmSystem::haveSecurity(tc)) {
69610844Sandreas.sandberg@arm.com            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
69710844Sandreas.sandberg@arm.com            cpsr.mode = MODE_HYP;
69810844Sandreas.sandberg@arm.com            tc->setMiscReg(MISCREG_CPSR, cpsr);
69910844Sandreas.sandberg@arm.com        }
70010844Sandreas.sandberg@arm.com    } else {
70113531Sjairo.balart@metempsy.com        // Advance the PC to the IMPLEMENTATION DEFINED reset value
70213531Sjairo.balart@metempsy.com        PCState pc = ArmSystem::resetAddr64(tc);
70313531Sjairo.balart@metempsy.com        pc.aarch64(true);
70413531Sjairo.balart@metempsy.com        pc.nextAArch64(true);
70510188Sgeoffrey.blake@arm.com        tc->pcState(pc);
70610037SARM gem5 Developers    }
70710037SARM gem5 Developers}
7087405SAli.Saidi@ARM.com
7097405SAli.Saidi@ARM.comvoid
7107405SAli.Saidi@ARM.comUndefinedInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
7117405SAli.Saidi@ARM.com{
7127405SAli.Saidi@ARM.com    if (FullSystem) {
71313582Sgabeblack@google.com        ArmFault::invoke(tc, inst);
7147405SAli.Saidi@ARM.com        return;
7157405SAli.Saidi@ARM.com    }
7167614Sminkyu.jeong@arm.com
71712478SCurtis.Dunham@arm.com    // If the mnemonic isn't defined this has to be an unknown instruction.
71812478SCurtis.Dunham@arm.com    assert(unknown || mnemonic != NULL);
71912478SCurtis.Dunham@arm.com    if (disabled) {
72012478SCurtis.Dunham@arm.com        panic("Attempted to execute disabled instruction "
72112478SCurtis.Dunham@arm.com                "'%s' (inst 0x%08x)", mnemonic, machInst);
72211771SCurtis.Dunham@arm.com    } else if (unknown) {
72312478SCurtis.Dunham@arm.com        panic("Attempted to execute unknown instruction (inst 0x%08x)",
72412478SCurtis.Dunham@arm.com              machInst);
72510037SARM gem5 Developers    } else {
72612478SCurtis.Dunham@arm.com        panic("Attempted to execute unimplemented instruction "
72710037SARM gem5 Developers                "'%s' (inst 0x%08x)", mnemonic, machInst);
72812478SCurtis.Dunham@arm.com    }
72910037SARM gem5 Developers}
73012478SCurtis.Dunham@arm.com
73110037SARM gem5 Developersbool
7327405SAli.Saidi@ARM.comUndefinedInstruction::routeToHyp(ThreadContext *tc) const
7337405SAli.Saidi@ARM.com{
7347405SAli.Saidi@ARM.com    bool toHyp;
73513582Sgabeblack@google.com
7367405SAli.Saidi@ARM.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
7377749SAli.Saidi@ARM.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
73813581Sgabeblack@google.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
73910037SARM gem5 Developers
74010037SARM gem5 Developers    // if in Hyp mode then stay in Hyp mode
7418284SAli.Saidi@ARM.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
7427405SAli.Saidi@ARM.com    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
7437405SAli.Saidi@ARM.com    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
7447749SAli.Saidi@ARM.com    return toHyp;
7457749SAli.Saidi@ARM.com}
7467749SAli.Saidi@ARM.com
7477749SAli.Saidi@ARM.comuint32_t
7487405SAli.Saidi@ARM.comUndefinedInstruction::iss() const
74912510Sgiacomo.travaglini@arm.com{
75012406Sgabeblack@google.com    if (overrideEc == EC_INVALID)
75112406Sgabeblack@google.com        return issRaw;
7527749SAli.Saidi@ARM.com
7537749SAli.Saidi@ARM.com    uint32_t new_iss = 0;
7547614Sminkyu.jeong@arm.com    uint32_t op0, op1, op2, CRn, CRm, Rt, dir;
7557614Sminkyu.jeong@arm.com
7567720Sgblack@eecs.umich.edu    dir = bits(machInst, 21, 21);
7577720Sgblack@eecs.umich.edu    op0 = bits(machInst, 20, 19);
7587720Sgblack@eecs.umich.edu    op1 = bits(machInst, 18, 16);
75912763Sgiacomo.travaglini@arm.com    CRn = bits(machInst, 15, 12);
7608887Sgeoffrey.blake@arm.com    CRm = bits(machInst, 11, 8);
7618887Sgeoffrey.blake@arm.com    op2 = bits(machInst, 7, 5);
7628887Sgeoffrey.blake@arm.com    Rt = bits(machInst, 4, 0);
7638887Sgeoffrey.blake@arm.com
7648887Sgeoffrey.blake@arm.com    new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 |
7658887Sgeoffrey.blake@arm.com            Rt << 5 | CRm << 1 | dir;
7668887Sgeoffrey.blake@arm.com
7678887Sgeoffrey.blake@arm.com    return new_iss;
7688887Sgeoffrey.blake@arm.com}
7697408Sgblack@eecs.umich.edu
77010037SARM gem5 Developersvoid
77110037SARM gem5 DevelopersSupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
77210037SARM gem5 Developers{
77310037SARM gem5 Developers    if (FullSystem) {
77410037SARM gem5 Developers        ArmFault::invoke(tc, inst);
77510037SARM gem5 Developers        return;
77610037SARM gem5 Developers    }
77710037SARM gem5 Developers
77810037SARM gem5 Developers    // As of now, there isn't a 32 bit thumb version of this instruction.
77910037SARM gem5 Developers    assert(!machInst.bigThumb);
78010037SARM gem5 Developers    uint32_t callNum;
7817408Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
7827408Sgblack@eecs.umich.edu    OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
7838206SWilliam.Wang@arm.com    if (opModeIs64(mode))
7848206SWilliam.Wang@arm.com        callNum = tc->readIntReg(INTREG_X8);
7858206SWilliam.Wang@arm.com    else
7868206SWilliam.Wang@arm.com        callNum = tc->readIntReg(INTREG_R7);
7878206SWilliam.Wang@arm.com    Fault fault;
7888206SWilliam.Wang@arm.com    tc->syscall(callNum, &fault);
7898206SWilliam.Wang@arm.com
7908206SWilliam.Wang@arm.com    // Advance the PC since that won't happen automatically.
79110037SARM gem5 Developers    PCState pc = tc->pcState();
79210037SARM gem5 Developers    assert(inst);
79310037SARM gem5 Developers    inst->advancePC(pc);
79410037SARM gem5 Developers    tc->pcState(pc);
79510037SARM gem5 Developers}
79612667Schuan.zhu@arm.com
79710037SARM gem5 Developersbool
79810037SARM gem5 DevelopersSupervisorCall::routeToHyp(ThreadContext *tc) const
79910037SARM gem5 Developers{
80010037SARM gem5 Developers    bool toHyp;
80110037SARM gem5 Developers
80210037SARM gem5 Developers    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
80310037SARM gem5 Developers    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
80413581Sgabeblack@google.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
8058206SWilliam.Wang@arm.com
80610037SARM gem5 Developers    // if in Hyp mode then stay in Hyp mode
80710037SARM gem5 Developers    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
80810037SARM gem5 Developers    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
80910037SARM gem5 Developers    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
81010037SARM gem5 Developers    return toHyp;
81110037SARM gem5 Developers}
81210037SARM gem5 Developers
81310037SARM gem5 DevelopersExceptionClass
81410037SARM gem5 DevelopersSupervisorCall::ec(ThreadContext *tc) const
81510037SARM gem5 Developers{
81610037SARM gem5 Developers    return (overrideEc != EC_INVALID) ? overrideEc :
81710037SARM gem5 Developers        (from64 ? EC_SVC_64 : vals.ec);
81810037SARM gem5 Developers}
81910037SARM gem5 Developers
82010037SARM gem5 Developersuint32_t
82110037SARM gem5 DevelopersSupervisorCall::iss() const
82210037SARM gem5 Developers{
82310037SARM gem5 Developers    // Even if we have a 24 bit imm from an arm32 instruction then we only use
82410037SARM gem5 Developers    // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC).
82510037SARM gem5 Developers    return issRaw & 0xFFFF;
82610037SARM gem5 Developers}
82710037SARM gem5 Developers
82810037SARM gem5 Developersuint32_t
82910037SARM gem5 DevelopersSecureMonitorCall::iss() const
83010037SARM gem5 Developers{
83110037SARM gem5 Developers    if (from64)
83210037SARM gem5 Developers        return bits(machInst, 20, 5);
83310037SARM gem5 Developers    return 0;
83410037SARM gem5 Developers}
8358206SWilliam.Wang@arm.com
8368206SWilliam.Wang@arm.comExceptionClass
8377408Sgblack@eecs.umich.eduUndefinedInstruction::ec(ThreadContext *tc) const
8387408Sgblack@eecs.umich.edu{
8397408Sgblack@eecs.umich.edu    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
8407731SAli.Saidi@ARM.com}
8418206SWilliam.Wang@arm.com
84210037SARM gem5 Developers
84310037SARM gem5 DevelopersHypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) :
84410037SARM gem5 Developers        ArmFaultVals<HypervisorCall>(_machInst, _imm)
84510037SARM gem5 Developers{}
84610037SARM gem5 Developers
8477408Sgblack@eecs.umich.eduExceptionClass
8487408Sgblack@eecs.umich.eduHypervisorCall::ec(ThreadContext *tc) const
8497408Sgblack@eecs.umich.edu{
8507408Sgblack@eecs.umich.edu    return from64 ? EC_HVC_64 : vals.ec;
8517408Sgblack@eecs.umich.edu}
8527408Sgblack@eecs.umich.edu
8537408Sgblack@eecs.umich.eduExceptionClass
8547408Sgblack@eecs.umich.eduHypervisorTrap::ec(ThreadContext *tc) const
8557408Sgblack@eecs.umich.edu{
8567408Sgblack@eecs.umich.edu    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
85710037SARM gem5 Developers}
85810037SARM gem5 Developers
85910037SARM gem5 Developerstemplate<class T>
86010037SARM gem5 DevelopersFaultOffset
86110037SARM gem5 DevelopersArmFaultVals<T>::offset(ThreadContext *tc)
86210037SARM gem5 Developers{
8637408Sgblack@eecs.umich.edu    bool isHypTrap = false;
8647408Sgblack@eecs.umich.edu
8657408Sgblack@eecs.umich.edu    // Normally we just use the exception vector from the table at the top if
8667408Sgblack@eecs.umich.edu    // this file, however if this exception has caused a transition to hype
8677408Sgblack@eecs.umich.edu    // mode, and its an exception type that would only do this if it has been
8687408Sgblack@eecs.umich.edu    // trapped then we use the hyp trap vector instead of the normal vector
8697408Sgblack@eecs.umich.edu    if (vals.hypTrappable) {
8707408Sgblack@eecs.umich.edu        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
8717408Sgblack@eecs.umich.edu        if (cpsr.mode == MODE_HYP) {
8727408Sgblack@eecs.umich.edu            CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
8737408Sgblack@eecs.umich.edu            isHypTrap = spsr.mode != MODE_HYP;
8747408Sgblack@eecs.umich.edu        }
87510037SARM gem5 Developers    }
87610037SARM gem5 Developers    return isHypTrap ? 0x14 : vals.offset;
8779377Sgblack@eecs.umich.edu}
8787408Sgblack@eecs.umich.edu
8797408Sgblack@eecs.umich.edu// void
88010037SARM gem5 Developers// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx)
88110037SARM gem5 Developers// {
88210037SARM gem5 Developers//     ESR esr = 0;
88310037SARM gem5 Developers//     esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32;
88410037SARM gem5 Developers//     esr.il = !machInst.thumb;
88510037SARM gem5 Developers//     if (machInst.aarch64)
88610037SARM gem5 Developers//         esr.imm16 = bits(machInst.instBits, 20, 5);
88710037SARM gem5 Developers//     else if (machInst.thumb)
88810037SARM gem5 Developers//         esr.imm16 = bits(machInst.instBits, 7, 0);
88910037SARM gem5 Developers//     else
89010037SARM gem5 Developers//         esr.imm16 = bits(machInst.instBits, 15, 0);
89110037SARM gem5 Developers//     tc->setMiscReg(esr_idx, esr);
89210037SARM gem5 Developers// }
89310037SARM gem5 Developers
89410037SARM gem5 Developersvoid
89510037SARM gem5 DevelopersSecureMonitorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
89610037SARM gem5 Developers{
89710037SARM gem5 Developers    if (FullSystem) {
89810037SARM gem5 Developers        ArmFault::invoke(tc, inst);
89910037SARM gem5 Developers        return;
90010037SARM gem5 Developers    }
90110037SARM gem5 Developers}
90210037SARM gem5 Developers
90310037SARM gem5 DevelopersExceptionClass
90410037SARM gem5 DevelopersSecureMonitorCall::ec(ThreadContext *tc) const
90510037SARM gem5 Developers{
90610037SARM gem5 Developers    return (from64 ? EC_SMC_64 : vals.ec);
90710037SARM gem5 Developers}
90810037SARM gem5 Developers
90910037SARM gem5 DevelopersExceptionClass
91010037SARM gem5 DevelopersSupervisorTrap::ec(ThreadContext *tc) const
91110037SARM gem5 Developers{
91210037SARM gem5 Developers    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
91310037SARM gem5 Developers}
91410037SARM gem5 Developers
91510037SARM gem5 DevelopersExceptionClass
91610037SARM gem5 DevelopersSecureMonitorTrap::ec(ThreadContext *tc) const
9178302SAli.Saidi@ARM.com{
9188302SAli.Saidi@ARM.com    return (overrideEc != EC_INVALID) ? overrideEc :
9198302SAli.Saidi@ARM.com        (from64 ? EC_SMC_64 : vals.ec);
92010037SARM gem5 Developers}
9218302SAli.Saidi@ARM.com
9228302SAli.Saidi@ARM.comtemplate<class T>
9238302SAli.Saidi@ARM.comvoid
9247783SGiacomo.Gabrielli@arm.comAbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
9257783SGiacomo.Gabrielli@arm.com{
92610037SARM gem5 Developers    if (tranMethod == ArmFault::UnknownTran) {
92710037SARM gem5 Developers        tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran
9287783SGiacomo.Gabrielli@arm.com                                             : ArmFault::VmsaTran;
9297783SGiacomo.Gabrielli@arm.com
9307783SGiacomo.Gabrielli@arm.com        if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) {
9317783SGiacomo.Gabrielli@arm.com            // See ARM ARM B3-1416
9327783SGiacomo.Gabrielli@arm.com            bool override_LPAE = false;
93310037SARM gem5 Developers            TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S);
93410037SARM gem5 Developers            TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS);
9357783SGiacomo.Gabrielli@arm.com            if (ttbcr_s.eae) {
9367783SGiacomo.Gabrielli@arm.com                override_LPAE = true;
9377783SGiacomo.Gabrielli@arm.com            } else {
9387408Sgblack@eecs.umich.edu                // Unimplemented code option, not seen in testing.  May need
9397408Sgblack@eecs.umich.edu                // extension according to the manual exceprt above.
9408206SWilliam.Wang@arm.com                DPRINTF(Faults, "Warning: Incomplete translation method "
9418206SWilliam.Wang@arm.com                        "override detected.\n");
9427408Sgblack@eecs.umich.edu            }
9437408Sgblack@eecs.umich.edu            if (override_LPAE)
94410037SARM gem5 Developers                tranMethod = ArmFault::LpaeTran;
9457408Sgblack@eecs.umich.edu        }
9467408Sgblack@eecs.umich.edu    }
94710037SARM gem5 Developers
94810037SARM gem5 Developers    if (source == ArmFault::AsynchronousExternalAbort) {
94910037SARM gem5 Developers        tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
95010037SARM gem5 Developers    }
95110037SARM gem5 Developers    // Get effective fault source encoding
95210037SARM gem5 Developers    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
95310037SARM gem5 Developers    FSR  fsr  = getFsr(tc);
95410037SARM gem5 Developers
95510037SARM gem5 Developers    // source must be determined BEFORE invoking generic routines which will
95610037SARM gem5 Developers    // try to set hsr etc. and are based upon source!
95710037SARM gem5 Developers    ArmFaultVals<T>::invoke(tc, inst);
95810037SARM gem5 Developers
95910037SARM gem5 Developers    if (!this->to64) {  // AArch32
96010037SARM gem5 Developers        if (cpsr.mode == MODE_HYP) {
96110037SARM gem5 Developers            tc->setMiscReg(T::HFarIndex, faultAddr);
96210037SARM gem5 Developers        } else if (stage2) {
96310037SARM gem5 Developers            tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf);
96410037SARM gem5 Developers            tc->setMiscReg(T::HFarIndex,  OVAddr);
96510037SARM gem5 Developers        } else {
96610037SARM gem5 Developers            tc->setMiscReg(T::FsrIndex, fsr);
96710037SARM gem5 Developers            tc->setMiscReg(T::FarIndex, faultAddr);
96810037SARM gem5 Developers        }
96910037SARM gem5 Developers        DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\
97010037SARM gem5 Developers                "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod);
97110037SARM gem5 Developers    } else {  // AArch64
97210037SARM gem5 Developers        // Set the FAR register.  Nothing else to do if we are in AArch64 state
97310037SARM gem5 Developers        // because the syndrome register has already been set inside invoke64()
97410037SARM gem5 Developers        if (stage2) {
97510037SARM gem5 Developers            // stage 2 fault, set HPFAR_EL2 to the faulting IPA
97610037SARM gem5 Developers            // and FAR_EL2 to the Original VA
97710037SARM gem5 Developers            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr);
97810037SARM gem5 Developers            tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
97912406Sgabeblack@google.com
98012406Sgabeblack@google.com            DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
98110037SARM gem5 Developers                    OVAddr, faultAddr);
9827408Sgblack@eecs.umich.edu        } else {
9837408Sgblack@eecs.umich.edu            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
9847408Sgblack@eecs.umich.edu        }
98510037SARM gem5 Developers    }
98612639Sgiacomo.travaglini@arm.com}
98712639Sgiacomo.travaglini@arm.com
98812639Sgiacomo.travaglini@arm.comtemplate<class T>
98912639Sgiacomo.travaglini@arm.comFSR
99012639Sgiacomo.travaglini@arm.comAbortFault<T>::getFsr(ThreadContext *tc)
99112639Sgiacomo.travaglini@arm.com{
99212639Sgiacomo.travaglini@arm.com    FSR fsr = 0;
99312639Sgiacomo.travaglini@arm.com
99410037SARM gem5 Developers    if (((CPSR) tc->readMiscRegNoEffect(MISCREG_CPSR)).width) {
9957408Sgblack@eecs.umich.edu        // AArch32
99610037SARM gem5 Developers        assert(tranMethod != ArmFault::UnknownTran);
99713581Sgabeblack@google.com        if (tranMethod == ArmFault::LpaeTran) {
99812406Sgabeblack@google.com            srcEncoded = ArmFault::longDescFaultSources[source];
99912406Sgabeblack@google.com            fsr.status = srcEncoded;
10007408Sgblack@eecs.umich.edu            fsr.lpae   = 1;
10019385SAndreas.Sandberg@arm.com        } else {
10029385SAndreas.Sandberg@arm.com            srcEncoded = ArmFault::shortDescFaultSources[source];
10039385SAndreas.Sandberg@arm.com            fsr.fsLow  = bits(srcEncoded, 3, 0);
100410461SAndreas.Sandberg@ARM.com            fsr.fsHigh = bits(srcEncoded, 4);
10059385SAndreas.Sandberg@arm.com            fsr.domain = static_cast<uint8_t>(domain);
10069385SAndreas.Sandberg@arm.com        }
10079385SAndreas.Sandberg@arm.com        fsr.wnr = (write ? 1 : 0);
10089385SAndreas.Sandberg@arm.com        fsr.ext = 0;
10099385SAndreas.Sandberg@arm.com    } else {
10109385SAndreas.Sandberg@arm.com        // AArch64
10119385SAndreas.Sandberg@arm.com        srcEncoded = ArmFault::aarch64FaultSources[source];
10129385SAndreas.Sandberg@arm.com    }
10139385SAndreas.Sandberg@arm.com    if (srcEncoded == ArmFault::FaultSourceInvalid) {
10149385SAndreas.Sandberg@arm.com        panic("Invalid fault source\n");
10159385SAndreas.Sandberg@arm.com    }
10169385SAndreas.Sandberg@arm.com    return fsr;
10179385SAndreas.Sandberg@arm.com}
10187408Sgblack@eecs.umich.edu
10197408Sgblack@eecs.umich.edutemplate<class T>
10207408Sgblack@eecs.umich.edubool
102110037SARM gem5 DevelopersAbortFault<T>::abortDisable(ThreadContext *tc)
102210037SARM gem5 Developers{
102310037SARM gem5 Developers    if (ArmSystem::haveSecurity(tc)) {
102410037SARM gem5 Developers        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
102510037SARM gem5 Developers        return (!scr.ns || scr.aw);
102610037SARM gem5 Developers    }
102710037SARM gem5 Developers    return true;
102810037SARM gem5 Developers}
102910037SARM gem5 Developers
103013116Sgiacomo.travaglini@arm.comtemplate<class T>
103110037SARM gem5 Developersvoid
103210037SARM gem5 DevelopersAbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val)
10339385SAndreas.Sandberg@arm.com{
10347408Sgblack@eecs.umich.edu    switch (id)
10359385SAndreas.Sandberg@arm.com    {
103612605Sgiacomo.travaglini@arm.com      case ArmFault::S1PTW:
103712605Sgiacomo.travaglini@arm.com        s1ptw = val;
103812605Sgiacomo.travaglini@arm.com        break;
103912605Sgiacomo.travaglini@arm.com      case ArmFault::OVA:
104012605Sgiacomo.travaglini@arm.com        OVAddr = val;
104112605Sgiacomo.travaglini@arm.com        break;
104212605Sgiacomo.travaglini@arm.com
104312605Sgiacomo.travaglini@arm.com      // Just ignore unknown ID's
104412605Sgiacomo.travaglini@arm.com      default:
104512605Sgiacomo.travaglini@arm.com        break;
104612605Sgiacomo.travaglini@arm.com    }
10477408Sgblack@eecs.umich.edu}
104812605Sgiacomo.travaglini@arm.com
104912605Sgiacomo.travaglini@arm.comtemplate<class T>
105012605Sgiacomo.travaglini@arm.comuint32_t
105112605Sgiacomo.travaglini@arm.comAbortFault<T>::iss() const
105212605Sgiacomo.travaglini@arm.com{
105312605Sgiacomo.travaglini@arm.com    uint32_t val;
105412605Sgiacomo.travaglini@arm.com
105512605Sgiacomo.travaglini@arm.com    val  = srcEncoded & 0x3F;
105612605Sgiacomo.travaglini@arm.com    val |= write << 6;
10577408Sgblack@eecs.umich.edu    val |= s1ptw << 7;
105812605Sgiacomo.travaglini@arm.com    return (val);
105912605Sgiacomo.travaglini@arm.com}
106012605Sgiacomo.travaglini@arm.com
106112605Sgiacomo.travaglini@arm.comtemplate<class T>
106212605Sgiacomo.travaglini@arm.combool
106312605Sgiacomo.travaglini@arm.comAbortFault<T>::isMMUFault() const
106412605Sgiacomo.travaglini@arm.com{
106512605Sgiacomo.travaglini@arm.com    // NOTE: Not relying on LL information being aligned to lowest bits here
106612605Sgiacomo.travaglini@arm.com    return
10677408Sgblack@eecs.umich.edu         (source == ArmFault::AlignmentFault)     ||
106812605Sgiacomo.travaglini@arm.com        ((source >= ArmFault::TranslationLL) &&
106912605Sgiacomo.travaglini@arm.com         (source <  ArmFault::TranslationLL + 4)) ||
107012605Sgiacomo.travaglini@arm.com        ((source >= ArmFault::AccessFlagLL) &&
107112605Sgiacomo.travaglini@arm.com         (source <  ArmFault::AccessFlagLL + 4))  ||
107212605Sgiacomo.travaglini@arm.com        ((source >= ArmFault::DomainLL) &&
107312605Sgiacomo.travaglini@arm.com         (source <  ArmFault::DomainLL + 4))      ||
107412605Sgiacomo.travaglini@arm.com        ((source >= ArmFault::PermissionLL) &&
107512605Sgiacomo.travaglini@arm.com         (source <  ArmFault::PermissionLL + 4));
107612605Sgiacomo.travaglini@arm.com}
107712605Sgiacomo.travaglini@arm.com
107812605Sgiacomo.travaglini@arm.comExceptionClass
107912605Sgiacomo.travaglini@arm.comPrefetchAbort::ec(ThreadContext *tc) const
108012605Sgiacomo.travaglini@arm.com{
108112576Sgiacomo.travaglini@arm.com    if (to64) {
108212605Sgiacomo.travaglini@arm.com        // AArch64
108312605Sgiacomo.travaglini@arm.com        if (toEL == fromEL)
108412605Sgiacomo.travaglini@arm.com            return EC_PREFETCH_ABORT_CURR_EL;
108512605Sgiacomo.travaglini@arm.com        else
108612605Sgiacomo.travaglini@arm.com            return EC_PREFETCH_ABORT_LOWER_EL;
108712605Sgiacomo.travaglini@arm.com    } else {
108812605Sgiacomo.travaglini@arm.com        // AArch32
108912605Sgiacomo.travaglini@arm.com        // Abort faults have different EC codes depending on whether
109012605Sgiacomo.travaglini@arm.com        // the fault originated within HYP mode, or not. So override
109112605Sgiacomo.travaglini@arm.com        // the method and add the extra adjustment of the EC value.
109212605Sgiacomo.travaglini@arm.com
109312605Sgiacomo.travaglini@arm.com        ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec;
109412605Sgiacomo.travaglini@arm.com
109512605Sgiacomo.travaglini@arm.com        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
109612576Sgiacomo.travaglini@arm.com        if (spsr.mode == MODE_HYP) {
109712605Sgiacomo.travaglini@arm.com            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
109812605Sgiacomo.travaglini@arm.com        }
109912605Sgiacomo.travaglini@arm.com        return ec;
110012605Sgiacomo.travaglini@arm.com    }
110112605Sgiacomo.travaglini@arm.com}
110212605Sgiacomo.travaglini@arm.com
110312605Sgiacomo.travaglini@arm.combool
110412605Sgiacomo.travaglini@arm.comPrefetchAbort::routeToMonitor(ThreadContext *tc) const
110512605Sgiacomo.travaglini@arm.com{
110612605Sgiacomo.travaglini@arm.com    SCR scr = 0;
110712605Sgiacomo.travaglini@arm.com    if (from64)
110812605Sgiacomo.travaglini@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
110912605Sgiacomo.travaglini@arm.com    else
111012605Sgiacomo.travaglini@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
111112605Sgiacomo.travaglini@arm.com
111212605Sgiacomo.travaglini@arm.com    return scr.ea && !isMMUFault();
111312605Sgiacomo.travaglini@arm.com}
111412605Sgiacomo.travaglini@arm.com
111512605Sgiacomo.travaglini@arm.combool
111612605Sgiacomo.travaglini@arm.comPrefetchAbort::routeToHyp(ThreadContext *tc) const
111712605Sgiacomo.travaglini@arm.com{
111812605Sgiacomo.travaglini@arm.com    bool toHyp;
111912605Sgiacomo.travaglini@arm.com
112012605Sgiacomo.travaglini@arm.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
112112605Sgiacomo.travaglini@arm.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
112212605Sgiacomo.travaglini@arm.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
11237408Sgblack@eecs.umich.edu    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
112412605Sgiacomo.travaglini@arm.com
112512605Sgiacomo.travaglini@arm.com    // if in Hyp mode then stay in Hyp mode
112612605Sgiacomo.travaglini@arm.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
112712605Sgiacomo.travaglini@arm.com    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
112812605Sgiacomo.travaglini@arm.com    toHyp |= (stage2 ||
112912605Sgiacomo.travaglini@arm.com                ( (source ==               DebugEvent) && hdcr.tde && (cpsr.mode !=  MODE_HYP)) ||
113012605Sgiacomo.travaglini@arm.com                ( (source == SynchronousExternalAbort) && hcr.tge  && (cpsr.mode == MODE_USER))
113112605Sgiacomo.travaglini@arm.com             ) && !inSecureState(tc);
113212605Sgiacomo.travaglini@arm.com    return toHyp;
113312605Sgiacomo.travaglini@arm.com}
113412605Sgiacomo.travaglini@arm.com
113512605Sgiacomo.travaglini@arm.comExceptionClass
113612605Sgiacomo.travaglini@arm.comDataAbort::ec(ThreadContext *tc) const
113712605Sgiacomo.travaglini@arm.com{
113812605Sgiacomo.travaglini@arm.com    if (to64) {
113912605Sgiacomo.travaglini@arm.com        // AArch64
114012576Sgiacomo.travaglini@arm.com        if (source == ArmFault::AsynchronousExternalAbort) {
114112605Sgiacomo.travaglini@arm.com            panic("Asynchronous External Abort should be handled with "
114212605Sgiacomo.travaglini@arm.com                    "SystemErrors (SErrors)!");
114312605Sgiacomo.travaglini@arm.com        }
114412605Sgiacomo.travaglini@arm.com        if (toEL == fromEL)
114512605Sgiacomo.travaglini@arm.com            return EC_DATA_ABORT_CURR_EL;
114612605Sgiacomo.travaglini@arm.com        else
114712605Sgiacomo.travaglini@arm.com            return EC_DATA_ABORT_LOWER_EL;
114812605Sgiacomo.travaglini@arm.com    } else {
114912605Sgiacomo.travaglini@arm.com        // AArch32
115012605Sgiacomo.travaglini@arm.com        // Abort faults have different EC codes depending on whether
115112605Sgiacomo.travaglini@arm.com        // the fault originated within HYP mode, or not. So override
115212605Sgiacomo.travaglini@arm.com        // the method and add the extra adjustment of the EC value.
115312576Sgiacomo.travaglini@arm.com
115412605Sgiacomo.travaglini@arm.com        ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec;
115512605Sgiacomo.travaglini@arm.com
115612605Sgiacomo.travaglini@arm.com        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
115712605Sgiacomo.travaglini@arm.com        if (spsr.mode == MODE_HYP) {
115812605Sgiacomo.travaglini@arm.com            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
115912605Sgiacomo.travaglini@arm.com        }
116012605Sgiacomo.travaglini@arm.com        return ec;
116112605Sgiacomo.travaglini@arm.com    }
116212605Sgiacomo.travaglini@arm.com}
116312605Sgiacomo.travaglini@arm.com
116412605Sgiacomo.travaglini@arm.combool
116512605Sgiacomo.travaglini@arm.comDataAbort::routeToMonitor(ThreadContext *tc) const
116612605Sgiacomo.travaglini@arm.com{
116712605Sgiacomo.travaglini@arm.com    SCR scr = 0;
116812605Sgiacomo.travaglini@arm.com    if (from64)
116912576Sgiacomo.travaglini@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
117012605Sgiacomo.travaglini@arm.com    else
117112605Sgiacomo.travaglini@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
117212605Sgiacomo.travaglini@arm.com
117312605Sgiacomo.travaglini@arm.com    return scr.ea && !isMMUFault();
117412605Sgiacomo.travaglini@arm.com}
117512605Sgiacomo.travaglini@arm.com
117612605Sgiacomo.travaglini@arm.combool
117712605Sgiacomo.travaglini@arm.comDataAbort::routeToHyp(ThreadContext *tc) const
117812605Sgiacomo.travaglini@arm.com{
117912605Sgiacomo.travaglini@arm.com    bool toHyp;
118012605Sgiacomo.travaglini@arm.com
118112605Sgiacomo.travaglini@arm.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
118212576Sgiacomo.travaglini@arm.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
118312605Sgiacomo.travaglini@arm.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
118412605Sgiacomo.travaglini@arm.com    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
118512605Sgiacomo.travaglini@arm.com
118612605Sgiacomo.travaglini@arm.com    // if in Hyp mode then stay in Hyp mode
118712605Sgiacomo.travaglini@arm.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
118812605Sgiacomo.travaglini@arm.com    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
118912605Sgiacomo.travaglini@arm.com    toHyp |= (stage2 ||
119012605Sgiacomo.travaglini@arm.com                ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) ||
119112605Sgiacomo.travaglini@arm.com                                               ((source == DebugEvent) && hdcr.tde) )
119212605Sgiacomo.travaglini@arm.com                ) ||
119312605Sgiacomo.travaglini@arm.com                ( (cpsr.mode == MODE_USER) && hcr.tge &&
119412605Sgiacomo.travaglini@arm.com                  ((source == AlignmentFault)            ||
119512605Sgiacomo.travaglini@arm.com                   (source == SynchronousExternalAbort))
119612605Sgiacomo.travaglini@arm.com                )
119712605Sgiacomo.travaglini@arm.com             ) && !inSecureState(tc);
119812577Sgiacomo.travaglini@arm.com    return toHyp;
119912605Sgiacomo.travaglini@arm.com}
120012605Sgiacomo.travaglini@arm.com
120112605Sgiacomo.travaglini@arm.comuint32_t
120212605Sgiacomo.travaglini@arm.comDataAbort::iss() const
120312605Sgiacomo.travaglini@arm.com{
120412605Sgiacomo.travaglini@arm.com    uint32_t val;
120512605Sgiacomo.travaglini@arm.com
120612605Sgiacomo.travaglini@arm.com    // Add on the data abort specific fields to the generic abort ISS value
120712605Sgiacomo.travaglini@arm.com    val  = AbortFault<DataAbort>::iss();
120812605Sgiacomo.travaglini@arm.com    // ISS is valid if not caused by a stage 1 page table walk, and when taken
120912605Sgiacomo.travaglini@arm.com    // to AArch64 only when directed to EL2
121012605Sgiacomo.travaglini@arm.com    if (!s1ptw && (!to64 || toEL == EL2)) {
121112605Sgiacomo.travaglini@arm.com        val |= isv << 24;
121212605Sgiacomo.travaglini@arm.com        if (isv) {
121312577Sgiacomo.travaglini@arm.com            val |= sas << 22;
121412605Sgiacomo.travaglini@arm.com            val |= sse << 21;
121512605Sgiacomo.travaglini@arm.com            val |= srt << 16;
121612605Sgiacomo.travaglini@arm.com            // AArch64 only. These assignments are safe on AArch32 as well
121712605Sgiacomo.travaglini@arm.com            // because these vars are initialized to false
121812605Sgiacomo.travaglini@arm.com            val |= sf << 15;
121912605Sgiacomo.travaglini@arm.com            val |= ar << 14;
122012605Sgiacomo.travaglini@arm.com        }
122112605Sgiacomo.travaglini@arm.com    }
122212605Sgiacomo.travaglini@arm.com    return (val);
122312605Sgiacomo.travaglini@arm.com}
122412605Sgiacomo.travaglini@arm.com
122512605Sgiacomo.travaglini@arm.comvoid
122610037SARM gem5 DevelopersDataAbort::annotate(AnnotationIDs id, uint64_t val)
122712605Sgiacomo.travaglini@arm.com{
122812605Sgiacomo.travaglini@arm.com    AbortFault<DataAbort>::annotate(id, val);
122912605Sgiacomo.travaglini@arm.com    switch (id)
123012605Sgiacomo.travaglini@arm.com    {
123112605Sgiacomo.travaglini@arm.com      case SAS:
123212605Sgiacomo.travaglini@arm.com        isv = true;
123312605Sgiacomo.travaglini@arm.com        sas = val;
123412605Sgiacomo.travaglini@arm.com        break;
123512605Sgiacomo.travaglini@arm.com      case SSE:
123612605Sgiacomo.travaglini@arm.com        isv = true;
123712605Sgiacomo.travaglini@arm.com        sse = val;
123812605Sgiacomo.travaglini@arm.com        break;
123912605Sgiacomo.travaglini@arm.com      case SRT:
124010037SARM gem5 Developers        isv = true;
124112605Sgiacomo.travaglini@arm.com        srt = val;
124212605Sgiacomo.travaglini@arm.com        break;
124312605Sgiacomo.travaglini@arm.com      case SF:
124412605Sgiacomo.travaglini@arm.com        isv = true;
124512605Sgiacomo.travaglini@arm.com        sf  = val;
124612605Sgiacomo.travaglini@arm.com        break;
124712605Sgiacomo.travaglini@arm.com      case AR:
124812605Sgiacomo.travaglini@arm.com        isv = true;
124912605Sgiacomo.travaglini@arm.com        ar  = val;
125012605Sgiacomo.travaglini@arm.com        break;
125112605Sgiacomo.travaglini@arm.com      // Just ignore unknown ID's
125212605Sgiacomo.travaglini@arm.com      default:
125312605Sgiacomo.travaglini@arm.com        break;
125410037SARM gem5 Developers    }
125512605Sgiacomo.travaglini@arm.com}
125612605Sgiacomo.travaglini@arm.com
125712605Sgiacomo.travaglini@arm.comvoid
125812605Sgiacomo.travaglini@arm.comVirtualDataAbort::invoke(ThreadContext *tc, const StaticInstPtr &inst)
125912605Sgiacomo.travaglini@arm.com{
126012605Sgiacomo.travaglini@arm.com    AbortFault<VirtualDataAbort>::invoke(tc, inst);
126112605Sgiacomo.travaglini@arm.com    HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
126212605Sgiacomo.travaglini@arm.com    hcr.va = 0;
126312605Sgiacomo.travaglini@arm.com    tc->setMiscRegNoEffect(MISCREG_HCR, hcr);
126412605Sgiacomo.travaglini@arm.com}
126512605Sgiacomo.travaglini@arm.com
126612605Sgiacomo.travaglini@arm.combool
126710037SARM gem5 DevelopersInterrupt::routeToMonitor(ThreadContext *tc) const
126812605Sgiacomo.travaglini@arm.com{
126912605Sgiacomo.travaglini@arm.com    assert(ArmSystem::haveSecurity(tc));
127012605Sgiacomo.travaglini@arm.com    SCR scr = 0;
127112605Sgiacomo.travaglini@arm.com    if (from64)
127212605Sgiacomo.travaglini@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
127312605Sgiacomo.travaglini@arm.com    else
127412605Sgiacomo.travaglini@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
127512605Sgiacomo.travaglini@arm.com    return scr.irq;
127612605Sgiacomo.travaglini@arm.com}
127712605Sgiacomo.travaglini@arm.com
127812605Sgiacomo.travaglini@arm.combool
127912605Sgiacomo.travaglini@arm.comInterrupt::routeToHyp(ThreadContext *tc) const
128010037SARM gem5 Developers{
128112605Sgiacomo.travaglini@arm.com    bool toHyp;
128212605Sgiacomo.travaglini@arm.com
128312605Sgiacomo.travaglini@arm.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
128412605Sgiacomo.travaglini@arm.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
128512605Sgiacomo.travaglini@arm.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
128612605Sgiacomo.travaglini@arm.com    // Determine whether IRQs are routed to Hyp mode.
128712605Sgiacomo.travaglini@arm.com    toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) ||
128812605Sgiacomo.travaglini@arm.com            (cpsr.mode == MODE_HYP);
128910037SARM gem5 Developers    return toHyp;
129012605Sgiacomo.travaglini@arm.com}
129112605Sgiacomo.travaglini@arm.com
129212605Sgiacomo.travaglini@arm.combool
129312605Sgiacomo.travaglini@arm.comInterrupt::abortDisable(ThreadContext *tc)
129412605Sgiacomo.travaglini@arm.com{
129512605Sgiacomo.travaglini@arm.com    if (ArmSystem::haveSecurity(tc)) {
129612605Sgiacomo.travaglini@arm.com        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
129712605Sgiacomo.travaglini@arm.com        return (!scr.ns || scr.aw);
129810037SARM gem5 Developers    }
129912605Sgiacomo.travaglini@arm.com    return true;
130012605Sgiacomo.travaglini@arm.com}
130112605Sgiacomo.travaglini@arm.com
130212605Sgiacomo.travaglini@arm.comVirtualInterrupt::VirtualInterrupt()
130312605Sgiacomo.travaglini@arm.com{}
130412605Sgiacomo.travaglini@arm.com
130512605Sgiacomo.travaglini@arm.combool
130612605Sgiacomo.travaglini@arm.comFastInterrupt::routeToMonitor(ThreadContext *tc) const
130710037SARM gem5 Developers{
130812605Sgiacomo.travaglini@arm.com    assert(ArmSystem::haveSecurity(tc));
130912605Sgiacomo.travaglini@arm.com    SCR scr = 0;
131012605Sgiacomo.travaglini@arm.com    if (from64)
131112605Sgiacomo.travaglini@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
131212605Sgiacomo.travaglini@arm.com    else
131312605Sgiacomo.travaglini@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
131412605Sgiacomo.travaglini@arm.com    return scr.fiq;
131512605Sgiacomo.travaglini@arm.com}
131612605Sgiacomo.travaglini@arm.com
131712605Sgiacomo.travaglini@arm.combool
131812605Sgiacomo.travaglini@arm.comFastInterrupt::routeToHyp(ThreadContext *tc) const
131912605Sgiacomo.travaglini@arm.com{
132012605Sgiacomo.travaglini@arm.com    bool toHyp;
132112605Sgiacomo.travaglini@arm.com
132212605Sgiacomo.travaglini@arm.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
132312605Sgiacomo.travaglini@arm.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
132412605Sgiacomo.travaglini@arm.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
132510037SARM gem5 Developers    // Determine whether IRQs are routed to Hyp mode.
132612605Sgiacomo.travaglini@arm.com    toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) ||
132712605Sgiacomo.travaglini@arm.com            (cpsr.mode == MODE_HYP);
132812605Sgiacomo.travaglini@arm.com    return toHyp;
132912605Sgiacomo.travaglini@arm.com}
133012605Sgiacomo.travaglini@arm.com
133112605Sgiacomo.travaglini@arm.combool
133212605Sgiacomo.travaglini@arm.comFastInterrupt::abortDisable(ThreadContext *tc)
133313549Sanouk.vanlaer@arm.com{
133413549Sanouk.vanlaer@arm.com    if (ArmSystem::haveSecurity(tc)) {
133513549Sanouk.vanlaer@arm.com        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
133613549Sanouk.vanlaer@arm.com        return (!scr.ns || scr.aw);
133713549Sanouk.vanlaer@arm.com    }
133813549Sanouk.vanlaer@arm.com    return true;
133913549Sanouk.vanlaer@arm.com}
134013549Sanouk.vanlaer@arm.com
134113549Sanouk.vanlaer@arm.combool
134213549Sanouk.vanlaer@arm.comFastInterrupt::fiqDisable(ThreadContext *tc)
134313549Sanouk.vanlaer@arm.com{
134412605Sgiacomo.travaglini@arm.com    if (ArmSystem::haveVirtualization(tc)) {
134510037SARM gem5 Developers        return true;
134610037SARM gem5 Developers    } else if (ArmSystem::haveSecurity(tc)) {
134710037SARM gem5 Developers        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
134810037SARM gem5 Developers        return (!scr.ns || scr.fw);
134912605Sgiacomo.travaglini@arm.com    }
135012605Sgiacomo.travaglini@arm.com    return true;
135112605Sgiacomo.travaglini@arm.com}
135212605Sgiacomo.travaglini@arm.com
135312605Sgiacomo.travaglini@arm.comVirtualFastInterrupt::VirtualFastInterrupt()
135412605Sgiacomo.travaglini@arm.com{}
135512605Sgiacomo.travaglini@arm.com
135612605Sgiacomo.travaglini@arm.comvoid
135712605Sgiacomo.travaglini@arm.comPCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
135812605Sgiacomo.travaglini@arm.com{
135912605Sgiacomo.travaglini@arm.com    ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
136012605Sgiacomo.travaglini@arm.com    assert(from64);
136112605Sgiacomo.travaglini@arm.com    // Set the FAR
136212605Sgiacomo.travaglini@arm.com    tc->setMiscReg(getFaultAddrReg64(), faultPC);
136312605Sgiacomo.travaglini@arm.com}
136412605Sgiacomo.travaglini@arm.com
136512605Sgiacomo.travaglini@arm.comSPAlignmentFault::SPAlignmentFault()
136612605Sgiacomo.travaglini@arm.com{}
136712605Sgiacomo.travaglini@arm.com
136812605Sgiacomo.travaglini@arm.comSystemError::SystemError()
136912605Sgiacomo.travaglini@arm.com{}
137012605Sgiacomo.travaglini@arm.com
137112605Sgiacomo.travaglini@arm.comvoid
137210037SARM gem5 DevelopersSystemError::invoke(ThreadContext *tc, const StaticInstPtr &inst)
137310037SARM gem5 Developers{
137412605Sgiacomo.travaglini@arm.com    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
137512605Sgiacomo.travaglini@arm.com    ArmFault::invoke(tc, inst);
137612605Sgiacomo.travaglini@arm.com}
137712605Sgiacomo.travaglini@arm.com
137812605Sgiacomo.travaglini@arm.combool
137912605Sgiacomo.travaglini@arm.comSystemError::routeToMonitor(ThreadContext *tc) const
138012605Sgiacomo.travaglini@arm.com{
138112605Sgiacomo.travaglini@arm.com    assert(ArmSystem::haveSecurity(tc));
138212605Sgiacomo.travaglini@arm.com    assert(from64);
138312605Sgiacomo.travaglini@arm.com    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
138412605Sgiacomo.travaglini@arm.com    return scr.ea;
138512605Sgiacomo.travaglini@arm.com}
138612605Sgiacomo.travaglini@arm.com
138710037SARM gem5 Developersbool
138810037SARM gem5 DevelopersSystemError::routeToHyp(ThreadContext *tc) const
138912605Sgiacomo.travaglini@arm.com{
139012605Sgiacomo.travaglini@arm.com    bool toHyp;
139112605Sgiacomo.travaglini@arm.com    assert(from64);
139212605Sgiacomo.travaglini@arm.com
139312605Sgiacomo.travaglini@arm.com    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
139412605Sgiacomo.travaglini@arm.com    HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
139512605Sgiacomo.travaglini@arm.com
139612605Sgiacomo.travaglini@arm.com    toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) ||
139712605Sgiacomo.travaglini@arm.com            (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc));
139812605Sgiacomo.travaglini@arm.com    return toHyp;
139912605Sgiacomo.travaglini@arm.com}
140012605Sgiacomo.travaglini@arm.com
140112605Sgiacomo.travaglini@arm.comvoid
140212605Sgiacomo.travaglini@arm.comFlushPipe::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
140312605Sgiacomo.travaglini@arm.com    DPRINTF(Faults, "Invoking FlushPipe Fault\n");
140412605Sgiacomo.travaglini@arm.com
140512605Sgiacomo.travaglini@arm.com    // Set the PC to the next instruction of the faulting instruction.
140612605Sgiacomo.travaglini@arm.com    // Net effect is simply squashing all instructions behind and
140712605Sgiacomo.travaglini@arm.com    // start refetching from the next instruction.
140812605Sgiacomo.travaglini@arm.com    PCState pc = tc->pcState();
140912605Sgiacomo.travaglini@arm.com    assert(inst);
141012605Sgiacomo.travaglini@arm.com    inst->advancePC(pc);
141112605Sgiacomo.travaglini@arm.com    tc->pcState(pc);
141212605Sgiacomo.travaglini@arm.com}
141310037SARM gem5 Developers
141410037SARM gem5 Developersvoid
141512605Sgiacomo.travaglini@arm.comArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
141612605Sgiacomo.travaglini@arm.com    DPRINTF(Faults, "Invoking ArmSev Fault\n");
141712605Sgiacomo.travaglini@arm.com    if (!FullSystem)
141812605Sgiacomo.travaglini@arm.com        return;
141912605Sgiacomo.travaglini@arm.com
142012605Sgiacomo.travaglini@arm.com    // Set sev_mailbox to 1, clear the pending interrupt from remote
142112605Sgiacomo.travaglini@arm.com    // SEV execution and let pipeline continue as pcState is still
142212605Sgiacomo.travaglini@arm.com    // valid.
142312605Sgiacomo.travaglini@arm.com    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
142412605Sgiacomo.travaglini@arm.com    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0);
142512605Sgiacomo.travaglini@arm.com}
142612605Sgiacomo.travaglini@arm.com
142712605Sgiacomo.travaglini@arm.com// Instantiate all the templates to make the linker happy
142812605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<Reset>;
142912605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<UndefinedInstruction>;
143012605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<SupervisorCall>;
143112605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<SecureMonitorCall>;
143212605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<HypervisorCall>;
143312605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<PrefetchAbort>;
143412605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<DataAbort>;
143512605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<VirtualDataAbort>;
143612605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<HypervisorTrap>;
143712605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<Interrupt>;
143812605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<VirtualInterrupt>;
143912605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<FastInterrupt>;
144012605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<VirtualFastInterrupt>;
144112605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<SupervisorTrap>;
144212605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<SecureMonitorTrap>;
144310037SARM gem5 Developerstemplate class ArmFaultVals<PCAlignmentFault>;
144410037SARM gem5 Developerstemplate class ArmFaultVals<SPAlignmentFault>;
144512605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<SystemError>;
144612605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<FlushPipe>;
144712605Sgiacomo.travaglini@arm.comtemplate class ArmFaultVals<ArmSev>;
144812605Sgiacomo.travaglini@arm.comtemplate class AbortFault<PrefetchAbort>;
144912605Sgiacomo.travaglini@arm.comtemplate class AbortFault<DataAbort>;
145012605Sgiacomo.travaglini@arm.comtemplate class AbortFault<VirtualDataAbort>;
145112605Sgiacomo.travaglini@arm.com
145212605Sgiacomo.travaglini@arm.com
145312605Sgiacomo.travaglini@arm.comIllegalInstSetStateFault::IllegalInstSetStateFault()
145412605Sgiacomo.travaglini@arm.com{}
145512605Sgiacomo.travaglini@arm.com
145612605Sgiacomo.travaglini@arm.com
145712605Sgiacomo.travaglini@arm.com} // namespace ArmISA
145812605Sgiacomo.travaglini@arm.com