faults.cc revision 12568
1360SN/A/*
210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2010, 2012-2014, 2016-2018 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
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
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
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
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
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
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
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
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
2391706SN/A);
24011851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals(
2411706SN/A    "Secure Monitor Trap",   0x004, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2421706SN/A    4, 2, 0, 0, false, false, false, EC_UNKNOWN
2431706SN/A);
2441706SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals(
24511851Sbrandon.potter@amd.com    "IRQ",                   0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2461706SN/A    4, 4, 0, 0, false, true,  false, EC_UNKNOWN
247511SN/A);
2486703Svince@csl.cornell.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals(
2496703Svince@csl.cornell.edu    "Virtual IRQ",           0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
25011851Sbrandon.potter@amd.com    4, 4, 0, 0, false, true,  false, EC_INVALID
2516703Svince@csl.cornell.edu);
2526685Stjones1@inf.ed.ac.uktemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals(
2536685Stjones1@inf.ed.ac.uk    "FIQ",                   0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
25411851Sbrandon.potter@amd.com    4, 4, 0, 0, false, true,  true,  EC_UNKNOWN
2556685Stjones1@inf.ed.ac.uk);
2566685Stjones1@inf.ed.ac.uktemplate<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals(
2575513SMichael.Adler@intel.com    "Virtual FIQ",           0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2585513SMichael.Adler@intel.com    4, 4, 0, 0, false, true,  true,  EC_INVALID
25911851Sbrandon.potter@amd.com);
2605513SMichael.Adler@intel.comtemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals(
26111885Sbrandon.potter@amd.com    // Some dummy values (SupervisorTrap is AArch64-only)
26211885Sbrandon.potter@amd.com    "Supervisor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
26311885Sbrandon.potter@amd.com    0, 0, 0, 0, false, false, false, EC_UNKNOWN
2645513SMichael.Adler@intel.com);
2651999SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals(
2661999SN/A    // Some dummy values (PCAlignmentFault is AArch64-only)
26711851Sbrandon.potter@amd.com    "PC Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2681999SN/A    0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT
26911885Sbrandon.potter@amd.com);
27011885Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals(
27111885Sbrandon.potter@amd.com    // Some dummy values (SPAlignmentFault is AArch64-only)
2721999SN/A    "SP Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2731999SN/A    0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT
2741999SN/A);
27511851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals(
2761999SN/A    // Some dummy values (SError is AArch64-only)
2773079Sstever@eecs.umich.edu    "SError",                0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC,
2783079Sstever@eecs.umich.edu    0, 0, 0, 0, false, true,  true,  EC_SERROR
27911851Sbrandon.potter@amd.com);
2803079Sstever@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals(
28111908SBrandon.Potter@amd.com    // Some dummy values (SoftwareBreakpoint is AArch64-only)
28211908SBrandon.Potter@amd.com    "Software Breakpoint",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
28311908SBrandon.Potter@amd.com    0, 0, 0, 0, true, false, false,  EC_SOFTWARE_BREAKPOINT
28411908SBrandon.Potter@amd.com);
28511875Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals(
2862093SN/A    // Some dummy values
28711851Sbrandon.potter@amd.com    "ArmSev Flush",          0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2882093SN/A    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN
2892687Sksewell@umich.edu);
2902687Sksewell@umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals(
29111851Sbrandon.potter@amd.com    // Some dummy values (SPAlignmentFault is AArch64-only)
2922687Sksewell@umich.edu    "Illegal Inst Set State Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2932238SN/A    0, 0, 0, 0, true, false, false, EC_ILLEGAL_INST
2942238SN/A);
29511851Sbrandon.potter@amd.com
2962238SN/AAddr
29711908SBrandon.Potter@amd.comArmFault::getVector(ThreadContext *tc)
29811908SBrandon.Potter@amd.com{
29911908SBrandon.Potter@amd.com    Addr base;
30011908SBrandon.Potter@amd.com
30111908SBrandon.Potter@amd.com    // ARM ARM issue C B1.8.1
30211908SBrandon.Potter@amd.com    bool haveSecurity = ArmSystem::haveSecurity(tc);
30311908SBrandon.Potter@amd.com
30411908SBrandon.Potter@amd.com    // panic if SCTLR.VE because I have no idea what to do with vectored
3052238SN/A    // interrupts
3062238SN/A    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
30711851Sbrandon.potter@amd.com    assert(!sctlr.ve);
3082238SN/A    // Check for invalid modes
30913571Sbrandon.potter@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
31013571Sbrandon.potter@amd.com    assert(haveSecurity                      || cpsr.mode != MODE_MON);
31113571Sbrandon.potter@amd.com    assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
31213571Sbrandon.potter@amd.com
31313568Sbrandon.potter@amd.com    switch (cpsr.mode)
31413568Sbrandon.potter@amd.com    {
31513568Sbrandon.potter@amd.com      case MODE_MON:
31613568Sbrandon.potter@amd.com        base = tc->readMiscReg(MISCREG_MVBAR);
31713568Sbrandon.potter@amd.com        break;
31813568Sbrandon.potter@amd.com      case MODE_HYP:
31913568Sbrandon.potter@amd.com        base = tc->readMiscReg(MISCREG_HVBAR);
32013568Sbrandon.potter@amd.com        break;
32113568Sbrandon.potter@amd.com      default:
32213568Sbrandon.potter@amd.com        if (sctlr.v) {
32313568Sbrandon.potter@amd.com            base = HighVecs;
32413568Sbrandon.potter@amd.com        } else {
32513448Sciro.santilli@arm.com            base = haveSecurity ? tc->readMiscReg(MISCREG_VBAR) : 0;
32613031Sbrandon.potter@amd.com        }
32713031Sbrandon.potter@amd.com        break;
32813031Sbrandon.potter@amd.com    }
32913448Sciro.santilli@arm.com    return base + offset(tc);
33013031Sbrandon.potter@amd.com}
33113539Sjavier.setoain@arm.com
33213539Sjavier.setoain@arm.comAddr
33313539Sjavier.setoain@arm.comArmFault::getVector64(ThreadContext *tc)
33413539Sjavier.setoain@arm.com{
33513539Sjavier.setoain@arm.com    Addr vbar;
33613539Sjavier.setoain@arm.com    switch (toEL) {
33713569Sbrandon.potter@amd.com      case EL3:
33813569Sbrandon.potter@amd.com        assert(ArmSystem::haveSecurity(tc));
33913569Sbrandon.potter@amd.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL3);
34013569Sbrandon.potter@amd.com        break;
34113569Sbrandon.potter@amd.com      case EL2:
34213569Sbrandon.potter@amd.com        assert(ArmSystem::haveVirtualization(tc));
34313569Sbrandon.potter@amd.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
34413569Sbrandon.potter@amd.com        break;
34513569Sbrandon.potter@amd.com      case EL1:
34613569Sbrandon.potter@amd.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL1);
34713569Sbrandon.potter@amd.com        break;
34813569Sbrandon.potter@amd.com      default:
34913569Sbrandon.potter@amd.com        panic("Invalid target exception level");
35013569Sbrandon.potter@amd.com        break;
35113569Sbrandon.potter@amd.com    }
35213569Sbrandon.potter@amd.com    return vbar + offset64(tc);
35313031Sbrandon.potter@amd.com}
3542238SN/A
35511851Sbrandon.potter@amd.comMiscRegIndex
3562238SN/AArmFault::getSyndromeReg64() const
3572238SN/A{
3582238SN/A    switch (toEL) {
35911851Sbrandon.potter@amd.com      case EL1:
3602238SN/A        return MISCREG_ESR_EL1;
3612238SN/A      case EL2:
3622238SN/A        return MISCREG_ESR_EL2;
36311851Sbrandon.potter@amd.com      case EL3:
3642238SN/A        return MISCREG_ESR_EL3;
3652238SN/A      default:
3662238SN/A        panic("Invalid exception level");
36711851Sbrandon.potter@amd.com        break;
3682238SN/A    }
3692238SN/A}
3702238SN/A
37111851Sbrandon.potter@amd.comMiscRegIndex
3722238SN/AArmFault::getFaultAddrReg64() const
3739455Smitch.hayenga+gem5@gmail.com{
3749455Smitch.hayenga+gem5@gmail.com    switch (toEL) {
37511851Sbrandon.potter@amd.com      case EL1:
37610203SAli.Saidi@ARM.com        return MISCREG_FAR_EL1;
37711851Sbrandon.potter@amd.com      case EL2:
37811851Sbrandon.potter@amd.com        return MISCREG_FAR_EL2;
3799455Smitch.hayenga+gem5@gmail.com      case EL3:
38013571Sbrandon.potter@amd.com        return MISCREG_FAR_EL3;
38113571Sbrandon.potter@amd.com      default:
38213571Sbrandon.potter@amd.com        panic("Invalid exception level");
38313571Sbrandon.potter@amd.com        break;
38413571Sbrandon.potter@amd.com    }
38513571Sbrandon.potter@amd.com}
38613571Sbrandon.potter@amd.com
38713571Sbrandon.potter@amd.comvoid
38813571Sbrandon.potter@amd.comArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
38913571Sbrandon.potter@amd.com{
39013571Sbrandon.potter@amd.com    uint32_t value;
39113571Sbrandon.potter@amd.com    uint32_t exc_class = (uint32_t) ec(tc);
3929112Smarc.orr@gmail.com    uint32_t issVal = iss();
39311906SBrandon.Potter@amd.com
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)) {
4449112Smarc.orr@gmail.com            toEL = EL2;
4459112Smarc.orr@gmail.com            hypRouted = true;
44611911SBrandon.Potter@amd.com        } else {
44711911SBrandon.Potter@amd.com            toEL = opModeToEL(nextMode());
4489112Smarc.orr@gmail.com        }
4499112Smarc.orr@gmail.com
4502238SN/A        if (fromEL > toEL)
4512238SN/A            toEL = fromEL;
4522238SN/A
4532238SN/A        if (toEL == ArmSystem::highestEL(tc) || ELIs64(tc, toEL)) {
45411851Sbrandon.potter@amd.com            // Invoke exception handler in AArch64 state
4552238SN/A            to64 = true;
4562238SN/A            invoke64(tc, inst);
4572238SN/A            return;
45811851Sbrandon.potter@amd.com        }
4592238SN/A    }
4602238SN/A
4612238SN/A    // ARMv7 (ARM ARM issue C B1.9)
46211851Sbrandon.potter@amd.com
4632238SN/A    bool have_security       = ArmSystem::haveSecurity(tc);
4642238SN/A    bool have_virtualization = ArmSystem::haveVirtualization(tc);
4652238SN/A
46611851Sbrandon.potter@amd.com    FaultBase::invoke(tc);
4672238SN/A    if (!FullSystem)
4682238SN/A        return;
4691354SN/A    countStat()++;
4701354SN/A
47110796Sbrandon.potter@amd.com    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
47210796Sbrandon.potter@amd.com    SCR scr = tc->readMiscReg(MISCREG_SCR);
4731354SN/A    CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR);
4741354SN/A    saved_cpsr.nz = tc->readCCReg(CCREG_NZ);
4751354SN/A    saved_cpsr.c = tc->readCCReg(CCREG_C);
4761354SN/A    saved_cpsr.v = tc->readCCReg(CCREG_V);
4771354SN/A    saved_cpsr.ge = tc->readCCReg(CCREG_GE);
4781354SN/A
4791354SN/A    Addr curPc M5_VAR_USED = tc->pcState().pc();
4801354SN/A    ITSTATE it = tc->pcState().itstate();
4811354SN/A    saved_cpsr.it2 = it.top6;
4821354SN/A    saved_cpsr.it1 = it.bottom2;
48310796Sbrandon.potter@amd.com
4841354SN/A    // if we have a valid instruction then use it to annotate this fault with
48510796Sbrandon.potter@amd.com    // extra information. This is used to generate the correct fault syndrome
4861354SN/A    // information
4871354SN/A    if (inst) {
4881354SN/A        ArmStaticInst *armInst = static_cast<ArmStaticInst *>(inst.get());
4891354SN/A        armInst->annotateFault(this);
49010796Sbrandon.potter@amd.com    }
49110796Sbrandon.potter@amd.com
49210796Sbrandon.potter@amd.com    if (have_security && routeToMonitor(tc)) {
49310796Sbrandon.potter@amd.com        cpsr.mode = MODE_MON;
49410796Sbrandon.potter@amd.com    } else if (have_virtualization && routeToHyp(tc)) {
49510796Sbrandon.potter@amd.com        cpsr.mode = MODE_HYP;
49610796Sbrandon.potter@amd.com        hypRouted = true;
49710796Sbrandon.potter@amd.com    } else {
49810796Sbrandon.potter@amd.com        cpsr.mode = nextMode();
49910796Sbrandon.potter@amd.com    }
50010796Sbrandon.potter@amd.com
501360SN/A    // Ensure Secure state if initially in Monitor mode
502360SN/A    if (have_security && saved_cpsr.mode == MODE_MON) {
503360SN/A        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
504360SN/A        if (scr.ns) {
505360SN/A            scr.ns = 0;
506360SN/A            tc->setMiscRegNoEffect(MISCREG_SCR, scr);
507360SN/A        }
50811759Sbrandon.potter@amd.com    }
5093113Sgblack@eecs.umich.edu
5103113Sgblack@eecs.umich.edu    // some bits are set differently if we have been routed to hyp mode
5113113Sgblack@eecs.umich.edu    if (cpsr.mode == MODE_HYP) {
5123113Sgblack@eecs.umich.edu        SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR);
5133113Sgblack@eecs.umich.edu        cpsr.t = hsctlr.te;
5143113Sgblack@eecs.umich.edu        cpsr.e = hsctlr.ee;
5153113Sgblack@eecs.umich.edu        if (!scr.ea)  {cpsr.a = 1;}
5163113Sgblack@eecs.umich.edu        if (!scr.fiq) {cpsr.f = 1;}
5173113Sgblack@eecs.umich.edu        if (!scr.irq) {cpsr.i = 1;}
5183113Sgblack@eecs.umich.edu    } else if (cpsr.mode == MODE_MON) {
5193113Sgblack@eecs.umich.edu        // Special case handling when entering monitor mode
5203113Sgblack@eecs.umich.edu        cpsr.t = sctlr.te;
5213113Sgblack@eecs.umich.edu        cpsr.e = sctlr.ee;
52212032Sandreas.sandberg@arm.com        cpsr.a = 1;
5233113Sgblack@eecs.umich.edu        cpsr.f = 1;
5243113Sgblack@eecs.umich.edu        cpsr.i = 1;
5254189Sgblack@eecs.umich.edu    } else {
5264189Sgblack@eecs.umich.edu        cpsr.t = sctlr.te;
5273113Sgblack@eecs.umich.edu        cpsr.e = sctlr.ee;
5283113Sgblack@eecs.umich.edu
5293113Sgblack@eecs.umich.edu        // The *Disable functions are virtual and different per fault
5303113Sgblack@eecs.umich.edu        cpsr.a = cpsr.a | abortDisable(tc);
5318737Skoansin.tan@gmail.com        cpsr.f = cpsr.f | fiqDisable(tc);
5323113Sgblack@eecs.umich.edu        cpsr.i = 1;
5338737Skoansin.tan@gmail.com    }
5343277Sgblack@eecs.umich.edu    cpsr.it1 = cpsr.it2 = 0;
5355515SMichael.Adler@intel.com    cpsr.j = 0;
5365515SMichael.Adler@intel.com    tc->setMiscReg(MISCREG_CPSR, cpsr);
5375515SMichael.Adler@intel.com
5385515SMichael.Adler@intel.com    // Make sure mailbox sets to one always
5395515SMichael.Adler@intel.com    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
5408737Skoansin.tan@gmail.com
5413277Sgblack@eecs.umich.edu    // Clear the exclusive monitor
5428737Skoansin.tan@gmail.com    tc->setMiscReg(MISCREG_LOCKFLAG, 0);
5433277Sgblack@eecs.umich.edu
5448737Skoansin.tan@gmail.com    if (cpsr.mode == MODE_HYP) {
5453277Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_ELR_HYP, curPc +
5468737Skoansin.tan@gmail.com                (saved_cpsr.t ? thumbPcOffset(true)  : armPcOffset(true)));
5473113Sgblack@eecs.umich.edu    } else {
5483113Sgblack@eecs.umich.edu        tc->setIntReg(INTREG_LR, curPc +
5493113Sgblack@eecs.umich.edu                (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false)));
5503113Sgblack@eecs.umich.edu    }
5518737Skoansin.tan@gmail.com
5523113Sgblack@eecs.umich.edu    switch (cpsr.mode) {
5538737Skoansin.tan@gmail.com      case MODE_FIQ:
5543114Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
5558737Skoansin.tan@gmail.com        break;
5563114Sgblack@eecs.umich.edu      case MODE_IRQ:
5578737Skoansin.tan@gmail.com        tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
5583114Sgblack@eecs.umich.edu        break;
5598737Skoansin.tan@gmail.com      case MODE_SVC:
56011906SBrandon.Potter@amd.com        tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
5614061Sgblack@eecs.umich.edu        break;
5624061Sgblack@eecs.umich.edu      case MODE_MON:
5638737Skoansin.tan@gmail.com        assert(have_security);
5643113Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr);
5658737Skoansin.tan@gmail.com        break;
5663113Sgblack@eecs.umich.edu      case MODE_ABORT:
5673113Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
5683113Sgblack@eecs.umich.edu        break;
5693113Sgblack@eecs.umich.edu      case MODE_UNDEFINED:
5703113Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
57112032Sandreas.sandberg@arm.com        if (ec(tc) != EC_UNKNOWN)
5723113Sgblack@eecs.umich.edu            setSyndrome(tc, MISCREG_HSR);
5733113Sgblack@eecs.umich.edu        break;
5744189Sgblack@eecs.umich.edu      case MODE_HYP:
5754189Sgblack@eecs.umich.edu        assert(have_virtualization);
5763113Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr);
5773113Sgblack@eecs.umich.edu        setSyndrome(tc, MISCREG_HSR);
5783113Sgblack@eecs.umich.edu        break;
5798737Skoansin.tan@gmail.com      default:
5803113Sgblack@eecs.umich.edu        panic("unknown Mode\n");
5818737Skoansin.tan@gmail.com    }
5823113Sgblack@eecs.umich.edu
5838737Skoansin.tan@gmail.com    Addr newPc = getVector(tc);
5843113Sgblack@eecs.umich.edu    DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n",
5853113Sgblack@eecs.umich.edu            name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc);
5863113Sgblack@eecs.umich.edu    PCState pc(newPc);
5873113Sgblack@eecs.umich.edu    pc.thumb(cpsr.t);
5883113Sgblack@eecs.umich.edu    pc.nextThumb(pc.thumb());
5893113Sgblack@eecs.umich.edu    pc.jazelle(cpsr.j);
5903113Sgblack@eecs.umich.edu    pc.nextJazelle(pc.jazelle());
59111906SBrandon.Potter@amd.com    pc.aarch64(!cpsr.width);
5923113Sgblack@eecs.umich.edu    pc.nextAArch64(!cpsr.width);
59312032Sandreas.sandberg@arm.com    tc->pcState(pc);
5948852Sandreas.hansson@arm.com}
59511906SBrandon.Potter@amd.com
5963113Sgblack@eecs.umich.eduvoid
5973113Sgblack@eecs.umich.eduArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
5983113Sgblack@eecs.umich.edu{
5993113Sgblack@eecs.umich.edu    // Determine actual misc. register indices for ELR_ELx and SPSR_ELx
6003113Sgblack@eecs.umich.edu    MiscRegIndex elr_idx, spsr_idx;
6013113Sgblack@eecs.umich.edu    switch (toEL) {
6023113Sgblack@eecs.umich.edu      case EL1:
6033113Sgblack@eecs.umich.edu        elr_idx = MISCREG_ELR_EL1;
60412032Sandreas.sandberg@arm.com        spsr_idx = MISCREG_SPSR_EL1;
6058852Sandreas.hansson@arm.com        break;
60611906SBrandon.Potter@amd.com      case EL2:
6073113Sgblack@eecs.umich.edu        assert(ArmSystem::haveVirtualization(tc));
6083113Sgblack@eecs.umich.edu        elr_idx = MISCREG_ELR_EL2;
6093113Sgblack@eecs.umich.edu        spsr_idx = MISCREG_SPSR_EL2;
6106686Stjones1@inf.ed.ac.uk        break;
6113113Sgblack@eecs.umich.edu      case EL3:
6123113Sgblack@eecs.umich.edu        assert(ArmSystem::haveSecurity(tc));
6133113Sgblack@eecs.umich.edu        elr_idx = MISCREG_ELR_EL3;
61411759Sbrandon.potter@amd.com        spsr_idx = MISCREG_SPSR_EL3;
61512032Sandreas.sandberg@arm.com        break;
61611759Sbrandon.potter@amd.com      default:
61711759Sbrandon.potter@amd.com        panic("Invalid target exception level");
61811759Sbrandon.potter@amd.com        break;
61911759Sbrandon.potter@amd.com    }
62011759Sbrandon.potter@amd.com
62111812Sbaz21@cam.ac.uk    // Save process state into SPSR_ELx
62211812Sbaz21@cam.ac.uk    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
62311812Sbaz21@cam.ac.uk    CPSR spsr = cpsr;
62411759Sbrandon.potter@amd.com    spsr.nz = tc->readCCReg(CCREG_NZ);
62511812Sbaz21@cam.ac.uk    spsr.c = tc->readCCReg(CCREG_C);
62611759Sbrandon.potter@amd.com    spsr.v = tc->readCCReg(CCREG_V);
62711759Sbrandon.potter@amd.com    if (from64) {
62811759Sbrandon.potter@amd.com        // Force some bitfields to 0
62911759Sbrandon.potter@amd.com        spsr.q = 0;
63011759Sbrandon.potter@amd.com        spsr.it1 = 0;
63111759Sbrandon.potter@amd.com        spsr.j = 0;
63211759Sbrandon.potter@amd.com        spsr.res0_23_22 = 0;
63311812Sbaz21@cam.ac.uk        spsr.ge = 0;
63411812Sbaz21@cam.ac.uk        spsr.it2 = 0;
63511812Sbaz21@cam.ac.uk        spsr.t = 0;
63611812Sbaz21@cam.ac.uk    } else {
63711812Sbaz21@cam.ac.uk        spsr.ge = tc->readCCReg(CCREG_GE);
63811812Sbaz21@cam.ac.uk        ITSTATE it = tc->pcState().itstate();
63911812Sbaz21@cam.ac.uk        spsr.it2 = it.top6;
64011759Sbrandon.potter@amd.com        spsr.it1 = it.bottom2;
64111759Sbrandon.potter@amd.com        // Force some bitfields to 0
64211812Sbaz21@cam.ac.uk        spsr.res0_23_22 = 0;
64311812Sbaz21@cam.ac.uk        spsr.ss = 0;
64411759Sbrandon.potter@amd.com    }
64511812Sbaz21@cam.ac.uk    tc->setMiscReg(spsr_idx, spsr);
64611812Sbaz21@cam.ac.uk
64711812Sbaz21@cam.ac.uk    // Save preferred return address into ELR_ELx
64811812Sbaz21@cam.ac.uk    Addr curr_pc = tc->pcState().pc();
64911812Sbaz21@cam.ac.uk    Addr ret_addr = curr_pc;
65011812Sbaz21@cam.ac.uk    if (from64)
65111812Sbaz21@cam.ac.uk        ret_addr += armPcElrOffset();
65211759Sbrandon.potter@amd.com    else
65311759Sbrandon.potter@amd.com        ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset();
65411759Sbrandon.potter@amd.com    tc->setMiscReg(elr_idx, ret_addr);
65511759Sbrandon.potter@amd.com
656378SN/A    Addr vec_address = getVector64(tc);
657378SN/A
6589141Smarc.orr@gmail.com    // Update process state
6599141Smarc.orr@gmail.com    OperatingMode64 mode = 0;
660360SN/A    mode.spX = 1;
6611450SN/A    mode.el = toEL;
66211856Sbrandon.potter@amd.com    mode.width = 0;
663360SN/A    cpsr.mode = mode;
6646701Sgblack@eecs.umich.edu    cpsr.daif = 0xf;
66511856Sbrandon.potter@amd.com    cpsr.il = 0;
66611856Sbrandon.potter@amd.com    cpsr.ss = 0;
667360SN/A    tc->setMiscReg(MISCREG_CPSR, cpsr);
66810930Sbrandon.potter@amd.com
669360SN/A    // Set PC to start of exception handler
67011856Sbrandon.potter@amd.com    Addr new_pc = purifyTaggedAddr(vec_address, tc, toEL);
67111856Sbrandon.potter@amd.com    DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x "
67210496Ssteve.reinhardt@amd.com            "elr:%#x newVec: %#x\n", name(), cpsr, curr_pc, ret_addr, new_pc);
67311856Sbrandon.potter@amd.com    PCState pc(new_pc);
67411856Sbrandon.potter@amd.com    pc.aarch64(!cpsr.width);
6751458SN/A    pc.nextAArch64(!cpsr.width);
676360SN/A    tc->pcState(pc);
67711856Sbrandon.potter@amd.com
67811856Sbrandon.potter@amd.com    // If we have a valid instruction then use it to annotate this fault with
67911856Sbrandon.potter@amd.com    // extra information. This is used to generate the correct fault syndrome
68011856Sbrandon.potter@amd.com    // information
68111856Sbrandon.potter@amd.com    if (inst)
68211856Sbrandon.potter@amd.com        static_cast<ArmStaticInst *>(inst.get())->annotateFault(this);
68311856Sbrandon.potter@amd.com    // Save exception syndrome
68411856Sbrandon.potter@amd.com    if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ))
68510496Ssteve.reinhardt@amd.com        setSyndrome(tc, getSyndromeReg64());
68611856Sbrandon.potter@amd.com}
68711856Sbrandon.potter@amd.com
68811856Sbrandon.potter@amd.comvoid
68911856Sbrandon.potter@amd.comReset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
69011856Sbrandon.potter@amd.com{
69110930Sbrandon.potter@amd.com    if (FullSystem) {
6929141Smarc.orr@gmail.com        tc->getCpuPtr()->clearInterrupts(tc->threadId());
693360SN/A        tc->clearArchRegs();
694360SN/A    }
695360SN/A    if (!ArmSystem::highestELIs64(tc)) {
69611907SBrandon.Potter@amd.com        ArmFault::invoke(tc, inst);
69711907SBrandon.Potter@amd.com        tc->setMiscReg(MISCREG_VMPIDR,
69811907SBrandon.Potter@amd.com                       getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc));
699360SN/A
70011907SBrandon.Potter@amd.com        // Unless we have SMC code to get us there, boot in HYP!
70111907SBrandon.Potter@amd.com        if (ArmSystem::haveVirtualization(tc) &&
70211907SBrandon.Potter@amd.com            !ArmSystem::haveSecurity(tc)) {
70311907SBrandon.Potter@amd.com            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
70411907SBrandon.Potter@amd.com            cpsr.mode = MODE_HYP;
70511907SBrandon.Potter@amd.com            tc->setMiscReg(MISCREG_CPSR, cpsr);
70611907SBrandon.Potter@amd.com        }
70711907SBrandon.Potter@amd.com    } else {
70811907SBrandon.Potter@amd.com        // Advance the PC to the IMPLEMENTATION DEFINED reset value
70911907SBrandon.Potter@amd.com        PCState pc = ArmSystem::resetAddr64(tc);
71011907SBrandon.Potter@amd.com        pc.aarch64(true);
71111907SBrandon.Potter@amd.com        pc.nextAArch64(true);
71211907SBrandon.Potter@amd.com        tc->pcState(pc);
71311907SBrandon.Potter@amd.com    }
714360SN/A}
71511907SBrandon.Potter@amd.com
7161458SN/Avoid
717360SN/AUndefinedInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
71811907SBrandon.Potter@amd.com{
71911907SBrandon.Potter@amd.com    if (FullSystem) {
72011907SBrandon.Potter@amd.com        ArmFault::invoke(tc, inst);
72111907SBrandon.Potter@amd.com        return;
72211907SBrandon.Potter@amd.com    }
72311907SBrandon.Potter@amd.com
72411907SBrandon.Potter@amd.com    // If the mnemonic isn't defined this has to be an unknown instruction.
72511907SBrandon.Potter@amd.com    assert(unknown || mnemonic != NULL);
72611907SBrandon.Potter@amd.com    if (disabled) {
72711907SBrandon.Potter@amd.com        panic("Attempted to execute disabled instruction "
728360SN/A                "'%s' (inst 0x%08x)", mnemonic, machInst);
72911907SBrandon.Potter@amd.com    } else if (unknown) {
73011907SBrandon.Potter@amd.com        panic("Attempted to execute unknown instruction (inst 0x%08x)",
73111907SBrandon.Potter@amd.com              machInst);
732360SN/A    } else {
733360SN/A        panic("Attempted to execute unimplemented instruction "
73411907SBrandon.Potter@amd.com                "'%s' (inst 0x%08x)", mnemonic, machInst);
73511907SBrandon.Potter@amd.com    }
73611907SBrandon.Potter@amd.com}
73711907SBrandon.Potter@amd.com
738360SN/Abool
73911907SBrandon.Potter@amd.comUndefinedInstruction::routeToHyp(ThreadContext *tc) const
740360SN/A{
741360SN/A    bool toHyp;
74211907SBrandon.Potter@amd.com
7433669Sbinkertn@umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
74411907SBrandon.Potter@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
74511907SBrandon.Potter@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
74611907SBrandon.Potter@amd.com
74711907SBrandon.Potter@amd.com    // if in Hyp mode then stay in Hyp mode
74811907SBrandon.Potter@amd.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
74911907SBrandon.Potter@amd.com    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
75011907SBrandon.Potter@amd.com    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
75111907SBrandon.Potter@amd.com    return toHyp;
75211907SBrandon.Potter@amd.com}
75311907SBrandon.Potter@amd.com
75411907SBrandon.Potter@amd.comuint32_t
75511907SBrandon.Potter@amd.comUndefinedInstruction::iss() const
75611907SBrandon.Potter@amd.com{
75711907SBrandon.Potter@amd.com
75811907SBrandon.Potter@amd.com    // If UndefinedInstruction is routed to hypervisor, iss field is 0.
75911907SBrandon.Potter@amd.com    if (hypRouted) {
76011907SBrandon.Potter@amd.com        return 0;
76111907SBrandon.Potter@amd.com    }
76211907SBrandon.Potter@amd.com
76313371Sciro.santilli@arm.com    if (overrideEc == EC_INVALID)
76411907SBrandon.Potter@amd.com        return issRaw;
7651706SN/A
76611907SBrandon.Potter@amd.com    uint32_t new_iss = 0;
76711907SBrandon.Potter@amd.com    uint32_t op0, op1, op2, CRn, CRm, Rt, dir;
76811907SBrandon.Potter@amd.com
76911907SBrandon.Potter@amd.com    dir = bits(machInst, 21, 21);
77011907SBrandon.Potter@amd.com    op0 = bits(machInst, 20, 19);
77111907SBrandon.Potter@amd.com    op1 = bits(machInst, 18, 16);
77210496Ssteve.reinhardt@amd.com    CRn = bits(machInst, 15, 12);
77310496Ssteve.reinhardt@amd.com    CRm = bits(machInst, 11, 8);
77411907SBrandon.Potter@amd.com    op2 = bits(machInst, 7, 5);
77511907SBrandon.Potter@amd.com    Rt = bits(machInst, 4, 0);
77611907SBrandon.Potter@amd.com
77711907SBrandon.Potter@amd.com    new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 |
77811907SBrandon.Potter@amd.com            Rt << 5 | CRm << 1 | dir;
77911907SBrandon.Potter@amd.com
78010496Ssteve.reinhardt@amd.com    return new_iss;
78111907SBrandon.Potter@amd.com}
78211907SBrandon.Potter@amd.com
78311907SBrandon.Potter@amd.comvoid
78411907SBrandon.Potter@amd.comSupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
78510496Ssteve.reinhardt@amd.com{
78610496Ssteve.reinhardt@amd.com    if (FullSystem) {
78711907SBrandon.Potter@amd.com        ArmFault::invoke(tc, inst);
78811907SBrandon.Potter@amd.com        return;
78911907SBrandon.Potter@amd.com    }
79011907SBrandon.Potter@amd.com
79111907SBrandon.Potter@amd.com    // As of now, there isn't a 32 bit thumb version of this instruction.
79211907SBrandon.Potter@amd.com    assert(!machInst.bigThumb);
79311907SBrandon.Potter@amd.com    uint32_t callNum;
79411907SBrandon.Potter@amd.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
79511907SBrandon.Potter@amd.com    OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
79611907SBrandon.Potter@amd.com    if (opModeIs64(mode))
79711907SBrandon.Potter@amd.com        callNum = tc->readIntReg(INTREG_X8);
79811907SBrandon.Potter@amd.com    else
79911907SBrandon.Potter@amd.com        callNum = tc->readIntReg(INTREG_R7);
80011907SBrandon.Potter@amd.com    Fault fault;
80111907SBrandon.Potter@amd.com    tc->syscall(callNum, &fault);
80211907SBrandon.Potter@amd.com
80311907SBrandon.Potter@amd.com    // Advance the PC since that won't happen automatically.
80411907SBrandon.Potter@amd.com    PCState pc = tc->pcState();
80511907SBrandon.Potter@amd.com    assert(inst);
80611907SBrandon.Potter@amd.com    inst->advancePC(pc);
80711907SBrandon.Potter@amd.com    tc->pcState(pc);
80811907SBrandon.Potter@amd.com}
80911907SBrandon.Potter@amd.com
81011907SBrandon.Potter@amd.combool
81111907SBrandon.Potter@amd.comSupervisorCall::routeToHyp(ThreadContext *tc) const
812360SN/A{
81311907SBrandon.Potter@amd.com    bool toHyp;
81411907SBrandon.Potter@amd.com
81511907SBrandon.Potter@amd.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
81611907SBrandon.Potter@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
81711907SBrandon.Potter@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
81811907SBrandon.Potter@amd.com
81911907SBrandon.Potter@amd.com    // if in Hyp mode then stay in Hyp mode
82011907SBrandon.Potter@amd.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
82111907SBrandon.Potter@amd.com    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
82211907SBrandon.Potter@amd.com    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
82311907SBrandon.Potter@amd.com    return toHyp;
82411907SBrandon.Potter@amd.com}
82511907SBrandon.Potter@amd.com
826360SN/AExceptionClass
827360SN/ASupervisorCall::ec(ThreadContext *tc) const
82810027SChris.Adeniyi-Jones@arm.com{
82910027SChris.Adeniyi-Jones@arm.com    return (overrideEc != EC_INVALID) ? overrideEc :
83010027SChris.Adeniyi-Jones@arm.com        (from64 ? EC_SVC_64 : vals.ec);
83111851Sbrandon.potter@amd.com}
83210027SChris.Adeniyi-Jones@arm.com
83310027SChris.Adeniyi-Jones@arm.comuint32_t
83411907SBrandon.Potter@amd.comSupervisorCall::iss() const
83510027SChris.Adeniyi-Jones@arm.com{
83610027SChris.Adeniyi-Jones@arm.com    // Even if we have a 24 bit imm from an arm32 instruction then we only use
83710027SChris.Adeniyi-Jones@arm.com    // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC).
83810027SChris.Adeniyi-Jones@arm.com    return issRaw & 0xFFFF;
83910027SChris.Adeniyi-Jones@arm.com}
84011851Sbrandon.potter@amd.com
84111851Sbrandon.potter@amd.comuint32_t
84210027SChris.Adeniyi-Jones@arm.comSecureMonitorCall::iss() const
84311907SBrandon.Potter@amd.com{
84410027SChris.Adeniyi-Jones@arm.com    if (from64)
84510027SChris.Adeniyi-Jones@arm.com        return bits(machInst, 20, 5);
84610633Smichaelupton@gmail.com    return 0;
84710633Smichaelupton@gmail.com}
84810633Smichaelupton@gmail.com
84911851Sbrandon.potter@amd.comExceptionClass
85010633Smichaelupton@gmail.comUndefinedInstruction::ec(ThreadContext *tc) const
85110633Smichaelupton@gmail.com{
85210633Smichaelupton@gmail.com    // If UndefinedInstruction is routed to hypervisor,
85310633Smichaelupton@gmail.com    // HSR.EC field is 0.
85410633Smichaelupton@gmail.com    if (hypRouted)
85510633Smichaelupton@gmail.com        return EC_UNKNOWN;
85610633Smichaelupton@gmail.com    else
85710633Smichaelupton@gmail.com        return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
85810633Smichaelupton@gmail.com}
85910633Smichaelupton@gmail.com
86010203SAli.Saidi@ARM.com
86110203SAli.Saidi@ARM.comHypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) :
86210203SAli.Saidi@ARM.com        ArmFaultVals<HypervisorCall>(_machInst, _imm)
86311851Sbrandon.potter@amd.com{}
86411851Sbrandon.potter@amd.com
86510203SAli.Saidi@ARM.comExceptionClass
86610203SAli.Saidi@ARM.comHypervisorCall::ec(ThreadContext *tc) const
86710203SAli.Saidi@ARM.com{
86810203SAli.Saidi@ARM.com    return from64 ? EC_HVC_64 : vals.ec;
86910203SAli.Saidi@ARM.com}
87010203SAli.Saidi@ARM.com
87110203SAli.Saidi@ARM.comExceptionClass
87210203SAli.Saidi@ARM.comHypervisorTrap::ec(ThreadContext *tc) const
87310203SAli.Saidi@ARM.com{
87410203SAli.Saidi@ARM.com    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
87510203SAli.Saidi@ARM.com}
87611851Sbrandon.potter@amd.com
87711851Sbrandon.potter@amd.comtemplate<class T>
87810203SAli.Saidi@ARM.comFaultOffset
87910203SAli.Saidi@ARM.comArmFaultVals<T>::offset(ThreadContext *tc)
88010203SAli.Saidi@ARM.com{
88110203SAli.Saidi@ARM.com    bool isHypTrap = false;
88210203SAli.Saidi@ARM.com
88310203SAli.Saidi@ARM.com    // Normally we just use the exception vector from the table at the top if
88410203SAli.Saidi@ARM.com    // this file, however if this exception has caused a transition to hype
88510203SAli.Saidi@ARM.com    // mode, and its an exception type that would only do this if it has been
88610850SGiacomo.Gabrielli@arm.com    // trapped then we use the hyp trap vector instead of the normal vector
88710850SGiacomo.Gabrielli@arm.com    if (vals.hypTrappable) {
88810850SGiacomo.Gabrielli@arm.com        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
88911851Sbrandon.potter@amd.com        if (cpsr.mode == MODE_HYP) {
89010850SGiacomo.Gabrielli@arm.com            CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
89110850SGiacomo.Gabrielli@arm.com            isHypTrap = spsr.mode != MODE_HYP;
89210850SGiacomo.Gabrielli@arm.com        }
89310850SGiacomo.Gabrielli@arm.com    }
89410850SGiacomo.Gabrielli@arm.com    return isHypTrap ? 0x14 : vals.offset;
89510850SGiacomo.Gabrielli@arm.com}
89610850SGiacomo.Gabrielli@arm.com
89710850SGiacomo.Gabrielli@arm.comtemplate<class T>
89810850SGiacomo.Gabrielli@arm.comFaultOffset
89910850SGiacomo.Gabrielli@arm.comArmFaultVals<T>::offset64(ThreadContext *tc)
90010850SGiacomo.Gabrielli@arm.com{
90110850SGiacomo.Gabrielli@arm.com    if (toEL == fromEL) {
90210850SGiacomo.Gabrielli@arm.com        if (opModeIsT(fromMode))
90310850SGiacomo.Gabrielli@arm.com            return vals.currELTOffset;
90410850SGiacomo.Gabrielli@arm.com        return vals.currELHOffset;
90510850SGiacomo.Gabrielli@arm.com    } else {
90610850SGiacomo.Gabrielli@arm.com        bool lower_32 = false;
90710850SGiacomo.Gabrielli@arm.com        if (toEL == EL3) {
90810850SGiacomo.Gabrielli@arm.com            if (!inSecureState(tc) && ArmSystem::haveEL(tc, EL2))
90910850SGiacomo.Gabrielli@arm.com                lower_32 = ELIs32(tc, EL2);
91010850SGiacomo.Gabrielli@arm.com            else
91110850SGiacomo.Gabrielli@arm.com                lower_32 = ELIs32(tc, EL1);
91210850SGiacomo.Gabrielli@arm.com        } else {
91310850SGiacomo.Gabrielli@arm.com            lower_32 = ELIs32(tc, static_cast<ExceptionLevel>(toEL - 1));
91410850SGiacomo.Gabrielli@arm.com        }
91510850SGiacomo.Gabrielli@arm.com
91610850SGiacomo.Gabrielli@arm.com        if (lower_32)
91710850SGiacomo.Gabrielli@arm.com            return vals.lowerEL32Offset;
91810850SGiacomo.Gabrielli@arm.com        return vals.lowerEL64Offset;
91910850SGiacomo.Gabrielli@arm.com    }
92010850SGiacomo.Gabrielli@arm.com}
92110850SGiacomo.Gabrielli@arm.com
9226640Svince@csl.cornell.edu// void
9236640Svince@csl.cornell.edu// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx)
9246640Svince@csl.cornell.edu// {
92511851Sbrandon.potter@amd.com//     ESR esr = 0;
92611851Sbrandon.potter@amd.com//     esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32;
9276640Svince@csl.cornell.edu//     esr.il = !machInst.thumb;
9286640Svince@csl.cornell.edu//     if (machInst.aarch64)
9296701Sgblack@eecs.umich.edu//         esr.imm16 = bits(machInst.instBits, 20, 5);
9306701Sgblack@eecs.umich.edu//     else if (machInst.thumb)
93110793Sbrandon.potter@amd.com//         esr.imm16 = bits(machInst.instBits, 7, 0);
9326640Svince@csl.cornell.edu//     else
93311758Sbrandon.potter@amd.com//         esr.imm16 = bits(machInst.instBits, 15, 0);
93411758Sbrandon.potter@amd.com//     tc->setMiscReg(esr_idx, esr);
93511758Sbrandon.potter@amd.com// }
9366640Svince@csl.cornell.edu
9378706Sandreas.hansson@arm.comvoid
9386640Svince@csl.cornell.eduSecureMonitorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
9396701Sgblack@eecs.umich.edu{
9406640Svince@csl.cornell.edu    if (FullSystem) {
941360SN/A        ArmFault::invoke(tc, inst);
9421999SN/A        return;
9431999SN/A    }
9441999SN/A}
94511851Sbrandon.potter@amd.com
9462680Sktlim@umich.eduExceptionClass
9471999SN/ASecureMonitorCall::ec(ThreadContext *tc) const
9481999SN/A{
9491999SN/A    return (from64 ? EC_SMC_64 : vals.ec);
9506701Sgblack@eecs.umich.edu}
9518852Sandreas.hansson@arm.com
9526701Sgblack@eecs.umich.edubool
9531999SN/ASupervisorTrap::routeToHyp(ThreadContext *tc) const
9546701Sgblack@eecs.umich.edu{
9551999SN/A    bool toHyp = false;
9566701Sgblack@eecs.umich.edu
9571999SN/A    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
9581999SN/A    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
9591999SN/A    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
9601999SN/A
9611999SN/A    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
9623669Sbinkertn@umich.edu    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.el == EL0);
9633669Sbinkertn@umich.edu    return toHyp;
9643669Sbinkertn@umich.edu}
9651999SN/A
9661999SN/Auint32_t
9671999SN/ASupervisorTrap::iss() const
9682218SN/A{
9691999SN/A    // If SupervisorTrap is routed to hypervisor, iss field is 0.
9701999SN/A    if (hypRouted) {
9711999SN/A        return 0;
9721999SN/A    }
97313570Sbrandon.potter@amd.com    return issRaw;
97413570Sbrandon.potter@amd.com}
97513570Sbrandon.potter@amd.com
97613570Sbrandon.potter@amd.comExceptionClass
97713570Sbrandon.potter@amd.comSupervisorTrap::ec(ThreadContext *tc) const
97813570Sbrandon.potter@amd.com{
97913570Sbrandon.potter@amd.com    if (hypRouted)
98013570Sbrandon.potter@amd.com        return EC_UNKNOWN;
98113570Sbrandon.potter@amd.com    else
98213570Sbrandon.potter@amd.com        return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
98313570Sbrandon.potter@amd.com}
98413570Sbrandon.potter@amd.com
98513570Sbrandon.potter@amd.comExceptionClass
98613570Sbrandon.potter@amd.comSecureMonitorTrap::ec(ThreadContext *tc) const
98713570Sbrandon.potter@amd.com{
98813570Sbrandon.potter@amd.com    return (overrideEc != EC_INVALID) ? overrideEc :
98913570Sbrandon.potter@amd.com        (from64 ? EC_SMC_64 : vals.ec);
99013570Sbrandon.potter@amd.com}
99113570Sbrandon.potter@amd.com
99213570Sbrandon.potter@amd.comtemplate<class T>
99313570Sbrandon.potter@amd.comvoid
99413570Sbrandon.potter@amd.comAbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
99513570Sbrandon.potter@amd.com{
99613570Sbrandon.potter@amd.com    if (tranMethod == ArmFault::UnknownTran) {
99713570Sbrandon.potter@amd.com        tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran
99813570Sbrandon.potter@amd.com                                             : ArmFault::VmsaTran;
99913570Sbrandon.potter@amd.com
100013570Sbrandon.potter@amd.com        if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) {
100113570Sbrandon.potter@amd.com            // See ARM ARM B3-1416
100213570Sbrandon.potter@amd.com            bool override_LPAE = false;
100313570Sbrandon.potter@amd.com            TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S);
100413570Sbrandon.potter@amd.com            TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS);
100513570Sbrandon.potter@amd.com            if (ttbcr_s.eae) {
100613570Sbrandon.potter@amd.com                override_LPAE = true;
100713570Sbrandon.potter@amd.com            } else {
100813570Sbrandon.potter@amd.com                // Unimplemented code option, not seen in testing.  May need
100913570Sbrandon.potter@amd.com                // extension according to the manual exceprt above.
101013570Sbrandon.potter@amd.com                DPRINTF(Faults, "Warning: Incomplete translation method "
101113570Sbrandon.potter@amd.com                        "override detected.\n");
101213570Sbrandon.potter@amd.com            }
101313570Sbrandon.potter@amd.com            if (override_LPAE)
101413570Sbrandon.potter@amd.com                tranMethod = ArmFault::LpaeTran;
101513570Sbrandon.potter@amd.com        }
101613570Sbrandon.potter@amd.com    }
101713570Sbrandon.potter@amd.com
101813570Sbrandon.potter@amd.com    if (source == ArmFault::AsynchronousExternalAbort) {
101913570Sbrandon.potter@amd.com        tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
102013570Sbrandon.potter@amd.com    }
102113570Sbrandon.potter@amd.com    // Get effective fault source encoding
102213570Sbrandon.potter@amd.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
102313570Sbrandon.potter@amd.com    FSR  fsr  = getFsr(tc);
102413570Sbrandon.potter@amd.com
102513570Sbrandon.potter@amd.com    // source must be determined BEFORE invoking generic routines which will
102613570Sbrandon.potter@amd.com    // try to set hsr etc. and are based upon source!
102713570Sbrandon.potter@amd.com    ArmFaultVals<T>::invoke(tc, inst);
102813570Sbrandon.potter@amd.com
102913570Sbrandon.potter@amd.com    if (!this->to64) {  // AArch32
103013570Sbrandon.potter@amd.com        if (cpsr.mode == MODE_HYP) {
103113570Sbrandon.potter@amd.com            tc->setMiscReg(T::HFarIndex, faultAddr);
103213570Sbrandon.potter@amd.com        } else if (stage2) {
103313570Sbrandon.potter@amd.com            tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf);
103413570Sbrandon.potter@amd.com            tc->setMiscReg(T::HFarIndex,  OVAddr);
103513570Sbrandon.potter@amd.com        } else {
103613570Sbrandon.potter@amd.com            tc->setMiscReg(T::FsrIndex, fsr);
103713570Sbrandon.potter@amd.com            tc->setMiscReg(T::FarIndex, faultAddr);
103813570Sbrandon.potter@amd.com        }
103913570Sbrandon.potter@amd.com        DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\
104013570Sbrandon.potter@amd.com                "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod);
104113570Sbrandon.potter@amd.com    } else {  // AArch64
104213570Sbrandon.potter@amd.com        // Set the FAR register.  Nothing else to do if we are in AArch64 state
104313570Sbrandon.potter@amd.com        // because the syndrome register has already been set inside invoke64()
104413570Sbrandon.potter@amd.com        if (stage2) {
104513570Sbrandon.potter@amd.com            // stage 2 fault, set HPFAR_EL2 to the faulting IPA
104613570Sbrandon.potter@amd.com            // and FAR_EL2 to the Original VA
10471999SN/A            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr);
10481999SN/A            tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
10491999SN/A
10501999SN/A            DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
105111856Sbrandon.potter@amd.com                    OVAddr, faultAddr);
10521999SN/A        } else {
10536701Sgblack@eecs.umich.edu            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
105411856Sbrandon.potter@amd.com        }
105511856Sbrandon.potter@amd.com    }
105610931Sbrandon.potter@amd.com}
105711856Sbrandon.potter@amd.com
105811856Sbrandon.potter@amd.comtemplate<class T>
10591999SN/AFSR
106011856Sbrandon.potter@amd.comAbortFault<T>::getFsr(ThreadContext *tc)
10611999SN/A{
106211856Sbrandon.potter@amd.com    FSR fsr = 0;
10631999SN/A
106411856Sbrandon.potter@amd.com    if (((CPSR) tc->readMiscRegNoEffect(MISCREG_CPSR)).width) {
10651999SN/A        // AArch32
106611856Sbrandon.potter@amd.com        assert(tranMethod != ArmFault::UnknownTran);
10671999SN/A        if (tranMethod == ArmFault::LpaeTran) {
10681999SN/A            srcEncoded = ArmFault::longDescFaultSources[source];
10695877Shsul@eecs.umich.edu            fsr.status = srcEncoded;
10705877Shsul@eecs.umich.edu            fsr.lpae   = 1;
10715877Shsul@eecs.umich.edu        } else {
107211851Sbrandon.potter@amd.com            srcEncoded = ArmFault::shortDescFaultSources[source];
10735877Shsul@eecs.umich.edu            fsr.fsLow  = bits(srcEncoded, 3, 0);
10746701Sgblack@eecs.umich.edu            fsr.fsHigh = bits(srcEncoded, 4);
10756701Sgblack@eecs.umich.edu            fsr.domain = static_cast<uint8_t>(domain);
10766701Sgblack@eecs.umich.edu        }
10776701Sgblack@eecs.umich.edu        fsr.wnr = (write ? 1 : 0);
10786701Sgblack@eecs.umich.edu        fsr.ext = 0;
107910027SChris.Adeniyi-Jones@arm.com    } else {
108010027SChris.Adeniyi-Jones@arm.com        // AArch64
108110027SChris.Adeniyi-Jones@arm.com        srcEncoded = ArmFault::aarch64FaultSources[source];
108210027SChris.Adeniyi-Jones@arm.com    }
108310027SChris.Adeniyi-Jones@arm.com    if (srcEncoded == ArmFault::FaultSourceInvalid) {
10845877Shsul@eecs.umich.edu        panic("Invalid fault source\n");
108510318Sandreas.hansson@arm.com    }
108610318Sandreas.hansson@arm.com    return fsr;
10875877Shsul@eecs.umich.edu}
10885877Shsul@eecs.umich.edu
10895877Shsul@eecs.umich.edutemplate<class T>
10905877Shsul@eecs.umich.edubool
109110486Stjablin@gmail.comAbortFault<T>::abortDisable(ThreadContext *tc)
109210486Stjablin@gmail.com{
10935877Shsul@eecs.umich.edu    if (ArmSystem::haveSecurity(tc)) {
109411905SBrandon.Potter@amd.com        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
109511905SBrandon.Potter@amd.com        return (!scr.ns || scr.aw);
109611905SBrandon.Potter@amd.com    }
109711905SBrandon.Potter@amd.com    return true;
109810027SChris.Adeniyi-Jones@arm.com}
109912206Srico.amslinger@informatik.uni-augsburg.de
110012206Srico.amslinger@informatik.uni-augsburg.detemplate<class T>
11015877Shsul@eecs.umich.eduvoid
110211905SBrandon.Potter@amd.comAbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val)
110311905SBrandon.Potter@amd.com{
11045877Shsul@eecs.umich.edu    switch (id)
11055877Shsul@eecs.umich.edu    {
110610027SChris.Adeniyi-Jones@arm.com      case ArmFault::S1PTW:
11075877Shsul@eecs.umich.edu        s1ptw = val;
11085877Shsul@eecs.umich.edu        break;
11095877Shsul@eecs.umich.edu      case ArmFault::OVA:
111012206Srico.amslinger@informatik.uni-augsburg.de        OVAddr = val;
111112206Srico.amslinger@informatik.uni-augsburg.de        break;
111212206Srico.amslinger@informatik.uni-augsburg.de
111312206Srico.amslinger@informatik.uni-augsburg.de      // Just ignore unknown ID's
111412206Srico.amslinger@informatik.uni-augsburg.de      default:
111512206Srico.amslinger@informatik.uni-augsburg.de        break;
111612206Srico.amslinger@informatik.uni-augsburg.de    }
111712206Srico.amslinger@informatik.uni-augsburg.de}
111812206Srico.amslinger@informatik.uni-augsburg.de
111910027SChris.Adeniyi-Jones@arm.comtemplate<class T>
112010027SChris.Adeniyi-Jones@arm.comuint32_t
112110027SChris.Adeniyi-Jones@arm.comAbortFault<T>::iss() const
112210027SChris.Adeniyi-Jones@arm.com{
11235877Shsul@eecs.umich.edu    uint32_t val;
112410027SChris.Adeniyi-Jones@arm.com
112510027SChris.Adeniyi-Jones@arm.com    val  = srcEncoded & 0x3F;
112610027SChris.Adeniyi-Jones@arm.com    val |= write << 6;
112710027SChris.Adeniyi-Jones@arm.com    val |= s1ptw << 7;
112812206Srico.amslinger@informatik.uni-augsburg.de    return (val);
112912206Srico.amslinger@informatik.uni-augsburg.de}
113012206Srico.amslinger@informatik.uni-augsburg.de
113112206Srico.amslinger@informatik.uni-augsburg.detemplate<class T>
113210027SChris.Adeniyi-Jones@arm.combool
113310027SChris.Adeniyi-Jones@arm.comAbortFault<T>::isMMUFault() const
113410027SChris.Adeniyi-Jones@arm.com{
113510027SChris.Adeniyi-Jones@arm.com    // NOTE: Not relying on LL information being aligned to lowest bits here
113610027SChris.Adeniyi-Jones@arm.com    return
113710027SChris.Adeniyi-Jones@arm.com         (source == ArmFault::AlignmentFault)     ||
11385877Shsul@eecs.umich.edu        ((source >= ArmFault::TranslationLL) &&
11395877Shsul@eecs.umich.edu         (source <  ArmFault::TranslationLL + 4)) ||
11405877Shsul@eecs.umich.edu        ((source >= ArmFault::AccessFlagLL) &&
114110027SChris.Adeniyi-Jones@arm.com         (source <  ArmFault::AccessFlagLL + 4))  ||
114210027SChris.Adeniyi-Jones@arm.com        ((source >= ArmFault::DomainLL) &&
11438601Ssteve.reinhardt@amd.com         (source <  ArmFault::DomainLL + 4))      ||
114410027SChris.Adeniyi-Jones@arm.com        ((source >= ArmFault::PermissionLL) &&
11455877Shsul@eecs.umich.edu         (source <  ArmFault::PermissionLL + 4));
11465877Shsul@eecs.umich.edu}
11471999SN/A
1148378SN/AExceptionClass
1149360SN/APrefetchAbort::ec(ThreadContext *tc) const
11501450SN/A{
115111851Sbrandon.potter@amd.com    if (to64) {
11522680Sktlim@umich.edu        // AArch64
1153360SN/A        if (toEL == fromEL)
1154360SN/A            return EC_PREFETCH_ABORT_CURR_EL;
1155360SN/A        else
11566701Sgblack@eecs.umich.edu            return EC_PREFETCH_ABORT_LOWER_EL;
11578852Sandreas.hansson@arm.com    } else {
11586701Sgblack@eecs.umich.edu        // AArch32
11596701Sgblack@eecs.umich.edu        // Abort faults have different EC codes depending on whether
11606701Sgblack@eecs.umich.edu        // the fault originated within HYP mode, or not. So override
11616701Sgblack@eecs.umich.edu        // the method and add the extra adjustment of the EC value.
1162360SN/A
11633669Sbinkertn@umich.edu        ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec;
11643669Sbinkertn@umich.edu
11653669Sbinkertn@umich.edu        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
1166360SN/A        if (spsr.mode == MODE_HYP) {
1167360SN/A            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
1168360SN/A        }
1169360SN/A        return ec;
11702218SN/A    }
1171360SN/A}
11728706Sandreas.hansson@arm.com
1173360SN/Abool
11741458SN/APrefetchAbort::routeToMonitor(ThreadContext *tc) const
1175360SN/A{
1176360SN/A    SCR scr = 0;
1177360SN/A    if (from64)
11785074Ssaidi@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
11795074Ssaidi@eecs.umich.edu    else
11805074Ssaidi@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
118111851Sbrandon.potter@amd.com
11825074Ssaidi@eecs.umich.edu    return scr.ea && !isMMUFault();
11835074Ssaidi@eecs.umich.edu}
11845074Ssaidi@eecs.umich.edu
11855074Ssaidi@eecs.umich.edubool
11866701Sgblack@eecs.umich.eduPrefetchAbort::routeToHyp(ThreadContext *tc) const
11878852Sandreas.hansson@arm.com{
11886701Sgblack@eecs.umich.edu    bool toHyp;
11895074Ssaidi@eecs.umich.edu
11906701Sgblack@eecs.umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
11915074Ssaidi@eecs.umich.edu    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
11925074Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
11935074Ssaidi@eecs.umich.edu    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
11945074Ssaidi@eecs.umich.edu
11955208Ssaidi@eecs.umich.edu    // if in Hyp mode then stay in Hyp mode
11965208Ssaidi@eecs.umich.edu    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
11975208Ssaidi@eecs.umich.edu    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
11985208Ssaidi@eecs.umich.edu    toHyp |= (stage2 ||
11995074Ssaidi@eecs.umich.edu                ( (source ==               DebugEvent) && hdcr.tde && (cpsr.mode !=  MODE_HYP)) ||
12005074Ssaidi@eecs.umich.edu                ( (source == SynchronousExternalAbort) && hcr.tge  && (cpsr.mode == MODE_USER))
12015208Ssaidi@eecs.umich.edu             ) && !inSecureState(tc);
12025074Ssaidi@eecs.umich.edu    return toHyp;
12035074Ssaidi@eecs.umich.edu}
12045074Ssaidi@eecs.umich.edu
12055074Ssaidi@eecs.umich.eduExceptionClass
12068706Sandreas.hansson@arm.comDataAbort::ec(ThreadContext *tc) const
12075074Ssaidi@eecs.umich.edu{
12085074Ssaidi@eecs.umich.edu    if (to64) {
12095074Ssaidi@eecs.umich.edu        // AArch64
12105074Ssaidi@eecs.umich.edu        if (source == ArmFault::AsynchronousExternalAbort) {
12115074Ssaidi@eecs.umich.edu            panic("Asynchronous External Abort should be handled with "
121210027SChris.Adeniyi-Jones@arm.com                    "SystemErrors (SErrors)!");
121310027SChris.Adeniyi-Jones@arm.com        }
121410027SChris.Adeniyi-Jones@arm.com        if (toEL == fromEL)
121511851Sbrandon.potter@amd.com            return EC_DATA_ABORT_CURR_EL;
121610027SChris.Adeniyi-Jones@arm.com        else
121710027SChris.Adeniyi-Jones@arm.com            return EC_DATA_ABORT_LOWER_EL;
121810027SChris.Adeniyi-Jones@arm.com    } else {
121910027SChris.Adeniyi-Jones@arm.com        // AArch32
122010027SChris.Adeniyi-Jones@arm.com        // Abort faults have different EC codes depending on whether
122110793Sbrandon.potter@amd.com        // the fault originated within HYP mode, or not. So override
122210027SChris.Adeniyi-Jones@arm.com        // the method and add the extra adjustment of the EC value.
122310027SChris.Adeniyi-Jones@arm.com
122410027SChris.Adeniyi-Jones@arm.com        ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec;
122510027SChris.Adeniyi-Jones@arm.com
122610027SChris.Adeniyi-Jones@arm.com        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
122710027SChris.Adeniyi-Jones@arm.com        if (spsr.mode == MODE_HYP) {
122810027SChris.Adeniyi-Jones@arm.com            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
122910027SChris.Adeniyi-Jones@arm.com        }
123010027SChris.Adeniyi-Jones@arm.com        return ec;
123110027SChris.Adeniyi-Jones@arm.com    }
123210027SChris.Adeniyi-Jones@arm.com}
123310027SChris.Adeniyi-Jones@arm.com
123410027SChris.Adeniyi-Jones@arm.combool
123510027SChris.Adeniyi-Jones@arm.comDataAbort::routeToMonitor(ThreadContext *tc) const
123610027SChris.Adeniyi-Jones@arm.com{
123710027SChris.Adeniyi-Jones@arm.com    SCR scr = 0;
123810027SChris.Adeniyi-Jones@arm.com    if (from64)
123910027SChris.Adeniyi-Jones@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
124010027SChris.Adeniyi-Jones@arm.com    else
124110027SChris.Adeniyi-Jones@arm.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
124210027SChris.Adeniyi-Jones@arm.com
124310027SChris.Adeniyi-Jones@arm.com    return scr.ea && !isMMUFault();
124410027SChris.Adeniyi-Jones@arm.com}
124510027SChris.Adeniyi-Jones@arm.com
124610027SChris.Adeniyi-Jones@arm.combool
124710027SChris.Adeniyi-Jones@arm.comDataAbort::routeToHyp(ThreadContext *tc) const
124810027SChris.Adeniyi-Jones@arm.com{
12491999SN/A    bool toHyp;
12501999SN/A
12511999SN/A    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
125211856Sbrandon.potter@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
12531999SN/A    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
12546701Sgblack@eecs.umich.edu    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
125511856Sbrandon.potter@amd.com
125611856Sbrandon.potter@amd.com    // if in Hyp mode then stay in Hyp mode
125710931Sbrandon.potter@amd.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
125811856Sbrandon.potter@amd.com    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
125911856Sbrandon.potter@amd.com    toHyp |= (stage2 ||
12601999SN/A                ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) ||
126111856Sbrandon.potter@amd.com                                               ((source == DebugEvent) && hdcr.tde) )
12621999SN/A                ) ||
12632764Sstever@eecs.umich.edu                ( (cpsr.mode == MODE_USER) && hcr.tge &&
12642064SN/A                  ((source == AlignmentFault)            ||
126510931Sbrandon.potter@amd.com                   (source == SynchronousExternalAbort))
12662064SN/A                )
12672064SN/A             ) && !inSecureState(tc);
126810931Sbrandon.potter@amd.com    return toHyp;
12692064SN/A}
12701999SN/A
12711999SN/Auint32_t
12722218SN/ADataAbort::iss() const
12731999SN/A{
127410931Sbrandon.potter@amd.com    uint32_t val;
12751999SN/A
12761999SN/A    // Add on the data abort specific fields to the generic abort ISS value
12771999SN/A    val  = AbortFault<DataAbort>::iss();
12781999SN/A    // ISS is valid if not caused by a stage 1 page table walk, and when taken
12791999SN/A    // to AArch64 only when directed to EL2
1280378SN/A    if (!s1ptw && (!to64 || toEL == EL2)) {
1281360SN/A        val |= isv << 24;
12821450SN/A        if (isv) {
128311851Sbrandon.potter@amd.com            val |= sas << 22;
12842680Sktlim@umich.edu            val |= sse << 21;
1285360SN/A            val |= srt << 16;
1286360SN/A            // AArch64 only. These assignments are safe on AArch32 as well
1287360SN/A            // because these vars are initialized to false
12886701Sgblack@eecs.umich.edu            val |= sf << 15;
12898852Sandreas.hansson@arm.com            val |= ar << 14;
12906701Sgblack@eecs.umich.edu        }
12916701Sgblack@eecs.umich.edu    }
12926701Sgblack@eecs.umich.edu    return (val);
12936701Sgblack@eecs.umich.edu}
1294360SN/A
12953669Sbinkertn@umich.eduvoid
12963669Sbinkertn@umich.eduDataAbort::annotate(AnnotationIDs id, uint64_t val)
12973669Sbinkertn@umich.edu{
1298360SN/A    AbortFault<DataAbort>::annotate(id, val);
1299360SN/A    switch (id)
1300360SN/A    {
1301360SN/A      case SAS:
13021458SN/A        isv = true;
1303360SN/A        sas = val;
13048706Sandreas.hansson@arm.com        break;
1305360SN/A      case SSE:
13061458SN/A        isv = true;
1307360SN/A        sse = val;
1308360SN/A        break;
13091999SN/A      case SRT:
13101999SN/A        isv = true;
13111999SN/A        srt = val;
131211851Sbrandon.potter@amd.com        break;
13132680Sktlim@umich.edu      case SF:
13141999SN/A        isv = true;
13151999SN/A        sf  = val;
13161999SN/A        break;
13176701Sgblack@eecs.umich.edu      case AR:
13188852Sandreas.hansson@arm.com        isv = true;
13196701Sgblack@eecs.umich.edu        ar  = val;
13206701Sgblack@eecs.umich.edu        break;
13216701Sgblack@eecs.umich.edu      // Just ignore unknown ID's
13226701Sgblack@eecs.umich.edu      default:
13231999SN/A        break;
13243669Sbinkertn@umich.edu    }
13253669Sbinkertn@umich.edu}
13263669Sbinkertn@umich.edu
13272764Sstever@eecs.umich.eduvoid
13282064SN/AVirtualDataAbort::invoke(ThreadContext *tc, const StaticInstPtr &inst)
13292064SN/A{
13302064SN/A    AbortFault<VirtualDataAbort>::invoke(tc, inst);
13311999SN/A    HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
13321999SN/A    hcr.va = 0;
13332064SN/A    tc->setMiscRegNoEffect(MISCREG_HCR, hcr);
13341999SN/A}
13351999SN/A
13361999SN/Abool
13371999SN/AInterrupt::routeToMonitor(ThreadContext *tc) const
13388706Sandreas.hansson@arm.com{
13391999SN/A    assert(ArmSystem::haveSecurity(tc));
13401999SN/A    SCR scr = 0;
13411999SN/A    if (from64)
13421999SN/A        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1343378SN/A    else
1344360SN/A        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
13451450SN/A    return scr.irq;
134611856Sbrandon.potter@amd.com}
1347360SN/A
13486701Sgblack@eecs.umich.edubool
134911856Sbrandon.potter@amd.comInterrupt::routeToHyp(ThreadContext *tc) const
135011856Sbrandon.potter@amd.com{
1351360SN/A    bool toHyp;
135211380Salexandru.dutu@amd.com
1353360SN/A    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
135411856Sbrandon.potter@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
135511856Sbrandon.potter@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
13561458SN/A    // Determine whether IRQs are routed to Hyp mode.
135711856Sbrandon.potter@amd.com    toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) ||
1358360SN/A            (cpsr.mode == MODE_HYP);
1359360SN/A    return toHyp;
136010931Sbrandon.potter@amd.com}
1361360SN/A
1362360SN/Abool
13631458SN/AInterrupt::abortDisable(ThreadContext *tc)
1364360SN/A{
136510931Sbrandon.potter@amd.com    if (ArmSystem::haveSecurity(tc)) {
13662021SN/A        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
13671458SN/A        return (!scr.ns || scr.aw);
1368360SN/A    }
1369360SN/A    return true;
13701706SN/A}
13711706SN/A
13721706SN/AVirtualInterrupt::VirtualInterrupt()
137311851Sbrandon.potter@amd.com{}
13742680Sktlim@umich.edu
13751706SN/Abool
137611799Sbrandon.potter@amd.comFastInterrupt::routeToMonitor(ThreadContext *tc) const
137711799Sbrandon.potter@amd.com{
137811799Sbrandon.potter@amd.com    assert(ArmSystem::haveSecurity(tc));
13791706SN/A    SCR scr = 0;
13801706SN/A    if (from64)
13816701Sgblack@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
13828852Sandreas.hansson@arm.com    else
13836701Sgblack@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
13846701Sgblack@eecs.umich.edu    return scr.fiq;
13856701Sgblack@eecs.umich.edu}
13866701Sgblack@eecs.umich.edu
13871706SN/Abool
13883669Sbinkertn@umich.eduFastInterrupt::routeToHyp(ThreadContext *tc) const
13893669Sbinkertn@umich.edu{
13903669Sbinkertn@umich.edu    bool toHyp;
13911706SN/A
13921706SN/A    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
13931706SN/A    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
13941706SN/A    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
13952218SN/A    // Determine whether IRQs are routed to Hyp mode.
13961706SN/A    toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) ||
139711759Sbrandon.potter@amd.com            (cpsr.mode == MODE_HYP);
139811799Sbrandon.potter@amd.com    return toHyp;
13991706SN/A}
14001706SN/A
14011706SN/Abool
140211886Sbrandon.potter@amd.comFastInterrupt::abortDisable(ThreadContext *tc)
140311886Sbrandon.potter@amd.com{
140411886Sbrandon.potter@amd.com    if (ArmSystem::haveSecurity(tc)) {
140511886Sbrandon.potter@amd.com        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
140611886Sbrandon.potter@amd.com        return (!scr.ns || scr.aw);
140712426Sqtt2@cornell.edu    }
140813557Sgabeblack@google.com    return true;
140913557Sgabeblack@google.com}
141011886Sbrandon.potter@amd.com
141112426Sqtt2@cornell.edubool
141213534Sandreas.sandberg@arm.comFastInterrupt::fiqDisable(ThreadContext *tc)
141312426Sqtt2@cornell.edu{
141413534Sandreas.sandberg@arm.com    if (ArmSystem::haveVirtualization(tc)) {
141512426Sqtt2@cornell.edu        return true;
141612426Sqtt2@cornell.edu    } else if (ArmSystem::haveSecurity(tc)) {
141712426Sqtt2@cornell.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
141813536Sandreas.sandberg@arm.com        return (!scr.ns || scr.fw);
141912426Sqtt2@cornell.edu    }
142012426Sqtt2@cornell.edu    return true;
142111886Sbrandon.potter@amd.com}
142213536Sandreas.sandberg@arm.com
142312426Sqtt2@cornell.eduVirtualFastInterrupt::VirtualFastInterrupt()
142411886Sbrandon.potter@amd.com{}
142511886Sbrandon.potter@amd.com
142611886Sbrandon.potter@amd.comvoid
142711886Sbrandon.potter@amd.comPCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
142811886Sbrandon.potter@amd.com{
142911886Sbrandon.potter@amd.com    ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
143011886Sbrandon.potter@amd.com    assert(from64);
143111886Sbrandon.potter@amd.com    // Set the FAR
143211886Sbrandon.potter@amd.com    tc->setMiscReg(getFaultAddrReg64(), faultPC);
143311886Sbrandon.potter@amd.com}
143411886Sbrandon.potter@amd.com
143511886Sbrandon.potter@amd.combool
143611886Sbrandon.potter@amd.comPCAlignmentFault::routeToHyp(ThreadContext *tc) const
143711886Sbrandon.potter@amd.com{
143811886Sbrandon.potter@amd.com    bool toHyp = false;
143911886Sbrandon.potter@amd.com
144011886Sbrandon.potter@amd.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
144111886Sbrandon.potter@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
144211886Sbrandon.potter@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
144311886Sbrandon.potter@amd.com
144411886Sbrandon.potter@amd.com    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
144511886Sbrandon.potter@amd.com    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.el == EL0);
144611886Sbrandon.potter@amd.com    return toHyp;
144711886Sbrandon.potter@amd.com}
144811886Sbrandon.potter@amd.com
144911886Sbrandon.potter@amd.comSPAlignmentFault::SPAlignmentFault()
145011886Sbrandon.potter@amd.com{}
145111886Sbrandon.potter@amd.com
145211886Sbrandon.potter@amd.comSystemError::SystemError()
145311886Sbrandon.potter@amd.com{}
145411886Sbrandon.potter@amd.com
145511886Sbrandon.potter@amd.comvoid
145611886Sbrandon.potter@amd.comSystemError::invoke(ThreadContext *tc, const StaticInstPtr &inst)
145711886Sbrandon.potter@amd.com{
145811886Sbrandon.potter@amd.com    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
145911886Sbrandon.potter@amd.com    ArmFault::invoke(tc, inst);
146011886Sbrandon.potter@amd.com}
146111886Sbrandon.potter@amd.com
146211886Sbrandon.potter@amd.combool
146311886Sbrandon.potter@amd.comSystemError::routeToMonitor(ThreadContext *tc) const
146411886Sbrandon.potter@amd.com{
146511886Sbrandon.potter@amd.com    assert(ArmSystem::haveSecurity(tc));
146611886Sbrandon.potter@amd.com    assert(from64);
146711886Sbrandon.potter@amd.com    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
146811886Sbrandon.potter@amd.com    return scr.ea;
146911886Sbrandon.potter@amd.com}
147011886Sbrandon.potter@amd.com
147111886Sbrandon.potter@amd.combool
147211886Sbrandon.potter@amd.comSystemError::routeToHyp(ThreadContext *tc) const
147311886Sbrandon.potter@amd.com{
147411886Sbrandon.potter@amd.com    bool toHyp;
147511886Sbrandon.potter@amd.com    assert(from64);
147611886Sbrandon.potter@amd.com
147711886Sbrandon.potter@amd.com    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
147811886Sbrandon.potter@amd.com    HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
147911886Sbrandon.potter@amd.com
148011886Sbrandon.potter@amd.com    toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) ||
148111886Sbrandon.potter@amd.com            (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc));
148211886Sbrandon.potter@amd.com    return toHyp;
148311886Sbrandon.potter@amd.com}
148411886Sbrandon.potter@amd.com
148511911SBrandon.Potter@amd.com
148611911SBrandon.Potter@amd.comSoftwareBreakpoint::SoftwareBreakpoint(ExtMachInst _mach_inst, uint32_t _iss)
148711911SBrandon.Potter@amd.com    : ArmFaultVals<SoftwareBreakpoint>(_mach_inst, _iss)
148811911SBrandon.Potter@amd.com{}
148911911SBrandon.Potter@amd.com
149011911SBrandon.Potter@amd.combool
149111911SBrandon.Potter@amd.comSoftwareBreakpoint::routeToHyp(ThreadContext *tc) const
149211886Sbrandon.potter@amd.com{
149311886Sbrandon.potter@amd.com    assert(from64);
149411886Sbrandon.potter@amd.com
149511886Sbrandon.potter@amd.com    const bool have_el2 = ArmSystem::haveVirtualization(tc);
149611886Sbrandon.potter@amd.com
149711886Sbrandon.potter@amd.com    const HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
149811886Sbrandon.potter@amd.com    const HDCR mdcr  = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
149911886Sbrandon.potter@amd.com
150011886Sbrandon.potter@amd.com    return have_el2 && !inSecureState(tc) && fromEL <= EL1 &&
150111886Sbrandon.potter@amd.com        (hcr.tge || mdcr.tde);
150211886Sbrandon.potter@amd.com}
150311886Sbrandon.potter@amd.com
150413536Sandreas.sandberg@arm.comvoid
150511886Sbrandon.potter@amd.comArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
150611886Sbrandon.potter@amd.com    DPRINTF(Faults, "Invoking ArmSev Fault\n");
150711886Sbrandon.potter@amd.com    if (!FullSystem)
150811886Sbrandon.potter@amd.com        return;
150911886Sbrandon.potter@amd.com
151011886Sbrandon.potter@amd.com    // Set sev_mailbox to 1, clear the pending interrupt from remote
151111886Sbrandon.potter@amd.com    // SEV execution and let pipeline continue as pcState is still
151211886Sbrandon.potter@amd.com    // valid.
151311886Sbrandon.potter@amd.com    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
151411886Sbrandon.potter@amd.com    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0);
151513535Sandreas.sandberg@arm.com}
151613535Sandreas.sandberg@arm.com
151713535Sandreas.sandberg@arm.com// Instantiate all the templates to make the linker happy
151811886Sbrandon.potter@amd.comtemplate class ArmFaultVals<Reset>;
151911886Sbrandon.potter@amd.comtemplate class ArmFaultVals<UndefinedInstruction>;
152011886Sbrandon.potter@amd.comtemplate class ArmFaultVals<SupervisorCall>;
152111886Sbrandon.potter@amd.comtemplate class ArmFaultVals<SecureMonitorCall>;
15221706SN/Atemplate class ArmFaultVals<HypervisorCall>;
15231706SN/Atemplate class ArmFaultVals<PrefetchAbort>;
15241706SN/Atemplate class ArmFaultVals<DataAbort>;
15251706SN/Atemplate class ArmFaultVals<VirtualDataAbort>;
152611856Sbrandon.potter@amd.comtemplate class ArmFaultVals<HypervisorTrap>;
15271706SN/Atemplate class ArmFaultVals<Interrupt>;
15286701Sgblack@eecs.umich.edutemplate class ArmFaultVals<VirtualInterrupt>;
152911856Sbrandon.potter@amd.comtemplate class ArmFaultVals<FastInterrupt>;
153011856Sbrandon.potter@amd.comtemplate class ArmFaultVals<VirtualFastInterrupt>;
15311706SN/Atemplate class ArmFaultVals<SupervisorTrap>;
153211856Sbrandon.potter@amd.comtemplate class ArmFaultVals<SecureMonitorTrap>;
153311856Sbrandon.potter@amd.comtemplate class ArmFaultVals<PCAlignmentFault>;
15341706SN/Atemplate class ArmFaultVals<SPAlignmentFault>;
153511856Sbrandon.potter@amd.comtemplate class ArmFaultVals<SystemError>;
15361706SN/Atemplate class ArmFaultVals<SoftwareBreakpoint>;
15371706SN/Atemplate class ArmFaultVals<ArmSev>;
153810931Sbrandon.potter@amd.comtemplate class AbortFault<PrefetchAbort>;
15391706SN/Atemplate class AbortFault<DataAbort>;
15401706SN/Atemplate class AbortFault<VirtualDataAbort>;
15412218SN/A
15421706SN/A
154311759Sbrandon.potter@amd.comIllegalInstSetStateFault::IllegalInstSetStateFault()
15441706SN/A{}
15451706SN/A
15461706SN/A
15471706SN/A} // namespace ArmISA
154813572Sbrandon.potter@amd.com