faults.cc revision 11793
1360SN/A/*
210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2010, 2012-2014, 2016 ARM Limited
310796Sbrandon.potter@amd.com * All rights reserved
410027SChris.Adeniyi-Jones@arm.com *
510027SChris.Adeniyi-Jones@arm.com * The license below extends only to copyright in the software and shall
610027SChris.Adeniyi-Jones@arm.com * not be construed as granting a license to any other intellectual
710027SChris.Adeniyi-Jones@arm.com * property including but not limited to intellectual property relating
810027SChris.Adeniyi-Jones@arm.com * to a hardware implementation of the functionality of the software
910027SChris.Adeniyi-Jones@arm.com * licensed hereunder.  You may use the software subject to the license
1010027SChris.Adeniyi-Jones@arm.com * terms below provided that you ensure that this notice is replicated
1110027SChris.Adeniyi-Jones@arm.com * unmodified and in its entirety in all distributions of the software,
1210027SChris.Adeniyi-Jones@arm.com * modified or unmodified, in source code or in binary form.
1310027SChris.Adeniyi-Jones@arm.com *
1410027SChris.Adeniyi-Jones@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
151458SN/A * Copyright (c) 2007-2008 The Florida State University
16360SN/A * All rights reserved.
17360SN/A *
18360SN/A * Redistribution and use in source and binary forms, with or without
19360SN/A * modification, are permitted provided that the following conditions are
20360SN/A * met: redistributions of source code must retain the above copyright
21360SN/A * notice, this list of conditions and the following disclaimer;
22360SN/A * redistributions in binary form must reproduce the above copyright
23360SN/A * notice, this list of conditions and the following disclaimer in the
24360SN/A * documentation and/or other materials provided with the distribution;
25360SN/A * neither the name of the copyright holders nor the names of its
26360SN/A * contributors may be used to endorse or promote products derived from
27360SN/A * this software without specific prior written permission.
28360SN/A *
29360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402665Ssaidi@eecs.umich.edu *
412665Ssaidi@eecs.umich.edu * Authors: Ali Saidi
422665Ssaidi@eecs.umich.edu *          Gabe Black
43360SN/A *          Giacomo Gabrielli
44360SN/A *          Thomas Grocutt
451354SN/A */
461354SN/A
47360SN/A#include "arch/arm/faults.hh"
4812018Sandreas.sandberg@arm.com
4912018Sandreas.sandberg@arm.com#include "arch/arm/insts/static_inst.hh"
5012018Sandreas.sandberg@arm.com#include "arch/arm/system.hh"
5112018Sandreas.sandberg@arm.com#include "arch/arm/utility.hh"
5212018Sandreas.sandberg@arm.com#include "base/compiler.hh"
5312018Sandreas.sandberg@arm.com#include "base/trace.hh"
5412018Sandreas.sandberg@arm.com#include "cpu/base.hh"
552064SN/A#include "cpu/thread_context.hh"
5612018Sandreas.sandberg@arm.com#include "debug/Faults.hh"
5712018Sandreas.sandberg@arm.com#include "sim/full_system.hh"
5812018Sandreas.sandberg@arm.com
5912018Sandreas.sandberg@arm.comnamespace ArmISA
6012018Sandreas.sandberg@arm.com{
6112018Sandreas.sandberg@arm.com
6211799Sbrandon.potter@amd.comuint8_t ArmFault::shortDescFaultSources[] = {
6312018Sandreas.sandberg@arm.com    0x01,  // AlignmentFault
6412018Sandreas.sandberg@arm.com    0x04,  // InstructionCacheMaintenance
6512018Sandreas.sandberg@arm.com    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
6612018Sandreas.sandberg@arm.com    0x0c,  // SynchExtAbtOnTranslTableWalkL1
6712018Sandreas.sandberg@arm.com    0x0e,  // SynchExtAbtOnTranslTableWalkL2
6812018Sandreas.sandberg@arm.com    0xff,  // SynchExtAbtOnTranslTableWalkL3 (INVALID)
6911799Sbrandon.potter@amd.com    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
70360SN/A    0x1c,  // SynchPtyErrOnTranslTableWalkL1
71360SN/A    0x1e,  // SynchPtyErrOnTranslTableWalkL2
72360SN/A    0xff,  // SynchPtyErrOnTranslTableWalkL3 (INVALID)
73360SN/A    0xff,  // TranslationL0 (INVALID)
74360SN/A    0x05,  // TranslationL1
75360SN/A    0x07,  // TranslationL2
761809SN/A    0xff,  // TranslationL3 (INVALID)
7711800Sbrandon.potter@amd.com    0xff,  // AccessFlagL0 (INVALID)
7811392Sbrandon.potter@amd.com    0x03,  // AccessFlagL1
791809SN/A    0x06,  // AccessFlagL2
8011392Sbrandon.potter@amd.com    0xff,  // AccessFlagL3 (INVALID)
8113570Sbrandon.potter@amd.com    0xff,  // DomainL0 (INVALID)
8211383Sbrandon.potter@amd.com    0x09,  // DomainL1
8313568Sbrandon.potter@amd.com    0x0b,  // DomainL2
843113Sgblack@eecs.umich.edu    0xff,  // DomainL3 (INVALID)
8511799Sbrandon.potter@amd.com    0xff,  // PermissionL0 (INVALID)
8611759Sbrandon.potter@amd.com    0x0d,  // PermissionL1
8711812Sbaz21@cam.ac.uk    0x0f,  // PermissionL2
8811812Sbaz21@cam.ac.uk    0xff,  // PermissionL3 (INVALID)
8911799Sbrandon.potter@amd.com    0x02,  // DebugEvent
908229Snate@binkert.org    0x08,  // SynchronousExternalAbort
9113570Sbrandon.potter@amd.com    0x10,  // TLBConflictAbort
928229Snate@binkert.org    0x19,  // SynchPtyErrOnMemoryAccess
9311594Santhony.gutierrez@amd.com    0x16,  // AsynchronousExternalAbort
947075Snate@binkert.org    0x18,  // AsynchPtyErrOnMemoryAccess
958229Snate@binkert.org    0xff,  // AddressSizeL0 (INVALID)
9611856Sbrandon.potter@amd.com    0xff,  // AddressSizeL1 (INVALID)
977075Snate@binkert.org    0xff,  // AddressSizeL2 (INVALID)
98360SN/A    0xff,  // AddressSizeL3 (INVALID)
9912461Sgabeblack@google.com    0x40,  // PrefetchTLBMiss
10011886Sbrandon.potter@amd.com    0x80   // PrefetchUncacheable
10111800Sbrandon.potter@amd.com};
10211392Sbrandon.potter@amd.com
10312334Sgabeblack@google.comstatic_assert(sizeof(ArmFault::shortDescFaultSources) ==
1041354SN/A              ArmFault::NumFaultSources,
1056216Snate@binkert.org              "Invalid size of ArmFault::shortDescFaultSources[]");
1066658Snate@binkert.org
1072474SN/Auint8_t ArmFault::longDescFaultSources[] = {
1082680Sktlim@umich.edu    0x21,  // AlignmentFault
1098229Snate@binkert.org    0xff,  // InstructionCacheMaintenance (INVALID)
11011886Sbrandon.potter@amd.com    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
11110496Ssteve.reinhardt@amd.com    0x15,  // SynchExtAbtOnTranslTableWalkL1
11211911SBrandon.Potter@amd.com    0x16,  // SynchExtAbtOnTranslTableWalkL2
1138229Snate@binkert.org    0x17,  // SynchExtAbtOnTranslTableWalkL3
11411794Sbrandon.potter@amd.com    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
11511886Sbrandon.potter@amd.com    0x1d,  // SynchPtyErrOnTranslTableWalkL1
11610497Ssteve.reinhardt@amd.com    0x1e,  // SynchPtyErrOnTranslTableWalkL2
11711794Sbrandon.potter@amd.com    0x1f,  // SynchPtyErrOnTranslTableWalkL3
118360SN/A    0xff,  // TranslationL0 (INVALID)
11913629SAndrea.Mondelli@ucf.edu    0x05,  // TranslationL1
12013629SAndrea.Mondelli@ucf.edu    0x06,  // TranslationL2
12113629SAndrea.Mondelli@ucf.edu    0x07,  // TranslationL3
12213629SAndrea.Mondelli@ucf.edu    0xff,  // AccessFlagL0 (INVALID)
123360SN/A    0x09,  // AccessFlagL1
124360SN/A    0x0a,  // AccessFlagL2
125360SN/A    0x0b,  // AccessFlagL3
126360SN/A    0xff,  // DomainL0 (INVALID)
127360SN/A    0x3d,  // DomainL1
128360SN/A    0x3e,  // DomainL2
129360SN/A    0xff,  // DomainL3 (RESERVED)
130360SN/A    0xff,  // PermissionL0 (INVALID)
131360SN/A    0x0d,  // PermissionL1
132378SN/A    0x0e,  // PermissionL2
1331706SN/A    0x0f,  // PermissionL3
13411851Sbrandon.potter@amd.com    0x22,  // DebugEvent
135378SN/A    0x10,  // SynchronousExternalAbort
136378SN/A    0x30,  // TLBConflictAbort
137378SN/A    0x18,  // SynchPtyErrOnMemoryAccess
138378SN/A    0x11,  // AsynchronousExternalAbort
139378SN/A    0x19,  // AsynchPtyErrOnMemoryAccess
1401706SN/A    0xff,  // AddressSizeL0 (INVALID)
14111851Sbrandon.potter@amd.com    0xff,  // AddressSizeL1 (INVALID)
142360SN/A    0xff,  // AddressSizeL2 (INVALID)
14311760Sbrandon.potter@amd.com    0xff,  // AddressSizeL3 (INVALID)
14411760Sbrandon.potter@amd.com    0x40,  // PrefetchTLBMiss
14511851Sbrandon.potter@amd.com    0x80   // PrefetchUncacheable
14611760Sbrandon.potter@amd.com};
1476109Ssanchezd@stanford.edu
1481706SN/Astatic_assert(sizeof(ArmFault::longDescFaultSources) ==
14911851Sbrandon.potter@amd.com              ArmFault::NumFaultSources,
150378SN/A              "Invalid size of ArmFault::longDescFaultSources[]");
1516109Ssanchezd@stanford.edu
1526109Ssanchezd@stanford.eduuint8_t ArmFault::aarch64FaultSources[] = {
15311851Sbrandon.potter@amd.com    0x21,  // AlignmentFault
1546109Ssanchezd@stanford.edu    0xff,  // InstructionCacheMaintenance (INVALID)
15511886Sbrandon.potter@amd.com    0x14,  // SynchExtAbtOnTranslTableWalkL0
15611886Sbrandon.potter@amd.com    0x15,  // SynchExtAbtOnTranslTableWalkL1
15711886Sbrandon.potter@amd.com    0x16,  // SynchExtAbtOnTranslTableWalkL2
15811886Sbrandon.potter@amd.com    0x17,  // SynchExtAbtOnTranslTableWalkL3
159378SN/A    0x1c,  // SynchPtyErrOnTranslTableWalkL0
1601706SN/A    0x1d,  // SynchPtyErrOnTranslTableWalkL1
16111851Sbrandon.potter@amd.com    0x1e,  // SynchPtyErrOnTranslTableWalkL2
162378SN/A    0x1f,  // SynchPtyErrOnTranslTableWalkL3
1635748SSteve.Reinhardt@amd.com    0x04,  // TranslationL0
1645748SSteve.Reinhardt@amd.com    0x05,  // TranslationL1
16511851Sbrandon.potter@amd.com    0x06,  // TranslationL2
166378SN/A    0x07,  // TranslationL3
167378SN/A    0x08,  // AccessFlagL0
1681706SN/A    0x09,  // AccessFlagL1
16911851Sbrandon.potter@amd.com    0x0a,  // AccessFlagL2
170378SN/A    0x0b,  // AccessFlagL3
171378SN/A    // @todo: Section & Page Domain Fault in AArch64?
1721706SN/A    0xff,  // DomainL0 (INVALID)
17311851Sbrandon.potter@amd.com    0xff,  // DomainL1 (INVALID)
174378SN/A    0xff,  // DomainL2 (INVALID)
1754118Sgblack@eecs.umich.edu    0xff,  // DomainL3 (INVALID)
1764118Sgblack@eecs.umich.edu    0x0c,  // PermissionL0
17711851Sbrandon.potter@amd.com    0x0d,  // PermissionL1
1784118Sgblack@eecs.umich.edu    0x0e,  // PermissionL2
179378SN/A    0x0f,  // PermissionL3
1801706SN/A    0xff,  // DebugEvent (INVALID)
18111851Sbrandon.potter@amd.com    0x10,  // SynchronousExternalAbort
182378SN/A    0x30,  // TLBConflictAbort
18313568Sbrandon.potter@amd.com    0x18,  // SynchPtyErrOnMemoryAccess
18413568Sbrandon.potter@amd.com    0xff,  // AsynchronousExternalAbort (INVALID)
18513568Sbrandon.potter@amd.com    0xff,  // AsynchPtyErrOnMemoryAccess (INVALID)
18613568Sbrandon.potter@amd.com    0x00,  // AddressSizeL0
187378SN/A    0x01,  // AddressSizeL1
1881706SN/A    0x02,  // AddressSizeL2
18911851Sbrandon.potter@amd.com    0x03,  // AddressSizeL3
190360SN/A    0x40,  // PrefetchTLBMiss
1915513SMichael.Adler@intel.com    0x80   // PrefetchUncacheable
1925513SMichael.Adler@intel.com};
19311851Sbrandon.potter@amd.com
1945513SMichael.Adler@intel.comstatic_assert(sizeof(ArmFault::aarch64FaultSources) ==
19510203SAli.Saidi@ARM.com              ArmFault::NumFaultSources,
19610203SAli.Saidi@ARM.com              "Invalid size of ArmFault::aarch64FaultSources[]");
19711851Sbrandon.potter@amd.com
19810203SAli.Saidi@ARM.com// Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode,
1995513SMichael.Adler@intel.com//         {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap,
20011851Sbrandon.potter@amd.com//         {A, F} disable, class, stat
2015513SMichael.Adler@intel.comtemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals = {
202511SN/A    // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED
20310633Smichaelupton@gmail.com    // location in AArch64)
20411851Sbrandon.potter@amd.com    "Reset",                 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
20510633Smichaelupton@gmail.com    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2061706SN/A};
20711851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals = {
208511SN/A    "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
20912795Smattdsinclair@gmail.com    4, 2, 0, 0, true,  false, false, EC_UNKNOWN, FaultStat()
21012795Smattdsinclair@gmail.com};
21112795Smattdsinclair@gmail.comtemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals = {
21212795Smattdsinclair@gmail.com    "Supervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
21312796Smattdsinclair@gmail.com    4, 2, 4, 2, true,  false, false, EC_SVC_TO_HYP, FaultStat()
21412796Smattdsinclair@gmail.com};
21512796Smattdsinclair@gmail.comtemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals = {
21612796Smattdsinclair@gmail.com    "Secure Monitor Call",   0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2175513SMichael.Adler@intel.com    4, 4, 4, 4, false, true,  true,  EC_SMC_TO_HYP, FaultStat()
2185513SMichael.Adler@intel.com};
21911851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals = {
2205513SMichael.Adler@intel.com    "Hypervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
22113031Sbrandon.potter@amd.com    4, 4, 4, 4, true,  false, false, EC_HVC, FaultStat()
22213031Sbrandon.potter@amd.com};
22313031Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals = {
22413031Sbrandon.potter@amd.com    "Prefetch Abort",        0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
22513031Sbrandon.potter@amd.com    4, 4, 0, 0, true,  true,  false, EC_PREFETCH_ABORT_TO_HYP, FaultStat()
22613031Sbrandon.potter@amd.com};
22713031Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals = {
22813031Sbrandon.potter@amd.com    "Data Abort",            0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
22913031Sbrandon.potter@amd.com    8, 8, 0, 0, true,  true,  false, EC_DATA_ABORT_TO_HYP, FaultStat()
23013031Sbrandon.potter@amd.com};
23113031Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals = {
23213031Sbrandon.potter@amd.com    "Virtual Data Abort",    0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
233511SN/A    8, 8, 0, 0, true,  true,  false, EC_INVALID, FaultStat()
2341706SN/A};
23511851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals = {
2361706SN/A    // @todo: double check these values
2371706SN/A    "Hypervisor Trap",       0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2381706SN/A    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
2391706SN/A};
24011851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals = {
2411706SN/A    "IRQ",                   0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2421706SN/A    4, 4, 0, 0, false, true,  false, EC_UNKNOWN, FaultStat()
2431706SN/A};
2441706SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals = {
24511851Sbrandon.potter@amd.com    "Virtual IRQ",           0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2461706SN/A    4, 4, 0, 0, false, true,  false, EC_INVALID, FaultStat()
247511SN/A};
2486703Svince@csl.cornell.edutemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals = {
2496703Svince@csl.cornell.edu    "FIQ",                   0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
25011851Sbrandon.potter@amd.com    4, 4, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2516703Svince@csl.cornell.edu};
2526685Stjones1@inf.ed.ac.uktemplate<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals = {
2536685Stjones1@inf.ed.ac.uk    "Virtual FIQ",           0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
25411851Sbrandon.potter@amd.com    4, 4, 0, 0, false, true,  true,  EC_INVALID, FaultStat()
2556685Stjones1@inf.ed.ac.uk};
2566685Stjones1@inf.ed.ac.uktemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals = {
2575513SMichael.Adler@intel.com    // Some dummy values (SupervisorTrap is AArch64-only)
2585513SMichael.Adler@intel.com    "Supervisor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
25911851Sbrandon.potter@amd.com    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
2605513SMichael.Adler@intel.com};
26111885Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals = {
26211885Sbrandon.potter@amd.com    // Some dummy values (SecureMonitorTrap is AArch64-only)
26311885Sbrandon.potter@amd.com    "Secure Monitor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2645513SMichael.Adler@intel.com    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
2651999SN/A};
2661999SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals = {
26711851Sbrandon.potter@amd.com    // Some dummy values (PCAlignmentFault is AArch64-only)
2681999SN/A    "PC Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
26911885Sbrandon.potter@amd.com    0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT, FaultStat()
27011885Sbrandon.potter@amd.com};
27111885Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals = {
2721999SN/A    // Some dummy values (SPAlignmentFault is AArch64-only)
2731999SN/A    "SP Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2741999SN/A    0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT, FaultStat()
27511851Sbrandon.potter@amd.com};
2761999SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals = {
2773079Sstever@eecs.umich.edu    // Some dummy values (SError is AArch64-only)
2783079Sstever@eecs.umich.edu    "SError",                0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC,
27911851Sbrandon.potter@amd.com    0, 0, 0, 0, false, true,  true,  EC_SERROR, FaultStat()
2803079Sstever@eecs.umich.edu};
28111908SBrandon.Potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<FlushPipe>::vals = {
28211908SBrandon.Potter@amd.com    // Some dummy values
28311908SBrandon.Potter@amd.com    "Pipe Flush",            0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
28411908SBrandon.Potter@amd.com    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
28511875Sbrandon.potter@amd.com};
2862093SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals = {
28711851Sbrandon.potter@amd.com    // Some dummy values
2882093SN/A    "ArmSev Flush",          0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2892687Sksewell@umich.edu    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2902687Sksewell@umich.edu};
29111851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals = {
2922687Sksewell@umich.edu    // Some dummy values (SPAlignmentFault is AArch64-only)
2932238SN/A    "Illegal Inst Set State Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2942238SN/A    0, 0, 0, 0, true, false, false, EC_ILLEGAL_INST, FaultStat()
29511851Sbrandon.potter@amd.com};
2962238SN/A
29711908SBrandon.Potter@amd.comAddr
29811908SBrandon.Potter@amd.comArmFault::getVector(ThreadContext *tc)
29911908SBrandon.Potter@amd.com{
30011908SBrandon.Potter@amd.com    Addr base;
30111908SBrandon.Potter@amd.com
30211908SBrandon.Potter@amd.com    // ARM ARM issue C B1.8.1
30311908SBrandon.Potter@amd.com    bool haveSecurity = ArmSystem::haveSecurity(tc);
30411908SBrandon.Potter@amd.com
3052238SN/A    // panic if SCTLR.VE because I have no idea what to do with vectored
3062238SN/A    // interrupts
30711851Sbrandon.potter@amd.com    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
3082238SN/A    assert(!sctlr.ve);
30913571Sbrandon.potter@amd.com    // Check for invalid modes
31013571Sbrandon.potter@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
31113571Sbrandon.potter@amd.com    assert(haveSecurity                      || cpsr.mode != MODE_MON);
31213571Sbrandon.potter@amd.com    assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
31313568Sbrandon.potter@amd.com
31413568Sbrandon.potter@amd.com    switch (cpsr.mode)
31513568Sbrandon.potter@amd.com    {
31613568Sbrandon.potter@amd.com      case MODE_MON:
31713568Sbrandon.potter@amd.com        base = tc->readMiscReg(MISCREG_MVBAR);
31813568Sbrandon.potter@amd.com        break;
31913568Sbrandon.potter@amd.com      case MODE_HYP:
32013568Sbrandon.potter@amd.com        base = tc->readMiscReg(MISCREG_HVBAR);
32113568Sbrandon.potter@amd.com        break;
32213568Sbrandon.potter@amd.com      default:
32313568Sbrandon.potter@amd.com        if (sctlr.v) {
32413568Sbrandon.potter@amd.com            base = HighVecs;
32513448Sciro.santilli@arm.com        } else {
32613031Sbrandon.potter@amd.com            base = haveSecurity ? tc->readMiscReg(MISCREG_VBAR) : 0;
32713031Sbrandon.potter@amd.com        }
32813031Sbrandon.potter@amd.com        break;
32913448Sciro.santilli@arm.com    }
33013031Sbrandon.potter@amd.com    return base + offset(tc);
33113539Sjavier.setoain@arm.com}
33213539Sjavier.setoain@arm.com
33313539Sjavier.setoain@arm.comAddr
33413539Sjavier.setoain@arm.comArmFault::getVector64(ThreadContext *tc)
33513539Sjavier.setoain@arm.com{
33613539Sjavier.setoain@arm.com    Addr vbar;
33713569Sbrandon.potter@amd.com    switch (toEL) {
33813569Sbrandon.potter@amd.com      case EL3:
33913569Sbrandon.potter@amd.com        assert(ArmSystem::haveSecurity(tc));
34013569Sbrandon.potter@amd.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL3);
34113569Sbrandon.potter@amd.com        break;
34213569Sbrandon.potter@amd.com      case EL2:
34313569Sbrandon.potter@amd.com        assert(ArmSystem::haveVirtualization(tc));
34413569Sbrandon.potter@amd.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
34513569Sbrandon.potter@amd.com        break;
34613569Sbrandon.potter@amd.com      case EL1:
34713569Sbrandon.potter@amd.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL1);
34813569Sbrandon.potter@amd.com        break;
34913569Sbrandon.potter@amd.com      default:
35013569Sbrandon.potter@amd.com        panic("Invalid target exception level");
35113569Sbrandon.potter@amd.com        break;
35213569Sbrandon.potter@amd.com    }
35313031Sbrandon.potter@amd.com    return vbar + offset64();
3542238SN/A}
35511851Sbrandon.potter@amd.com
3562238SN/AMiscRegIndex
3572238SN/AArmFault::getSyndromeReg64() const
3582238SN/A{
35911851Sbrandon.potter@amd.com    switch (toEL) {
3602238SN/A      case EL1:
3612238SN/A        return MISCREG_ESR_EL1;
3622238SN/A      case EL2:
36311851Sbrandon.potter@amd.com        return MISCREG_ESR_EL2;
3642238SN/A      case EL3:
3652238SN/A        return MISCREG_ESR_EL3;
3662238SN/A      default:
36711851Sbrandon.potter@amd.com        panic("Invalid exception level");
3682238SN/A        break;
3692238SN/A    }
3702238SN/A}
37111851Sbrandon.potter@amd.com
3722238SN/AMiscRegIndex
3739455Smitch.hayenga+gem5@gmail.comArmFault::getFaultAddrReg64() const
3749455Smitch.hayenga+gem5@gmail.com{
37511851Sbrandon.potter@amd.com    switch (toEL) {
37610203SAli.Saidi@ARM.com      case EL1:
37711851Sbrandon.potter@amd.com        return MISCREG_FAR_EL1;
37811851Sbrandon.potter@amd.com      case EL2:
3799455Smitch.hayenga+gem5@gmail.com        return MISCREG_FAR_EL2;
38013571Sbrandon.potter@amd.com      case EL3:
38113571Sbrandon.potter@amd.com        return MISCREG_FAR_EL3;
38213571Sbrandon.potter@amd.com      default:
38313571Sbrandon.potter@amd.com        panic("Invalid exception level");
38413571Sbrandon.potter@amd.com        break;
38513571Sbrandon.potter@amd.com    }
38613571Sbrandon.potter@amd.com}
38713571Sbrandon.potter@amd.com
38813571Sbrandon.potter@amd.comvoid
38913571Sbrandon.potter@amd.comArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
39013571Sbrandon.potter@amd.com{
39113571Sbrandon.potter@amd.com    uint32_t value;
3929112Smarc.orr@gmail.com    uint32_t exc_class = (uint32_t) ec(tc);
39311906SBrandon.Potter@amd.com    uint32_t issVal = iss();
39411906SBrandon.Potter@amd.com    assert(!from64 || ArmSystem::highestELIs64(tc));
3959112Smarc.orr@gmail.com
3969112Smarc.orr@gmail.com    value = exc_class << 26;
39711851Sbrandon.potter@amd.com
3989112Smarc.orr@gmail.com    // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24,
3999112Smarc.orr@gmail.com    // 0x25) for which the ISS information is not valid (ARMv7).
40011911SBrandon.Potter@amd.com    // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not
4019112Smarc.orr@gmail.com    // valid it is treated as RES1.
40211911SBrandon.Potter@amd.com    if (to64) {
40311911SBrandon.Potter@amd.com        value |= 1 << 25;
40411911SBrandon.Potter@amd.com    } else if ((bits(exc_class, 5, 3) != 4) ||
40511911SBrandon.Potter@amd.com               (bits(exc_class, 2) && bits(issVal, 24))) {
40613642Sqtt2@cornell.edu        if (!machInst.thumb || machInst.bigThumb)
40713642Sqtt2@cornell.edu            value |= 1 << 25;
40813642Sqtt2@cornell.edu    }
4099112Smarc.orr@gmail.com    // Condition code valid for EC[5:4] nonzero
41011911SBrandon.Potter@amd.com    if (!from64 && ((bits(exc_class, 5, 4) == 0) &&
41111911SBrandon.Potter@amd.com                    (bits(exc_class, 3, 0) != 0))) {
41211911SBrandon.Potter@amd.com        if (!machInst.thumb) {
41311911SBrandon.Potter@amd.com            uint32_t      cond;
4149238Slluc.alvarez@bsc.es            ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode;
41513642Sqtt2@cornell.edu            // If its on unconditional instruction report with a cond code of
4169112Smarc.orr@gmail.com            // 0xE, ie the unconditional code
41711911SBrandon.Potter@amd.com            cond  = (condCode == COND_UC) ? COND_AL : condCode;
4189112Smarc.orr@gmail.com            value |= cond << 20;
41913642Sqtt2@cornell.edu            value |= 1    << 24;
42011911SBrandon.Potter@amd.com        }
42111911SBrandon.Potter@amd.com        value |= bits(issVal, 19, 0);
42211911SBrandon.Potter@amd.com    } else {
42311911SBrandon.Potter@amd.com        value |= issVal;
4249112Smarc.orr@gmail.com    }
42511911SBrandon.Potter@amd.com    tc->setMiscReg(syndrome_reg, value);
42611911SBrandon.Potter@amd.com}
42711911SBrandon.Potter@amd.com
42811911SBrandon.Potter@amd.comvoid
42911911SBrandon.Potter@amd.comArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
43011911SBrandon.Potter@amd.com{
4319112Smarc.orr@gmail.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
4329112Smarc.orr@gmail.com
43313642Sqtt2@cornell.edu    if (ArmSystem::highestELIs64(tc)) {  // ARMv8
43413642Sqtt2@cornell.edu        // Determine source exception level and mode
43513642Sqtt2@cornell.edu        fromMode = (OperatingMode) (uint8_t) cpsr.mode;
43613642Sqtt2@cornell.edu        fromEL = opModeToEL(fromMode);
43713642Sqtt2@cornell.edu        if (opModeIs64(fromMode))
43811911SBrandon.Potter@amd.com            from64 = true;
4399112Smarc.orr@gmail.com
44011911SBrandon.Potter@amd.com        // Determine target exception level
44111911SBrandon.Potter@amd.com        if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc))
44213642Sqtt2@cornell.edu            toEL = EL3;
44313642Sqtt2@cornell.edu        else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc))
44413650Smw828@cornell.edu            toEL = EL2;
44513650Smw828@cornell.edu        else
44613650Smw828@cornell.edu            toEL = opModeToEL(nextMode());
44713650Smw828@cornell.edu        if (fromEL > toEL)
44813650Smw828@cornell.edu            toEL = fromEL;
44913650Smw828@cornell.edu
45013650Smw828@cornell.edu        if (toEL == ArmSystem::highestEL(tc) || ELIs64(tc, toEL)) {
45113650Smw828@cornell.edu            // Invoke exception handler in AArch64 state
45213650Smw828@cornell.edu            to64 = true;
45313650Smw828@cornell.edu            invoke64(tc, inst);
45413650Smw828@cornell.edu            return;
45513650Smw828@cornell.edu        }
45613650Smw828@cornell.edu    }
45713650Smw828@cornell.edu
45813651Smw828@cornell.edu    // ARMv7 (ARM ARM issue C B1.9)
45913651Smw828@cornell.edu
46013651Smw828@cornell.edu    bool have_security       = ArmSystem::haveSecurity(tc);
46113651Smw828@cornell.edu    bool have_virtualization = ArmSystem::haveVirtualization(tc);
46213651Smw828@cornell.edu
46313651Smw828@cornell.edu    FaultBase::invoke(tc);
46413651Smw828@cornell.edu    if (!FullSystem)
46513651Smw828@cornell.edu        return;
46613651Smw828@cornell.edu    countStat()++;
46713651Smw828@cornell.edu
46813651Smw828@cornell.edu    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
46913651Smw828@cornell.edu    SCR scr = tc->readMiscReg(MISCREG_SCR);
47013651Smw828@cornell.edu    CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR);
47113651Smw828@cornell.edu    saved_cpsr.nz = tc->readCCReg(CCREG_NZ);
47213651Smw828@cornell.edu    saved_cpsr.c = tc->readCCReg(CCREG_C);
47313651Smw828@cornell.edu    saved_cpsr.v = tc->readCCReg(CCREG_V);
47413651Smw828@cornell.edu    saved_cpsr.ge = tc->readCCReg(CCREG_GE);
47513651Smw828@cornell.edu
47613651Smw828@cornell.edu    Addr curPc M5_VAR_USED = tc->pcState().pc();
47713651Smw828@cornell.edu    ITSTATE it = tc->pcState().itstate();
47813651Smw828@cornell.edu    saved_cpsr.it2 = it.top6;
47913651Smw828@cornell.edu    saved_cpsr.it1 = it.bottom2;
48013651Smw828@cornell.edu
48113651Smw828@cornell.edu    // if we have a valid instruction then use it to annotate this fault with
48213651Smw828@cornell.edu    // extra information. This is used to generate the correct fault syndrome
48313651Smw828@cornell.edu    // information
48413651Smw828@cornell.edu    if (inst) {
48513651Smw828@cornell.edu        ArmStaticInst *armInst = reinterpret_cast<ArmStaticInst *>(inst.get());
48613651Smw828@cornell.edu        armInst->annotateFault(this);
48713651Smw828@cornell.edu    }
48813651Smw828@cornell.edu
48913651Smw828@cornell.edu    if (have_security && routeToMonitor(tc))
49013651Smw828@cornell.edu        cpsr.mode = MODE_MON;
49113651Smw828@cornell.edu    else if (have_virtualization && routeToHyp(tc))
49213651Smw828@cornell.edu        cpsr.mode = MODE_HYP;
49313651Smw828@cornell.edu    else
49413651Smw828@cornell.edu        cpsr.mode = nextMode();
49513651Smw828@cornell.edu
49613651Smw828@cornell.edu    // Ensure Secure state if initially in Monitor mode
49713651Smw828@cornell.edu    if (have_security && saved_cpsr.mode == MODE_MON) {
49813651Smw828@cornell.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
49913651Smw828@cornell.edu        if (scr.ns) {
50013651Smw828@cornell.edu            scr.ns = 0;
50113651Smw828@cornell.edu            tc->setMiscRegNoEffect(MISCREG_SCR, scr);
50213651Smw828@cornell.edu        }
50313651Smw828@cornell.edu    }
50413651Smw828@cornell.edu
50513651Smw828@cornell.edu    // some bits are set differently if we have been routed to hyp mode
50613651Smw828@cornell.edu    if (cpsr.mode == MODE_HYP) {
50713651Smw828@cornell.edu        SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR);
50813651Smw828@cornell.edu        cpsr.t = hsctlr.te;
50913651Smw828@cornell.edu        cpsr.e = hsctlr.ee;
51013651Smw828@cornell.edu        if (!scr.ea)  {cpsr.a = 1;}
51113651Smw828@cornell.edu        if (!scr.fiq) {cpsr.f = 1;}
51213651Smw828@cornell.edu        if (!scr.irq) {cpsr.i = 1;}
51313651Smw828@cornell.edu    } else if (cpsr.mode == MODE_MON) {
51413651Smw828@cornell.edu        // Special case handling when entering monitor mode
51513651Smw828@cornell.edu        cpsr.t = sctlr.te;
51613651Smw828@cornell.edu        cpsr.e = sctlr.ee;
51713651Smw828@cornell.edu        cpsr.a = 1;
51813651Smw828@cornell.edu        cpsr.f = 1;
51913651Smw828@cornell.edu        cpsr.i = 1;
52013651Smw828@cornell.edu    } else {
52113651Smw828@cornell.edu        cpsr.t = sctlr.te;
52213651Smw828@cornell.edu        cpsr.e = sctlr.ee;
52313651Smw828@cornell.edu
52413651Smw828@cornell.edu        // The *Disable functions are virtual and different per fault
52513651Smw828@cornell.edu        cpsr.a = cpsr.a | abortDisable(tc);
52613651Smw828@cornell.edu        cpsr.f = cpsr.f | fiqDisable(tc);
52713651Smw828@cornell.edu        cpsr.i = 1;
52813651Smw828@cornell.edu    }
5299112Smarc.orr@gmail.com    cpsr.it1 = cpsr.it2 = 0;
53011911SBrandon.Potter@amd.com    cpsr.j = 0;
53111911SBrandon.Potter@amd.com    tc->setMiscReg(MISCREG_CPSR, cpsr);
5329112Smarc.orr@gmail.com
5339112Smarc.orr@gmail.com    // Make sure mailbox sets to one always
5342238SN/A    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
5352238SN/A
5362238SN/A    // Clear the exclusive monitor
5372238SN/A    tc->setMiscReg(MISCREG_LOCKFLAG, 0);
53811851Sbrandon.potter@amd.com
5392238SN/A    if (cpsr.mode == MODE_HYP) {
5402238SN/A        tc->setMiscReg(MISCREG_ELR_HYP, curPc +
5412238SN/A                (saved_cpsr.t ? thumbPcOffset(true)  : armPcOffset(true)));
54211851Sbrandon.potter@amd.com    } else {
5432238SN/A        tc->setIntReg(INTREG_LR, curPc +
5442238SN/A                (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false)));
5452238SN/A    }
54611851Sbrandon.potter@amd.com
5472238SN/A    switch (cpsr.mode) {
5482238SN/A      case MODE_FIQ:
5492238SN/A        tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
55011851Sbrandon.potter@amd.com        break;
5512238SN/A      case MODE_IRQ:
5522238SN/A        tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
5531354SN/A        break;
5541354SN/A      case MODE_SVC:
55510796Sbrandon.potter@amd.com        tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
55610796Sbrandon.potter@amd.com        break;
5571354SN/A      case MODE_MON:
5581354SN/A        assert(have_security);
5591354SN/A        tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr);
5601354SN/A        break;
5611354SN/A      case MODE_ABORT:
5621354SN/A        tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
5631354SN/A        break;
5641354SN/A      case MODE_UNDEFINED:
5651354SN/A        tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
5661354SN/A        if (ec(tc) != EC_UNKNOWN)
56710796Sbrandon.potter@amd.com            setSyndrome(tc, MISCREG_HSR);
5681354SN/A        break;
56910796Sbrandon.potter@amd.com      case MODE_HYP:
5701354SN/A        assert(have_virtualization);
5711354SN/A        tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr);
5721354SN/A        setSyndrome(tc, MISCREG_HSR);
5731354SN/A        break;
57410796Sbrandon.potter@amd.com      default:
57510796Sbrandon.potter@amd.com        panic("unknown Mode\n");
57610796Sbrandon.potter@amd.com    }
57710796Sbrandon.potter@amd.com
57810796Sbrandon.potter@amd.com    Addr newPc = getVector(tc);
57910796Sbrandon.potter@amd.com    DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n",
58010796Sbrandon.potter@amd.com            name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc);
58110796Sbrandon.potter@amd.com    PCState pc(newPc);
58210796Sbrandon.potter@amd.com    pc.thumb(cpsr.t);
58310796Sbrandon.potter@amd.com    pc.nextThumb(pc.thumb());
58410796Sbrandon.potter@amd.com    pc.jazelle(cpsr.j);
585360SN/A    pc.nextJazelle(pc.jazelle());
586360SN/A    pc.aarch64(!cpsr.width);
587360SN/A    pc.nextAArch64(!cpsr.width);
588360SN/A    tc->pcState(pc);
589360SN/A}
590360SN/A
591360SN/Avoid
59211759Sbrandon.potter@amd.comArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
5933113Sgblack@eecs.umich.edu{
5943113Sgblack@eecs.umich.edu    // Determine actual misc. register indices for ELR_ELx and SPSR_ELx
5953113Sgblack@eecs.umich.edu    MiscRegIndex elr_idx, spsr_idx;
5963113Sgblack@eecs.umich.edu    switch (toEL) {
5973113Sgblack@eecs.umich.edu      case EL1:
5983113Sgblack@eecs.umich.edu        elr_idx = MISCREG_ELR_EL1;
5993113Sgblack@eecs.umich.edu        spsr_idx = MISCREG_SPSR_EL1;
6003113Sgblack@eecs.umich.edu        break;
6013113Sgblack@eecs.umich.edu      case EL2:
6023113Sgblack@eecs.umich.edu        assert(ArmSystem::haveVirtualization(tc));
6033113Sgblack@eecs.umich.edu        elr_idx = MISCREG_ELR_EL2;
6043113Sgblack@eecs.umich.edu        spsr_idx = MISCREG_SPSR_EL2;
6053113Sgblack@eecs.umich.edu        break;
60612032Sandreas.sandberg@arm.com      case EL3:
6073113Sgblack@eecs.umich.edu        assert(ArmSystem::haveSecurity(tc));
6083113Sgblack@eecs.umich.edu        elr_idx = MISCREG_ELR_EL3;
6094189Sgblack@eecs.umich.edu        spsr_idx = MISCREG_SPSR_EL3;
6104189Sgblack@eecs.umich.edu        break;
6113113Sgblack@eecs.umich.edu      default:
6123113Sgblack@eecs.umich.edu        panic("Invalid target exception level");
6133113Sgblack@eecs.umich.edu        break;
6143113Sgblack@eecs.umich.edu    }
6158737Skoansin.tan@gmail.com
6163113Sgblack@eecs.umich.edu    // Save process state into SPSR_ELx
6178737Skoansin.tan@gmail.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
6183277Sgblack@eecs.umich.edu    CPSR spsr = cpsr;
6195515SMichael.Adler@intel.com    spsr.nz = tc->readCCReg(CCREG_NZ);
6205515SMichael.Adler@intel.com    spsr.c = tc->readCCReg(CCREG_C);
6215515SMichael.Adler@intel.com    spsr.v = tc->readCCReg(CCREG_V);
6225515SMichael.Adler@intel.com    if (from64) {
6235515SMichael.Adler@intel.com        // Force some bitfields to 0
6248737Skoansin.tan@gmail.com        spsr.q = 0;
6253277Sgblack@eecs.umich.edu        spsr.it1 = 0;
6268737Skoansin.tan@gmail.com        spsr.j = 0;
6273277Sgblack@eecs.umich.edu        spsr.res0_23_22 = 0;
6288737Skoansin.tan@gmail.com        spsr.ge = 0;
6293277Sgblack@eecs.umich.edu        spsr.it2 = 0;
6308737Skoansin.tan@gmail.com        spsr.t = 0;
6313113Sgblack@eecs.umich.edu    } else {
6323113Sgblack@eecs.umich.edu        spsr.ge = tc->readCCReg(CCREG_GE);
6333113Sgblack@eecs.umich.edu        ITSTATE it = tc->pcState().itstate();
6343113Sgblack@eecs.umich.edu        spsr.it2 = it.top6;
6358737Skoansin.tan@gmail.com        spsr.it1 = it.bottom2;
6363113Sgblack@eecs.umich.edu        // Force some bitfields to 0
6378737Skoansin.tan@gmail.com        spsr.res0_23_22 = 0;
6383114Sgblack@eecs.umich.edu        spsr.ss = 0;
6398737Skoansin.tan@gmail.com    }
6403114Sgblack@eecs.umich.edu    tc->setMiscReg(spsr_idx, spsr);
6418737Skoansin.tan@gmail.com
6423114Sgblack@eecs.umich.edu    // Save preferred return address into ELR_ELx
6438737Skoansin.tan@gmail.com    Addr curr_pc = tc->pcState().pc();
64411906SBrandon.Potter@amd.com    Addr ret_addr = curr_pc;
6454061Sgblack@eecs.umich.edu    if (from64)
6464061Sgblack@eecs.umich.edu        ret_addr += armPcElrOffset();
6478737Skoansin.tan@gmail.com    else
6483113Sgblack@eecs.umich.edu        ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset();
6498737Skoansin.tan@gmail.com    tc->setMiscReg(elr_idx, ret_addr);
6503113Sgblack@eecs.umich.edu
6513113Sgblack@eecs.umich.edu    // Update process state
6523113Sgblack@eecs.umich.edu    OperatingMode64 mode = 0;
6533113Sgblack@eecs.umich.edu    mode.spX = 1;
6543113Sgblack@eecs.umich.edu    mode.el = toEL;
65512032Sandreas.sandberg@arm.com    mode.width = 0;
6563113Sgblack@eecs.umich.edu    cpsr.mode = mode;
6573113Sgblack@eecs.umich.edu    cpsr.daif = 0xf;
6584189Sgblack@eecs.umich.edu    cpsr.il = 0;
6594189Sgblack@eecs.umich.edu    cpsr.ss = 0;
6603113Sgblack@eecs.umich.edu    tc->setMiscReg(MISCREG_CPSR, cpsr);
6613113Sgblack@eecs.umich.edu
6623113Sgblack@eecs.umich.edu    // Set PC to start of exception handler
6638737Skoansin.tan@gmail.com    Addr new_pc = purifyTaggedAddr(getVector64(tc), tc, toEL);
6643113Sgblack@eecs.umich.edu    DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x "
6658737Skoansin.tan@gmail.com            "elr:%#x newVec: %#x\n", name(), cpsr, curr_pc, ret_addr, new_pc);
6663113Sgblack@eecs.umich.edu    PCState pc(new_pc);
6678737Skoansin.tan@gmail.com    pc.aarch64(!cpsr.width);
6683113Sgblack@eecs.umich.edu    pc.nextAArch64(!cpsr.width);
6693113Sgblack@eecs.umich.edu    tc->pcState(pc);
6703113Sgblack@eecs.umich.edu
6713113Sgblack@eecs.umich.edu    // If we have a valid instruction then use it to annotate this fault with
6723113Sgblack@eecs.umich.edu    // extra information. This is used to generate the correct fault syndrome
6733113Sgblack@eecs.umich.edu    // information
6743113Sgblack@eecs.umich.edu    if (inst)
67511906SBrandon.Potter@amd.com        reinterpret_cast<ArmStaticInst *>(inst.get())->annotateFault(this);
6763113Sgblack@eecs.umich.edu    // Save exception syndrome
67712032Sandreas.sandberg@arm.com    if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ))
6788852Sandreas.hansson@arm.com        setSyndrome(tc, getSyndromeReg64());
67911906SBrandon.Potter@amd.com}
6803113Sgblack@eecs.umich.edu
6813113Sgblack@eecs.umich.eduvoid
6823113Sgblack@eecs.umich.eduReset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
6833113Sgblack@eecs.umich.edu{
6843113Sgblack@eecs.umich.edu    if (FullSystem) {
6853113Sgblack@eecs.umich.edu        tc->getCpuPtr()->clearInterrupts(tc->threadId());
6863113Sgblack@eecs.umich.edu        tc->clearArchRegs();
6873113Sgblack@eecs.umich.edu    }
68812032Sandreas.sandberg@arm.com    if (!ArmSystem::highestELIs64(tc)) {
6898852Sandreas.hansson@arm.com        ArmFault::invoke(tc, inst);
69011906SBrandon.Potter@amd.com        tc->setMiscReg(MISCREG_VMPIDR,
6913113Sgblack@eecs.umich.edu                       getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc));
6923113Sgblack@eecs.umich.edu
6933113Sgblack@eecs.umich.edu        // Unless we have SMC code to get us there, boot in HYP!
6946686Stjones1@inf.ed.ac.uk        if (ArmSystem::haveVirtualization(tc) &&
6953113Sgblack@eecs.umich.edu            !ArmSystem::haveSecurity(tc)) {
6963113Sgblack@eecs.umich.edu            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
6973113Sgblack@eecs.umich.edu            cpsr.mode = MODE_HYP;
69811759Sbrandon.potter@amd.com            tc->setMiscReg(MISCREG_CPSR, cpsr);
69912032Sandreas.sandberg@arm.com        }
70011759Sbrandon.potter@amd.com    } else {
70111759Sbrandon.potter@amd.com        // Advance the PC to the IMPLEMENTATION DEFINED reset value
70211759Sbrandon.potter@amd.com        PCState pc = ArmSystem::resetAddr64(tc);
70311759Sbrandon.potter@amd.com        pc.aarch64(true);
70411759Sbrandon.potter@amd.com        pc.nextAArch64(true);
70511812Sbaz21@cam.ac.uk        tc->pcState(pc);
70611812Sbaz21@cam.ac.uk    }
70711812Sbaz21@cam.ac.uk}
70811759Sbrandon.potter@amd.com
70911812Sbaz21@cam.ac.ukvoid
71011759Sbrandon.potter@amd.comUndefinedInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
71111759Sbrandon.potter@amd.com{
71211759Sbrandon.potter@amd.com    if (FullSystem) {
71311759Sbrandon.potter@amd.com        ArmFault::invoke(tc, inst);
71411759Sbrandon.potter@amd.com        return;
71511759Sbrandon.potter@amd.com    }
71611759Sbrandon.potter@amd.com
71711812Sbaz21@cam.ac.uk    // If the mnemonic isn't defined this has to be an unknown instruction.
71811812Sbaz21@cam.ac.uk    assert(unknown || mnemonic != NULL);
71911812Sbaz21@cam.ac.uk    if (disabled) {
72011812Sbaz21@cam.ac.uk        panic("Attempted to execute disabled instruction "
72111812Sbaz21@cam.ac.uk                "'%s' (inst 0x%08x)", mnemonic, machInst);
72211812Sbaz21@cam.ac.uk    } else if (unknown) {
72311812Sbaz21@cam.ac.uk        panic("Attempted to execute unknown instruction (inst 0x%08x)",
72411759Sbrandon.potter@amd.com              machInst);
72511759Sbrandon.potter@amd.com    } else {
72611812Sbaz21@cam.ac.uk        panic("Attempted to execute unimplemented instruction "
72711812Sbaz21@cam.ac.uk                "'%s' (inst 0x%08x)", mnemonic, machInst);
72811759Sbrandon.potter@amd.com    }
72911812Sbaz21@cam.ac.uk}
73011812Sbaz21@cam.ac.uk
73111812Sbaz21@cam.ac.ukbool
73211812Sbaz21@cam.ac.ukUndefinedInstruction::routeToHyp(ThreadContext *tc) const
73311812Sbaz21@cam.ac.uk{
73411812Sbaz21@cam.ac.uk    bool toHyp;
73511812Sbaz21@cam.ac.uk
73611759Sbrandon.potter@amd.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
73711759Sbrandon.potter@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
73811759Sbrandon.potter@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
73911759Sbrandon.potter@amd.com
740378SN/A    // if in Hyp mode then stay in Hyp mode
741378SN/A    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
7429141Smarc.orr@gmail.com    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
7439141Smarc.orr@gmail.com    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
744360SN/A    return toHyp;
7451450SN/A}
74611856Sbrandon.potter@amd.com
747360SN/Auint32_t
7486701Sgblack@eecs.umich.eduUndefinedInstruction::iss() const
74911856Sbrandon.potter@amd.com{
75011856Sbrandon.potter@amd.com    if (overrideEc == EC_INVALID)
751360SN/A        return issRaw;
75210930Sbrandon.potter@amd.com
753360SN/A    uint32_t new_iss = 0;
75411856Sbrandon.potter@amd.com    uint32_t op0, op1, op2, CRn, CRm, Rt, dir;
75511856Sbrandon.potter@amd.com
75610496Ssteve.reinhardt@amd.com    dir = bits(machInst, 21, 21);
75711856Sbrandon.potter@amd.com    op0 = bits(machInst, 20, 19);
75811856Sbrandon.potter@amd.com    op1 = bits(machInst, 18, 16);
7591458SN/A    CRn = bits(machInst, 15, 12);
760360SN/A    CRm = bits(machInst, 11, 8);
76111856Sbrandon.potter@amd.com    op2 = bits(machInst, 7, 5);
76211856Sbrandon.potter@amd.com    Rt = bits(machInst, 4, 0);
76311856Sbrandon.potter@amd.com
76411856Sbrandon.potter@amd.com    new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 |
76511856Sbrandon.potter@amd.com            Rt << 5 | CRm << 1 | dir;
76611856Sbrandon.potter@amd.com
76711856Sbrandon.potter@amd.com    return new_iss;
76811856Sbrandon.potter@amd.com}
76910496Ssteve.reinhardt@amd.com
77011856Sbrandon.potter@amd.comvoid
77111856Sbrandon.potter@amd.comSupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
77211856Sbrandon.potter@amd.com{
77311856Sbrandon.potter@amd.com    if (FullSystem) {
77411856Sbrandon.potter@amd.com        ArmFault::invoke(tc, inst);
77510930Sbrandon.potter@amd.com        return;
7769141Smarc.orr@gmail.com    }
777360SN/A
778360SN/A    // As of now, there isn't a 32 bit thumb version of this instruction.
779360SN/A    assert(!machInst.bigThumb);
78011907SBrandon.Potter@amd.com    uint32_t callNum;
78111907SBrandon.Potter@amd.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
78211907SBrandon.Potter@amd.com    OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
783360SN/A    if (opModeIs64(mode))
78411907SBrandon.Potter@amd.com        callNum = tc->readIntReg(INTREG_X8);
78511907SBrandon.Potter@amd.com    else
78611907SBrandon.Potter@amd.com        callNum = tc->readIntReg(INTREG_R7);
78711907SBrandon.Potter@amd.com    tc->syscall(callNum);
78811907SBrandon.Potter@amd.com
78911907SBrandon.Potter@amd.com    // Advance the PC since that won't happen automatically.
79011907SBrandon.Potter@amd.com    PCState pc = tc->pcState();
79111907SBrandon.Potter@amd.com    assert(inst);
79211907SBrandon.Potter@amd.com    inst->advancePC(pc);
79311907SBrandon.Potter@amd.com    tc->pcState(pc);
79411907SBrandon.Potter@amd.com}
79511907SBrandon.Potter@amd.com
79611907SBrandon.Potter@amd.combool
79711907SBrandon.Potter@amd.comSupervisorCall::routeToHyp(ThreadContext *tc) const
798360SN/A{
79911907SBrandon.Potter@amd.com    bool toHyp;
8001458SN/A
801360SN/A    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
80211907SBrandon.Potter@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
80311907SBrandon.Potter@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
80411907SBrandon.Potter@amd.com
80511907SBrandon.Potter@amd.com    // if in Hyp mode then stay in Hyp mode
80611907SBrandon.Potter@amd.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
80711907SBrandon.Potter@amd.com    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
80811907SBrandon.Potter@amd.com    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
80911907SBrandon.Potter@amd.com    return toHyp;
81011907SBrandon.Potter@amd.com}
81111907SBrandon.Potter@amd.com
812360SN/AExceptionClass
81311907SBrandon.Potter@amd.comSupervisorCall::ec(ThreadContext *tc) const
81411907SBrandon.Potter@amd.com{
81511907SBrandon.Potter@amd.com    return (overrideEc != EC_INVALID) ? overrideEc :
816360SN/A        (from64 ? EC_SVC_64 : vals.ec);
817360SN/A}
81811907SBrandon.Potter@amd.com
81911907SBrandon.Potter@amd.comuint32_t
82011907SBrandon.Potter@amd.comSupervisorCall::iss() const
82111907SBrandon.Potter@amd.com{
822360SN/A    // Even if we have a 24 bit imm from an arm32 instruction then we only use
82311907SBrandon.Potter@amd.com    // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC).
824360SN/A    return issRaw & 0xFFFF;
825360SN/A}
82611907SBrandon.Potter@amd.com
8273669Sbinkertn@umich.eduuint32_t
82811907SBrandon.Potter@amd.comSecureMonitorCall::iss() const
82911907SBrandon.Potter@amd.com{
83011907SBrandon.Potter@amd.com    if (from64)
83111907SBrandon.Potter@amd.com        return bits(machInst, 20, 5);
83211907SBrandon.Potter@amd.com    return 0;
83311907SBrandon.Potter@amd.com}
83411907SBrandon.Potter@amd.com
83511907SBrandon.Potter@amd.comExceptionClass
83611907SBrandon.Potter@amd.comUndefinedInstruction::ec(ThreadContext *tc) const
83711907SBrandon.Potter@amd.com{
83811907SBrandon.Potter@amd.com    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
83911907SBrandon.Potter@amd.com}
84011907SBrandon.Potter@amd.com
84111907SBrandon.Potter@amd.com
84211907SBrandon.Potter@amd.comHypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) :
84311907SBrandon.Potter@amd.com        ArmFaultVals<HypervisorCall>(_machInst, _imm)
84411907SBrandon.Potter@amd.com{}
84511907SBrandon.Potter@amd.com
84611907SBrandon.Potter@amd.comExceptionClass
84713371Sciro.santilli@arm.comHypervisorCall::ec(ThreadContext *tc) const
84811907SBrandon.Potter@amd.com{
8491706SN/A    return from64 ? EC_HVC_64 : vals.ec;
85011907SBrandon.Potter@amd.com}
85111907SBrandon.Potter@amd.com
85211907SBrandon.Potter@amd.comExceptionClass
85311907SBrandon.Potter@amd.comHypervisorTrap::ec(ThreadContext *tc) const
85411907SBrandon.Potter@amd.com{
85511907SBrandon.Potter@amd.com    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
85610496Ssteve.reinhardt@amd.com}
85710496Ssteve.reinhardt@amd.com
85811907SBrandon.Potter@amd.comtemplate<class T>
85911907SBrandon.Potter@amd.comFaultOffset
86011907SBrandon.Potter@amd.comArmFaultVals<T>::offset(ThreadContext *tc)
86111907SBrandon.Potter@amd.com{
86211907SBrandon.Potter@amd.com    bool isHypTrap = false;
86311907SBrandon.Potter@amd.com
86410496Ssteve.reinhardt@amd.com    // Normally we just use the exception vector from the table at the top if
86511907SBrandon.Potter@amd.com    // this file, however if this exception has caused a transition to hype
86611907SBrandon.Potter@amd.com    // mode, and its an exception type that would only do this if it has been
86711907SBrandon.Potter@amd.com    // trapped then we use the hyp trap vector instead of the normal vector
86811907SBrandon.Potter@amd.com    if (vals.hypTrappable) {
86910496Ssteve.reinhardt@amd.com        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
87010496Ssteve.reinhardt@amd.com        if (cpsr.mode == MODE_HYP) {
87111907SBrandon.Potter@amd.com            CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
87211907SBrandon.Potter@amd.com            isHypTrap = spsr.mode != MODE_HYP;
87311907SBrandon.Potter@amd.com        }
87411907SBrandon.Potter@amd.com    }
87511907SBrandon.Potter@amd.com    return isHypTrap ? 0x14 : vals.offset;
87611907SBrandon.Potter@amd.com}
87711907SBrandon.Potter@amd.com
87811907SBrandon.Potter@amd.com// void
87911907SBrandon.Potter@amd.com// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx)
88011907SBrandon.Potter@amd.com// {
88111907SBrandon.Potter@amd.com//     ESR esr = 0;
88211907SBrandon.Potter@amd.com//     esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32;
88311907SBrandon.Potter@amd.com//     esr.il = !machInst.thumb;
88411907SBrandon.Potter@amd.com//     if (machInst.aarch64)
88511907SBrandon.Potter@amd.com//         esr.imm16 = bits(machInst.instBits, 20, 5);
88611907SBrandon.Potter@amd.com//     else if (machInst.thumb)
88711907SBrandon.Potter@amd.com//         esr.imm16 = bits(machInst.instBits, 7, 0);
88811907SBrandon.Potter@amd.com//     else
88911907SBrandon.Potter@amd.com//         esr.imm16 = bits(machInst.instBits, 15, 0);
89011907SBrandon.Potter@amd.com//     tc->setMiscReg(esr_idx, esr);
89111907SBrandon.Potter@amd.com// }
89211907SBrandon.Potter@amd.com
89311907SBrandon.Potter@amd.comvoid
89411907SBrandon.Potter@amd.comSecureMonitorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
89511907SBrandon.Potter@amd.com{
896360SN/A    if (FullSystem) {
89711907SBrandon.Potter@amd.com        ArmFault::invoke(tc, inst);
89811907SBrandon.Potter@amd.com        return;
89911907SBrandon.Potter@amd.com    }
90011907SBrandon.Potter@amd.com}
90111907SBrandon.Potter@amd.com
90211907SBrandon.Potter@amd.comExceptionClass
90311907SBrandon.Potter@amd.comSecureMonitorCall::ec(ThreadContext *tc) const
90411907SBrandon.Potter@amd.com{
90511907SBrandon.Potter@amd.com    return (from64 ? EC_SMC_64 : vals.ec);
90611907SBrandon.Potter@amd.com}
90711907SBrandon.Potter@amd.com
90811907SBrandon.Potter@amd.comExceptionClass
90911907SBrandon.Potter@amd.comSupervisorTrap::ec(ThreadContext *tc) const
910360SN/A{
911360SN/A    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
91210027SChris.Adeniyi-Jones@arm.com}
91310027SChris.Adeniyi-Jones@arm.com
91410027SChris.Adeniyi-Jones@arm.comExceptionClass
91511851Sbrandon.potter@amd.comSecureMonitorTrap::ec(ThreadContext *tc) const
91610027SChris.Adeniyi-Jones@arm.com{
91710027SChris.Adeniyi-Jones@arm.com    return (overrideEc != EC_INVALID) ? overrideEc :
91811907SBrandon.Potter@amd.com        (from64 ? EC_SMC_64 : vals.ec);
91910027SChris.Adeniyi-Jones@arm.com}
92010027SChris.Adeniyi-Jones@arm.com
92110027SChris.Adeniyi-Jones@arm.comtemplate<class T>
92210027SChris.Adeniyi-Jones@arm.comvoid
92310027SChris.Adeniyi-Jones@arm.comAbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
92411851Sbrandon.potter@amd.com{
92511851Sbrandon.potter@amd.com    if (tranMethod == ArmFault::UnknownTran) {
92610027SChris.Adeniyi-Jones@arm.com        tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran
92711907SBrandon.Potter@amd.com                                             : ArmFault::VmsaTran;
92810027SChris.Adeniyi-Jones@arm.com
92910027SChris.Adeniyi-Jones@arm.com        if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) {
93010633Smichaelupton@gmail.com            // See ARM ARM B3-1416
93110633Smichaelupton@gmail.com            bool override_LPAE = false;
93210633Smichaelupton@gmail.com            TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S);
93311851Sbrandon.potter@amd.com            TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS);
93410633Smichaelupton@gmail.com            if (ttbcr_s.eae) {
93510633Smichaelupton@gmail.com                override_LPAE = true;
93610633Smichaelupton@gmail.com            } else {
93710633Smichaelupton@gmail.com                // Unimplemented code option, not seen in testing.  May need
93810633Smichaelupton@gmail.com                // extension according to the manual exceprt above.
93910633Smichaelupton@gmail.com                DPRINTF(Faults, "Warning: Incomplete translation method "
94010633Smichaelupton@gmail.com                        "override detected.\n");
94110633Smichaelupton@gmail.com            }
94210633Smichaelupton@gmail.com            if (override_LPAE)
94310633Smichaelupton@gmail.com                tranMethod = ArmFault::LpaeTran;
94410203SAli.Saidi@ARM.com        }
94510203SAli.Saidi@ARM.com    }
94610203SAli.Saidi@ARM.com
94711851Sbrandon.potter@amd.com    if (source == ArmFault::AsynchronousExternalAbort) {
94811851Sbrandon.potter@amd.com        tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
94910203SAli.Saidi@ARM.com    }
95010203SAli.Saidi@ARM.com    // Get effective fault source encoding
95110203SAli.Saidi@ARM.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
95210203SAli.Saidi@ARM.com    FSR  fsr  = getFsr(tc);
95310203SAli.Saidi@ARM.com
95410203SAli.Saidi@ARM.com    // source must be determined BEFORE invoking generic routines which will
95510203SAli.Saidi@ARM.com    // try to set hsr etc. and are based upon source!
95610203SAli.Saidi@ARM.com    ArmFaultVals<T>::invoke(tc, inst);
95710203SAli.Saidi@ARM.com
95810203SAli.Saidi@ARM.com    if (!this->to64) {  // AArch32
95910203SAli.Saidi@ARM.com        if (cpsr.mode == MODE_HYP) {
96011851Sbrandon.potter@amd.com            tc->setMiscReg(T::HFarIndex, faultAddr);
96111851Sbrandon.potter@amd.com        } else if (stage2) {
96210203SAli.Saidi@ARM.com            tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf);
96310203SAli.Saidi@ARM.com            tc->setMiscReg(T::HFarIndex,  OVAddr);
96410203SAli.Saidi@ARM.com        } else {
96510203SAli.Saidi@ARM.com            tc->setMiscReg(T::FsrIndex, fsr);
96610203SAli.Saidi@ARM.com            tc->setMiscReg(T::FarIndex, faultAddr);
96710203SAli.Saidi@ARM.com        }
96810203SAli.Saidi@ARM.com        DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\
96910203SAli.Saidi@ARM.com                "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod);
97010850SGiacomo.Gabrielli@arm.com    } else {  // AArch64
97110850SGiacomo.Gabrielli@arm.com        // Set the FAR register.  Nothing else to do if we are in AArch64 state
97210850SGiacomo.Gabrielli@arm.com        // because the syndrome register has already been set inside invoke64()
97311851Sbrandon.potter@amd.com        if (stage2) {
97410850SGiacomo.Gabrielli@arm.com            // stage 2 fault, set HPFAR_EL2 to the faulting IPA
97510850SGiacomo.Gabrielli@arm.com            // and FAR_EL2 to the Original VA
97610850SGiacomo.Gabrielli@arm.com            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr);
97710850SGiacomo.Gabrielli@arm.com            tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
97810850SGiacomo.Gabrielli@arm.com
97910850SGiacomo.Gabrielli@arm.com            DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
98010850SGiacomo.Gabrielli@arm.com                    OVAddr, faultAddr);
98110850SGiacomo.Gabrielli@arm.com        } else {
98210850SGiacomo.Gabrielli@arm.com            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
98310850SGiacomo.Gabrielli@arm.com        }
98410850SGiacomo.Gabrielli@arm.com    }
98510850SGiacomo.Gabrielli@arm.com}
98610850SGiacomo.Gabrielli@arm.com
98710850SGiacomo.Gabrielli@arm.comtemplate<class T>
98810850SGiacomo.Gabrielli@arm.comFSR
98910850SGiacomo.Gabrielli@arm.comAbortFault<T>::getFsr(ThreadContext *tc)
99010850SGiacomo.Gabrielli@arm.com{
99110850SGiacomo.Gabrielli@arm.com    FSR fsr = 0;
99210850SGiacomo.Gabrielli@arm.com
99310850SGiacomo.Gabrielli@arm.com    if (((CPSR) tc->readMiscRegNoEffect(MISCREG_CPSR)).width) {
99410850SGiacomo.Gabrielli@arm.com        // AArch32
99510850SGiacomo.Gabrielli@arm.com        assert(tranMethod != ArmFault::UnknownTran);
99610850SGiacomo.Gabrielli@arm.com        if (tranMethod == ArmFault::LpaeTran) {
99710850SGiacomo.Gabrielli@arm.com            srcEncoded = ArmFault::longDescFaultSources[source];
99810850SGiacomo.Gabrielli@arm.com            fsr.status = srcEncoded;
99910850SGiacomo.Gabrielli@arm.com            fsr.lpae   = 1;
100010850SGiacomo.Gabrielli@arm.com        } else {
100110850SGiacomo.Gabrielli@arm.com            srcEncoded = ArmFault::shortDescFaultSources[source];
100210850SGiacomo.Gabrielli@arm.com            fsr.fsLow  = bits(srcEncoded, 3, 0);
100310850SGiacomo.Gabrielli@arm.com            fsr.fsHigh = bits(srcEncoded, 4);
100410850SGiacomo.Gabrielli@arm.com            fsr.domain = static_cast<uint8_t>(domain);
100510850SGiacomo.Gabrielli@arm.com        }
10066640Svince@csl.cornell.edu        fsr.wnr = (write ? 1 : 0);
10076640Svince@csl.cornell.edu        fsr.ext = 0;
10086640Svince@csl.cornell.edu    } else {
100911851Sbrandon.potter@amd.com        // AArch64
101011851Sbrandon.potter@amd.com        srcEncoded = ArmFault::aarch64FaultSources[source];
10116640Svince@csl.cornell.edu    }
10126640Svince@csl.cornell.edu    if (srcEncoded == ArmFault::FaultSourceInvalid) {
10136701Sgblack@eecs.umich.edu        panic("Invalid fault source\n");
10146701Sgblack@eecs.umich.edu    }
101510793Sbrandon.potter@amd.com    return fsr;
10166640Svince@csl.cornell.edu}
101711758Sbrandon.potter@amd.com
101811758Sbrandon.potter@amd.comtemplate<class T>
101911758Sbrandon.potter@amd.combool
10206640Svince@csl.cornell.eduAbortFault<T>::abortDisable(ThreadContext *tc)
10218706Sandreas.hansson@arm.com{
10226640Svince@csl.cornell.edu    if (ArmSystem::haveSecurity(tc)) {
10236701Sgblack@eecs.umich.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
10246640Svince@csl.cornell.edu        return (!scr.ns || scr.aw);
1025360SN/A    }
10261999SN/A    return true;
10271999SN/A}
10281999SN/A
102911851Sbrandon.potter@amd.comtemplate<class T>
10302680Sktlim@umich.eduvoid
10311999SN/AAbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val)
10321999SN/A{
10331999SN/A    switch (id)
10346701Sgblack@eecs.umich.edu    {
10358852Sandreas.hansson@arm.com      case ArmFault::S1PTW:
10366701Sgblack@eecs.umich.edu        s1ptw = val;
10371999SN/A        break;
10386701Sgblack@eecs.umich.edu      case ArmFault::OVA:
10391999SN/A        OVAddr = val;
10406701Sgblack@eecs.umich.edu        break;
10411999SN/A
10421999SN/A      // Just ignore unknown ID's
10431999SN/A      default:
10441999SN/A        break;
10451999SN/A    }
10463669Sbinkertn@umich.edu}
10473669Sbinkertn@umich.edu
10483669Sbinkertn@umich.edutemplate<class T>
10491999SN/Auint32_t
10501999SN/AAbortFault<T>::iss() const
10511999SN/A{
10522218SN/A    uint32_t val;
10531999SN/A
10541999SN/A    val  = srcEncoded & 0x3F;
10551999SN/A    val |= write << 6;
10561999SN/A    val |= s1ptw << 7;
105713570Sbrandon.potter@amd.com    return (val);
105813570Sbrandon.potter@amd.com}
105913570Sbrandon.potter@amd.com
106013570Sbrandon.potter@amd.comtemplate<class T>
106113570Sbrandon.potter@amd.combool
106213570Sbrandon.potter@amd.comAbortFault<T>::isMMUFault() const
106313570Sbrandon.potter@amd.com{
106413570Sbrandon.potter@amd.com    // NOTE: Not relying on LL information being aligned to lowest bits here
106513570Sbrandon.potter@amd.com    return
106613570Sbrandon.potter@amd.com         (source == ArmFault::AlignmentFault)     ||
106713570Sbrandon.potter@amd.com        ((source >= ArmFault::TranslationLL) &&
106813570Sbrandon.potter@amd.com         (source <  ArmFault::TranslationLL + 4)) ||
106913570Sbrandon.potter@amd.com        ((source >= ArmFault::AccessFlagLL) &&
107013570Sbrandon.potter@amd.com         (source <  ArmFault::AccessFlagLL + 4))  ||
107113570Sbrandon.potter@amd.com        ((source >= ArmFault::DomainLL) &&
107213570Sbrandon.potter@amd.com         (source <  ArmFault::DomainLL + 4))      ||
107313570Sbrandon.potter@amd.com        ((source >= ArmFault::PermissionLL) &&
107413570Sbrandon.potter@amd.com         (source <  ArmFault::PermissionLL + 4));
107513570Sbrandon.potter@amd.com}
107613570Sbrandon.potter@amd.com
107713570Sbrandon.potter@amd.comExceptionClass
107813570Sbrandon.potter@amd.comPrefetchAbort::ec(ThreadContext *tc) const
107913570Sbrandon.potter@amd.com{
108013570Sbrandon.potter@amd.com    if (to64) {
108113570Sbrandon.potter@amd.com        // AArch64
108213570Sbrandon.potter@amd.com        if (toEL == fromEL)
108313570Sbrandon.potter@amd.com            return EC_PREFETCH_ABORT_CURR_EL;
108413570Sbrandon.potter@amd.com        else
108513570Sbrandon.potter@amd.com            return EC_PREFETCH_ABORT_LOWER_EL;
108613570Sbrandon.potter@amd.com    } else {
108713570Sbrandon.potter@amd.com        // AArch32
108813570Sbrandon.potter@amd.com        // Abort faults have different EC codes depending on whether
108913570Sbrandon.potter@amd.com        // the fault originated within HYP mode, or not. So override
109013570Sbrandon.potter@amd.com        // the method and add the extra adjustment of the EC value.
109113570Sbrandon.potter@amd.com
109213570Sbrandon.potter@amd.com        ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec;
109313570Sbrandon.potter@amd.com
109413570Sbrandon.potter@amd.com        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
109513570Sbrandon.potter@amd.com        if (spsr.mode == MODE_HYP) {
109613570Sbrandon.potter@amd.com            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
109713570Sbrandon.potter@amd.com        }
109813570Sbrandon.potter@amd.com        return ec;
109913570Sbrandon.potter@amd.com    }
110013570Sbrandon.potter@amd.com}
110113570Sbrandon.potter@amd.com
110213570Sbrandon.potter@amd.combool
110313570Sbrandon.potter@amd.comPrefetchAbort::routeToMonitor(ThreadContext *tc) const
110413570Sbrandon.potter@amd.com{
110513570Sbrandon.potter@amd.com    SCR scr = 0;
110613570Sbrandon.potter@amd.com    if (from64)
110713570Sbrandon.potter@amd.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
110813570Sbrandon.potter@amd.com    else
110913570Sbrandon.potter@amd.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
111013570Sbrandon.potter@amd.com
111113570Sbrandon.potter@amd.com    return scr.ea && !isMMUFault();
111213570Sbrandon.potter@amd.com}
111313570Sbrandon.potter@amd.com
111413570Sbrandon.potter@amd.combool
111513570Sbrandon.potter@amd.comPrefetchAbort::routeToHyp(ThreadContext *tc) const
111613570Sbrandon.potter@amd.com{
111713570Sbrandon.potter@amd.com    bool toHyp;
111813570Sbrandon.potter@amd.com
111913570Sbrandon.potter@amd.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
112013570Sbrandon.potter@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
112113570Sbrandon.potter@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
112213570Sbrandon.potter@amd.com    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
112313570Sbrandon.potter@amd.com
112413570Sbrandon.potter@amd.com    // if in Hyp mode then stay in Hyp mode
112513570Sbrandon.potter@amd.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
112613570Sbrandon.potter@amd.com    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
112713570Sbrandon.potter@amd.com    toHyp |= (stage2 ||
112813570Sbrandon.potter@amd.com                ( (source ==               DebugEvent) && hdcr.tde && (cpsr.mode !=  MODE_HYP)) ||
112913570Sbrandon.potter@amd.com                ( (source == SynchronousExternalAbort) && hcr.tge  && (cpsr.mode == MODE_USER))
113013570Sbrandon.potter@amd.com             ) && !inSecureState(tc);
11311999SN/A    return toHyp;
11321999SN/A}
11331999SN/A
11341999SN/AExceptionClass
113511856Sbrandon.potter@amd.comDataAbort::ec(ThreadContext *tc) const
11361999SN/A{
11376701Sgblack@eecs.umich.edu    if (to64) {
113811856Sbrandon.potter@amd.com        // AArch64
113911856Sbrandon.potter@amd.com        if (source == ArmFault::AsynchronousExternalAbort) {
114010931Sbrandon.potter@amd.com            panic("Asynchronous External Abort should be handled with "
114111856Sbrandon.potter@amd.com                    "SystemErrors (SErrors)!");
114211856Sbrandon.potter@amd.com        }
11431999SN/A        if (toEL == fromEL)
114411856Sbrandon.potter@amd.com            return EC_DATA_ABORT_CURR_EL;
11451999SN/A        else
114611856Sbrandon.potter@amd.com            return EC_DATA_ABORT_LOWER_EL;
11471999SN/A    } else {
114811856Sbrandon.potter@amd.com        // AArch32
11491999SN/A        // Abort faults have different EC codes depending on whether
115011856Sbrandon.potter@amd.com        // the fault originated within HYP mode, or not. So override
11511999SN/A        // the method and add the extra adjustment of the EC value.
11521999SN/A
11535877Shsul@eecs.umich.edu        ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec;
11545877Shsul@eecs.umich.edu
11555877Shsul@eecs.umich.edu        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
115611851Sbrandon.potter@amd.com        if (spsr.mode == MODE_HYP) {
11575877Shsul@eecs.umich.edu            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
11586701Sgblack@eecs.umich.edu        }
11596701Sgblack@eecs.umich.edu        return ec;
11606701Sgblack@eecs.umich.edu    }
11616701Sgblack@eecs.umich.edu}
11626701Sgblack@eecs.umich.edu
116310027SChris.Adeniyi-Jones@arm.combool
116410027SChris.Adeniyi-Jones@arm.comDataAbort::routeToMonitor(ThreadContext *tc) const
116510027SChris.Adeniyi-Jones@arm.com{
116610027SChris.Adeniyi-Jones@arm.com    SCR scr = 0;
116710027SChris.Adeniyi-Jones@arm.com    if (from64)
11685877Shsul@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
116910318Sandreas.hansson@arm.com    else
117010318Sandreas.hansson@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
11715877Shsul@eecs.umich.edu
11725877Shsul@eecs.umich.edu    return scr.ea && !isMMUFault();
11735877Shsul@eecs.umich.edu}
11745877Shsul@eecs.umich.edu
117510486Stjablin@gmail.combool
117610486Stjablin@gmail.comDataAbort::routeToHyp(ThreadContext *tc) const
11775877Shsul@eecs.umich.edu{
117811905SBrandon.Potter@amd.com    bool toHyp;
117911905SBrandon.Potter@amd.com
118011905SBrandon.Potter@amd.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
118111905SBrandon.Potter@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
118210027SChris.Adeniyi-Jones@arm.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
118312206Srico.amslinger@informatik.uni-augsburg.de    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
118412206Srico.amslinger@informatik.uni-augsburg.de
11855877Shsul@eecs.umich.edu    // if in Hyp mode then stay in Hyp mode
118611905SBrandon.Potter@amd.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
118711905SBrandon.Potter@amd.com    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
11885877Shsul@eecs.umich.edu    toHyp |= (stage2 ||
11895877Shsul@eecs.umich.edu                ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) ||
119010027SChris.Adeniyi-Jones@arm.com                                               ((source == DebugEvent) && hdcr.tde) )
11915877Shsul@eecs.umich.edu                ) ||
11925877Shsul@eecs.umich.edu                ( (cpsr.mode == MODE_USER) && hcr.tge &&
11935877Shsul@eecs.umich.edu                  ((source == AlignmentFault)            ||
119412206Srico.amslinger@informatik.uni-augsburg.de                   (source == SynchronousExternalAbort))
119512206Srico.amslinger@informatik.uni-augsburg.de                )
119612206Srico.amslinger@informatik.uni-augsburg.de             ) && !inSecureState(tc);
119712206Srico.amslinger@informatik.uni-augsburg.de    return toHyp;
119812206Srico.amslinger@informatik.uni-augsburg.de}
119912206Srico.amslinger@informatik.uni-augsburg.de
120012206Srico.amslinger@informatik.uni-augsburg.deuint32_t
120112206Srico.amslinger@informatik.uni-augsburg.deDataAbort::iss() const
120212206Srico.amslinger@informatik.uni-augsburg.de{
120310027SChris.Adeniyi-Jones@arm.com    uint32_t val;
120410027SChris.Adeniyi-Jones@arm.com
120510027SChris.Adeniyi-Jones@arm.com    // Add on the data abort specific fields to the generic abort ISS value
120610027SChris.Adeniyi-Jones@arm.com    val  = AbortFault<DataAbort>::iss();
12075877Shsul@eecs.umich.edu    // ISS is valid if not caused by a stage 1 page table walk, and when taken
120810027SChris.Adeniyi-Jones@arm.com    // to AArch64 only when directed to EL2
120910027SChris.Adeniyi-Jones@arm.com    if (!s1ptw && (!to64 || toEL == EL2)) {
121010027SChris.Adeniyi-Jones@arm.com        val |= isv << 24;
121110027SChris.Adeniyi-Jones@arm.com        if (isv) {
121212206Srico.amslinger@informatik.uni-augsburg.de            val |= sas << 22;
121312206Srico.amslinger@informatik.uni-augsburg.de            val |= sse << 21;
121412206Srico.amslinger@informatik.uni-augsburg.de            val |= srt << 16;
121512206Srico.amslinger@informatik.uni-augsburg.de            // AArch64 only. These assignments are safe on AArch32 as well
121610027SChris.Adeniyi-Jones@arm.com            // because these vars are initialized to false
121710027SChris.Adeniyi-Jones@arm.com            val |= sf << 15;
121810027SChris.Adeniyi-Jones@arm.com            val |= ar << 14;
121910027SChris.Adeniyi-Jones@arm.com        }
122010027SChris.Adeniyi-Jones@arm.com    }
122110027SChris.Adeniyi-Jones@arm.com    return (val);
12225877Shsul@eecs.umich.edu}
12235877Shsul@eecs.umich.edu
12245877Shsul@eecs.umich.eduvoid
122510027SChris.Adeniyi-Jones@arm.comDataAbort::annotate(AnnotationIDs id, uint64_t val)
122610027SChris.Adeniyi-Jones@arm.com{
12278601Ssteve.reinhardt@amd.com    AbortFault<DataAbort>::annotate(id, val);
122810027SChris.Adeniyi-Jones@arm.com    switch (id)
12295877Shsul@eecs.umich.edu    {
12305877Shsul@eecs.umich.edu      case SAS:
12311999SN/A        isv = true;
1232378SN/A        sas = val;
1233360SN/A        break;
12341450SN/A      case SSE:
123511851Sbrandon.potter@amd.com        isv = true;
12362680Sktlim@umich.edu        sse = val;
1237360SN/A        break;
1238360SN/A      case SRT:
1239360SN/A        isv = true;
12406701Sgblack@eecs.umich.edu        srt = val;
12418852Sandreas.hansson@arm.com        break;
12426701Sgblack@eecs.umich.edu      case SF:
12436701Sgblack@eecs.umich.edu        isv = true;
12446701Sgblack@eecs.umich.edu        sf  = val;
12456701Sgblack@eecs.umich.edu        break;
1246360SN/A      case AR:
12473669Sbinkertn@umich.edu        isv = true;
12483669Sbinkertn@umich.edu        ar  = val;
12493669Sbinkertn@umich.edu        break;
1250360SN/A      // Just ignore unknown ID's
1251360SN/A      default:
1252360SN/A        break;
1253360SN/A    }
12542218SN/A}
1255360SN/A
12568706Sandreas.hansson@arm.comvoid
1257360SN/AVirtualDataAbort::invoke(ThreadContext *tc, const StaticInstPtr &inst)
12581458SN/A{
1259360SN/A    AbortFault<VirtualDataAbort>::invoke(tc, inst);
1260360SN/A    HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
1261360SN/A    hcr.va = 0;
12625074Ssaidi@eecs.umich.edu    tc->setMiscRegNoEffect(MISCREG_HCR, hcr);
12635074Ssaidi@eecs.umich.edu}
12645074Ssaidi@eecs.umich.edu
126511851Sbrandon.potter@amd.combool
12665074Ssaidi@eecs.umich.eduInterrupt::routeToMonitor(ThreadContext *tc) const
12675074Ssaidi@eecs.umich.edu{
12685074Ssaidi@eecs.umich.edu    assert(ArmSystem::haveSecurity(tc));
12695074Ssaidi@eecs.umich.edu    SCR scr = 0;
12706701Sgblack@eecs.umich.edu    if (from64)
12718852Sandreas.hansson@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
12726701Sgblack@eecs.umich.edu    else
12735074Ssaidi@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
12746701Sgblack@eecs.umich.edu    return scr.irq;
12755074Ssaidi@eecs.umich.edu}
12765074Ssaidi@eecs.umich.edu
12775074Ssaidi@eecs.umich.edubool
12785074Ssaidi@eecs.umich.eduInterrupt::routeToHyp(ThreadContext *tc) const
12795208Ssaidi@eecs.umich.edu{
12805208Ssaidi@eecs.umich.edu    bool toHyp;
12815208Ssaidi@eecs.umich.edu
12825208Ssaidi@eecs.umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
12835074Ssaidi@eecs.umich.edu    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
12845074Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
12855208Ssaidi@eecs.umich.edu    // Determine whether IRQs are routed to Hyp mode.
12865074Ssaidi@eecs.umich.edu    toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) ||
12875074Ssaidi@eecs.umich.edu            (cpsr.mode == MODE_HYP);
12885074Ssaidi@eecs.umich.edu    return toHyp;
12895074Ssaidi@eecs.umich.edu}
12908706Sandreas.hansson@arm.com
12915074Ssaidi@eecs.umich.edubool
12925074Ssaidi@eecs.umich.eduInterrupt::abortDisable(ThreadContext *tc)
12935074Ssaidi@eecs.umich.edu{
12945074Ssaidi@eecs.umich.edu    if (ArmSystem::haveSecurity(tc)) {
12955074Ssaidi@eecs.umich.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
129610027SChris.Adeniyi-Jones@arm.com        return (!scr.ns || scr.aw);
129710027SChris.Adeniyi-Jones@arm.com    }
129810027SChris.Adeniyi-Jones@arm.com    return true;
129911851Sbrandon.potter@amd.com}
130010027SChris.Adeniyi-Jones@arm.com
130110027SChris.Adeniyi-Jones@arm.comVirtualInterrupt::VirtualInterrupt()
130210027SChris.Adeniyi-Jones@arm.com{}
130310027SChris.Adeniyi-Jones@arm.com
130410027SChris.Adeniyi-Jones@arm.combool
130510793Sbrandon.potter@amd.comFastInterrupt::routeToMonitor(ThreadContext *tc) const
130610027SChris.Adeniyi-Jones@arm.com{
130710027SChris.Adeniyi-Jones@arm.com    assert(ArmSystem::haveSecurity(tc));
130810027SChris.Adeniyi-Jones@arm.com    SCR scr = 0;
130910027SChris.Adeniyi-Jones@arm.com    if (from64)
131010027SChris.Adeniyi-Jones@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
131110027SChris.Adeniyi-Jones@arm.com    else
131210027SChris.Adeniyi-Jones@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
131310027SChris.Adeniyi-Jones@arm.com    return scr.fiq;
131410027SChris.Adeniyi-Jones@arm.com}
131510027SChris.Adeniyi-Jones@arm.com
131610027SChris.Adeniyi-Jones@arm.combool
131710027SChris.Adeniyi-Jones@arm.comFastInterrupt::routeToHyp(ThreadContext *tc) const
131810027SChris.Adeniyi-Jones@arm.com{
131910027SChris.Adeniyi-Jones@arm.com    bool toHyp;
132010027SChris.Adeniyi-Jones@arm.com
132110027SChris.Adeniyi-Jones@arm.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
132210027SChris.Adeniyi-Jones@arm.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
132310027SChris.Adeniyi-Jones@arm.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
132410027SChris.Adeniyi-Jones@arm.com    // Determine whether IRQs are routed to Hyp mode.
132510027SChris.Adeniyi-Jones@arm.com    toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) ||
132610027SChris.Adeniyi-Jones@arm.com            (cpsr.mode == MODE_HYP);
132710027SChris.Adeniyi-Jones@arm.com    return toHyp;
132810027SChris.Adeniyi-Jones@arm.com}
132910027SChris.Adeniyi-Jones@arm.com
133010027SChris.Adeniyi-Jones@arm.combool
133110027SChris.Adeniyi-Jones@arm.comFastInterrupt::abortDisable(ThreadContext *tc)
133210027SChris.Adeniyi-Jones@arm.com{
13331999SN/A    if (ArmSystem::haveSecurity(tc)) {
13341999SN/A        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
13351999SN/A        return (!scr.ns || scr.aw);
133611856Sbrandon.potter@amd.com    }
13371999SN/A    return true;
13386701Sgblack@eecs.umich.edu}
133911856Sbrandon.potter@amd.com
134011856Sbrandon.potter@amd.combool
134110931Sbrandon.potter@amd.comFastInterrupt::fiqDisable(ThreadContext *tc)
134211856Sbrandon.potter@amd.com{
134311856Sbrandon.potter@amd.com    if (ArmSystem::haveVirtualization(tc)) {
13441999SN/A        return true;
134511856Sbrandon.potter@amd.com    } else if (ArmSystem::haveSecurity(tc)) {
13461999SN/A        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
13472764Sstever@eecs.umich.edu        return (!scr.ns || scr.fw);
13482064SN/A    }
134910931Sbrandon.potter@amd.com    return true;
13502064SN/A}
13512064SN/A
135210931Sbrandon.potter@amd.comVirtualFastInterrupt::VirtualFastInterrupt()
13532064SN/A{}
13541999SN/A
13551999SN/Avoid
13562218SN/APCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
13571999SN/A{
135810931Sbrandon.potter@amd.com    ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
13591999SN/A    assert(from64);
13601999SN/A    // Set the FAR
13611999SN/A    tc->setMiscReg(getFaultAddrReg64(), faultPC);
13621999SN/A}
13631999SN/A
1364378SN/ASPAlignmentFault::SPAlignmentFault()
1365360SN/A{}
13661450SN/A
136711851Sbrandon.potter@amd.comSystemError::SystemError()
13682680Sktlim@umich.edu{}
1369360SN/A
1370360SN/Avoid
1371360SN/ASystemError::invoke(ThreadContext *tc, const StaticInstPtr &inst)
13726701Sgblack@eecs.umich.edu{
13738852Sandreas.hansson@arm.com    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
13746701Sgblack@eecs.umich.edu    ArmFault::invoke(tc, inst);
13756701Sgblack@eecs.umich.edu}
13766701Sgblack@eecs.umich.edu
13776701Sgblack@eecs.umich.edubool
1378360SN/ASystemError::routeToMonitor(ThreadContext *tc) const
13793669Sbinkertn@umich.edu{
13803669Sbinkertn@umich.edu    assert(ArmSystem::haveSecurity(tc));
13813669Sbinkertn@umich.edu    assert(from64);
1382360SN/A    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1383360SN/A    return scr.ea;
1384360SN/A}
1385360SN/A
13861458SN/Abool
1387360SN/ASystemError::routeToHyp(ThreadContext *tc) const
13888706Sandreas.hansson@arm.com{
1389360SN/A    bool toHyp;
13901458SN/A    assert(from64);
1391360SN/A
1392360SN/A    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
13931999SN/A    HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
13941999SN/A
13951999SN/A    toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) ||
139611851Sbrandon.potter@amd.com            (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc));
13972680Sktlim@umich.edu    return toHyp;
13981999SN/A}
13991999SN/A
14001999SN/Avoid
14016701Sgblack@eecs.umich.eduFlushPipe::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
14028852Sandreas.hansson@arm.com    DPRINTF(Faults, "Invoking FlushPipe Fault\n");
14036701Sgblack@eecs.umich.edu
14046701Sgblack@eecs.umich.edu    // Set the PC to the next instruction of the faulting instruction.
14056701Sgblack@eecs.umich.edu    // Net effect is simply squashing all instructions behind and
14066701Sgblack@eecs.umich.edu    // start refetching from the next instruction.
14071999SN/A    PCState pc = tc->pcState();
14083669Sbinkertn@umich.edu    assert(inst);
14093669Sbinkertn@umich.edu    inst->advancePC(pc);
14103669Sbinkertn@umich.edu    tc->pcState(pc);
14112764Sstever@eecs.umich.edu}
14122064SN/A
14132064SN/Avoid
14142064SN/AArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
14151999SN/A    DPRINTF(Faults, "Invoking ArmSev Fault\n");
14161999SN/A    if (!FullSystem)
14172064SN/A        return;
14181999SN/A
14191999SN/A    // Set sev_mailbox to 1, clear the pending interrupt from remote
14201999SN/A    // SEV execution and let pipeline continue as pcState is still
14211999SN/A    // valid.
14228706Sandreas.hansson@arm.com    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
14231999SN/A    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0);
14241999SN/A}
14251999SN/A
14261999SN/A// Instantiate all the templates to make the linker happy
1427378SN/Atemplate class ArmFaultVals<Reset>;
1428360SN/Atemplate class ArmFaultVals<UndefinedInstruction>;
14291450SN/Atemplate class ArmFaultVals<SupervisorCall>;
143011856Sbrandon.potter@amd.comtemplate class ArmFaultVals<SecureMonitorCall>;
1431360SN/Atemplate class ArmFaultVals<HypervisorCall>;
14326701Sgblack@eecs.umich.edutemplate class ArmFaultVals<PrefetchAbort>;
143311856Sbrandon.potter@amd.comtemplate class ArmFaultVals<DataAbort>;
143411856Sbrandon.potter@amd.comtemplate class ArmFaultVals<VirtualDataAbort>;
1435360SN/Atemplate class ArmFaultVals<HypervisorTrap>;
143611380Salexandru.dutu@amd.comtemplate class ArmFaultVals<Interrupt>;
1437360SN/Atemplate class ArmFaultVals<VirtualInterrupt>;
143811856Sbrandon.potter@amd.comtemplate class ArmFaultVals<FastInterrupt>;
143911856Sbrandon.potter@amd.comtemplate class ArmFaultVals<VirtualFastInterrupt>;
14401458SN/Atemplate class ArmFaultVals<SupervisorTrap>;
144111856Sbrandon.potter@amd.comtemplate class ArmFaultVals<SecureMonitorTrap>;
1442360SN/Atemplate class ArmFaultVals<PCAlignmentFault>;
1443360SN/Atemplate class ArmFaultVals<SPAlignmentFault>;
144410931Sbrandon.potter@amd.comtemplate class ArmFaultVals<SystemError>;
1445360SN/Atemplate class ArmFaultVals<FlushPipe>;
1446360SN/Atemplate class ArmFaultVals<ArmSev>;
14471458SN/Atemplate class AbortFault<PrefetchAbort>;
1448360SN/Atemplate class AbortFault<DataAbort>;
144910931Sbrandon.potter@amd.comtemplate class AbortFault<VirtualDataAbort>;
14502021SN/A
14511458SN/A
1452360SN/AIllegalInstSetStateFault::IllegalInstSetStateFault()
1453360SN/A{}
14541706SN/A
14551706SN/A
14561706SN/A} // namespace ArmISA
145711851Sbrandon.potter@amd.com