faults.cc revision 12589
1360SN/A/*
210027SChris.Adeniyi-Jones@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"
482764Sstever@eecs.umich.edu
499202Spalle@lyckegaard.dk#include "arch/arm/insts/static_inst.hh"
509202Spalle@lyckegaard.dk#include "arch/arm/system.hh"
512064SN/A#include "arch/arm/utility.hh"
52360SN/A#include "base/compiler.hh"
53360SN/A#include "base/trace.hh"
54360SN/A#include "cpu/base.hh"
55360SN/A#include "cpu/thread_context.hh"
56360SN/A#include "debug/Faults.hh"
57360SN/A#include "sim/full_system.hh"
581809SN/A
595543Ssaidi@eecs.umich.edunamespace ArmISA
601809SN/A{
613113Sgblack@eecs.umich.edu
628229Snate@binkert.orguint8_t ArmFault::shortDescFaultSources[] = {
638229Snate@binkert.org    0x01,  // AlignmentFault
643113Sgblack@eecs.umich.edu    0x04,  // InstructionCacheMaintenance
657075Snate@binkert.org    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
668229Snate@binkert.org    0x0c,  // SynchExtAbtOnTranslTableWalkL1
677075Snate@binkert.org    0x0e,  // SynchExtAbtOnTranslTableWalkL2
68360SN/A    0xff,  // SynchExtAbtOnTranslTableWalkL3 (INVALID)
692474SN/A    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
705543Ssaidi@eecs.umich.edu    0x1c,  // SynchPtyErrOnTranslTableWalkL1
712462SN/A    0x1e,  // SynchPtyErrOnTranslTableWalkL2
721354SN/A    0xff,  // SynchPtyErrOnTranslTableWalkL3 (INVALID)
736216Snate@binkert.org    0xff,  // TranslationL0 (INVALID)
746658Snate@binkert.org    0x05,  // TranslationL1
752474SN/A    0x07,  // TranslationL2
762680Sktlim@umich.edu    0xff,  // TranslationL3 (INVALID)
778232Snate@binkert.org    0xff,  // AccessFlagL0 (INVALID)
788229Snate@binkert.org    0x03,  // AccessFlagL1
797678Sgblack@eecs.umich.edu    0x06,  // AccessFlagL2
8010496Ssteve.reinhardt@amd.com    0xff,  // AccessFlagL3 (INVALID)
818229Snate@binkert.org    0xff,  // DomainL0 (INVALID)
8210497Ssteve.reinhardt@amd.com    0x09,  // DomainL1
838766Sgblack@eecs.umich.edu    0x0b,  // DomainL2
846640Svince@csl.cornell.edu    0xff,  // DomainL3 (INVALID)
85360SN/A    0xff,  // PermissionL0 (INVALID)
86360SN/A    0x0d,  // PermissionL1
87360SN/A    0x0f,  // PermissionL2
88360SN/A    0xff,  // PermissionL3 (INVALID)
89360SN/A    0x02,  // DebugEvent
90360SN/A    0x08,  // SynchronousExternalAbort
91360SN/A    0x10,  // TLBConflictAbort
92360SN/A    0x19,  // SynchPtyErrOnMemoryAccess
93378SN/A    0x16,  // AsynchronousExternalAbort
941450SN/A    0x18,  // AsynchPtyErrOnMemoryAccess
953114Sgblack@eecs.umich.edu    0xff,  // AddressSizeL0 (INVALID)
96360SN/A    0xff,  // AddressSizeL1 (INVALID)
975543Ssaidi@eecs.umich.edu    0xff,  // AddressSizeL2 (INVALID)
985543Ssaidi@eecs.umich.edu    0xff,  // AddressSizeL3 (INVALID)
995543Ssaidi@eecs.umich.edu    0x40,  // PrefetchTLBMiss
100360SN/A    0x80   // PrefetchUncacheable
101360SN/A};
102360SN/A
103360SN/Astatic_assert(sizeof(ArmFault::shortDescFaultSources) ==
104360SN/A              ArmFault::NumFaultSources,
1052680Sktlim@umich.edu              "Invalid size of ArmFault::shortDescFaultSources[]");
106360SN/A
107360SN/Auint8_t ArmFault::longDescFaultSources[] = {
108360SN/A    0x21,  // AlignmentFault
109360SN/A    0xff,  // InstructionCacheMaintenance (INVALID)
110360SN/A    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
111360SN/A    0x15,  // SynchExtAbtOnTranslTableWalkL1
112360SN/A    0x16,  // SynchExtAbtOnTranslTableWalkL2
113360SN/A    0x17,  // SynchExtAbtOnTranslTableWalkL3
114360SN/A    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
115360SN/A    0x1d,  // SynchPtyErrOnTranslTableWalkL1
116360SN/A    0x1e,  // SynchPtyErrOnTranslTableWalkL2
1173114Sgblack@eecs.umich.edu    0x1f,  // SynchPtyErrOnTranslTableWalkL3
118360SN/A    0xff,  // TranslationL0 (INVALID)
119360SN/A    0x05,  // TranslationL1
120360SN/A    0x06,  // TranslationL2
121360SN/A    0x07,  // TranslationL3
122360SN/A    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)
130378SN/A    0xff,  // PermissionL0 (INVALID)
1311706SN/A    0x0d,  // PermissionL1
1323114Sgblack@eecs.umich.edu    0x0e,  // PermissionL2
133378SN/A    0x0f,  // PermissionL3
134378SN/A    0x22,  // DebugEvent
135378SN/A    0x10,  // SynchronousExternalAbort
136378SN/A    0x30,  // TLBConflictAbort
137378SN/A    0x18,  // SynchPtyErrOnMemoryAccess
1381706SN/A    0x11,  // AsynchronousExternalAbort
1393114Sgblack@eecs.umich.edu    0x19,  // AsynchPtyErrOnMemoryAccess
1408149SChris.Emmons@ARM.com    0xff,  // AddressSizeL0 (INVALID)
1418149SChris.Emmons@ARM.com    0xff,  // AddressSizeL1 (INVALID)
142360SN/A    0xff,  // AddressSizeL2 (INVALID)
1436109Ssanchezd@stanford.edu    0xff,  // AddressSizeL3 (INVALID)
1441706SN/A    0x40,  // PrefetchTLBMiss
1453114Sgblack@eecs.umich.edu    0x80   // PrefetchUncacheable
146378SN/A};
1476109Ssanchezd@stanford.edu
1486109Ssanchezd@stanford.edustatic_assert(sizeof(ArmFault::longDescFaultSources) ==
1496109Ssanchezd@stanford.edu              ArmFault::NumFaultSources,
1506109Ssanchezd@stanford.edu              "Invalid size of ArmFault::longDescFaultSources[]");
151378SN/A
1521706SN/Auint8_t ArmFault::aarch64FaultSources[] = {
1533114Sgblack@eecs.umich.edu    0x21,  // AlignmentFault
154378SN/A    0xff,  // InstructionCacheMaintenance (INVALID)
1555748SSteve.Reinhardt@amd.com    0x14,  // SynchExtAbtOnTranslTableWalkL0
1565748SSteve.Reinhardt@amd.com    0x15,  // SynchExtAbtOnTranslTableWalkL1
1575748SSteve.Reinhardt@amd.com    0x16,  // SynchExtAbtOnTranslTableWalkL2
158378SN/A    0x17,  // SynchExtAbtOnTranslTableWalkL3
159378SN/A    0x1c,  // SynchPtyErrOnTranslTableWalkL0
1601706SN/A    0x1d,  // SynchPtyErrOnTranslTableWalkL1
1613114Sgblack@eecs.umich.edu    0x1e,  // SynchPtyErrOnTranslTableWalkL2
162378SN/A    0x1f,  // SynchPtyErrOnTranslTableWalkL3
163378SN/A    0x04,  // TranslationL0
1641706SN/A    0x05,  // TranslationL1
1653114Sgblack@eecs.umich.edu    0x06,  // TranslationL2
166378SN/A    0x07,  // TranslationL3
167378SN/A    0x08,  // AccessFlagL0
1681706SN/A    0x09,  // AccessFlagL1
1693114Sgblack@eecs.umich.edu    0x0a,  // AccessFlagL2
170378SN/A    0x0b,  // AccessFlagL3
171378SN/A    // @todo: Section & Page Domain Fault in AArch64?
1721706SN/A    0xff,  // DomainL0 (INVALID)
1733114Sgblack@eecs.umich.edu    0xff,  // DomainL1 (INVALID)
174378SN/A    0xff,  // DomainL2 (INVALID)
1754118Sgblack@eecs.umich.edu    0xff,  // DomainL3 (INVALID)
1764118Sgblack@eecs.umich.edu    0x0c,  // PermissionL0
1774118Sgblack@eecs.umich.edu    0x0d,  // PermissionL1
1784118Sgblack@eecs.umich.edu    0x0e,  // PermissionL2
179378SN/A    0x0f,  // PermissionL3
1801706SN/A    0x22,  // DebugEvent
1813114Sgblack@eecs.umich.edu    0x10,  // SynchronousExternalAbort
182378SN/A    0x30,  // TLBConflictAbort
183378SN/A    0x18,  // SynchPtyErrOnMemoryAccess
1841706SN/A    0xff,  // AsynchronousExternalAbort (INVALID)
1853114Sgblack@eecs.umich.edu    0xff,  // AsynchPtyErrOnMemoryAccess (INVALID)
186360SN/A    0x00,  // AddressSizeL0
1875513SMichael.Adler@intel.com    0x01,  // AddressSizeL1
1885513SMichael.Adler@intel.com    0x02,  // AddressSizeL2
1895513SMichael.Adler@intel.com    0x03,  // AddressSizeL3
1905513SMichael.Adler@intel.com    0x40,  // PrefetchTLBMiss
19110203SAli.Saidi@ARM.com    0x80   // PrefetchUncacheable
19210203SAli.Saidi@ARM.com};
19310203SAli.Saidi@ARM.com
19410203SAli.Saidi@ARM.comstatic_assert(sizeof(ArmFault::aarch64FaultSources) ==
1955513SMichael.Adler@intel.com              ArmFault::NumFaultSources,
1965513SMichael.Adler@intel.com              "Invalid size of ArmFault::aarch64FaultSources[]");
1975513SMichael.Adler@intel.com
198511SN/A// Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode,
19910633Smichaelupton@gmail.com//         {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap,
20010633Smichaelupton@gmail.com//         {A, F} disable, class, stat
20110633Smichaelupton@gmail.comtemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals(
2021706SN/A    // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED
2033114Sgblack@eecs.umich.edu    // location in AArch64)
204511SN/A    "Reset",                 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2055513SMichael.Adler@intel.com    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN
2065513SMichael.Adler@intel.com);
2075513SMichael.Adler@intel.comtemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals(
2085513SMichael.Adler@intel.com    "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
209511SN/A    4, 2, 0, 0, true,  false, false, EC_UNKNOWN
2101706SN/A);
2113114Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals(
2121706SN/A    "Supervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2131706SN/A    4, 2, 4, 2, true,  false, false, EC_SVC_TO_HYP
2141706SN/A);
2151706SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals(
2163114Sgblack@eecs.umich.edu    "Secure Monitor Call",   0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2171706SN/A    4, 4, 4, 4, false, true,  true,  EC_SMC_TO_HYP
2181706SN/A);
2191706SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals(
2201706SN/A    "Hypervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2213114Sgblack@eecs.umich.edu    4, 4, 4, 4, true,  false, false, EC_HVC
2221706SN/A);
223511SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals(
2246703Svince@csl.cornell.edu    "Prefetch Abort",        0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2256703Svince@csl.cornell.edu    4, 4, 0, 0, true,  true,  false, EC_PREFETCH_ABORT_TO_HYP
2266703Svince@csl.cornell.edu);
2276703Svince@csl.cornell.edutemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals(
2286685Stjones1@inf.ed.ac.uk    "Data Abort",            0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2296685Stjones1@inf.ed.ac.uk    8, 8, 0, 0, true,  true,  false, EC_DATA_ABORT_TO_HYP
2306685Stjones1@inf.ed.ac.uk);
2316685Stjones1@inf.ed.ac.uktemplate<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals(
2326685Stjones1@inf.ed.ac.uk    "Virtual Data Abort",    0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2335513SMichael.Adler@intel.com    8, 8, 0, 0, true,  true,  false, EC_INVALID
2345513SMichael.Adler@intel.com);
2355513SMichael.Adler@intel.comtemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals(
2365513SMichael.Adler@intel.com    // @todo: double check these values
2375513SMichael.Adler@intel.com    "Hypervisor Trap",       0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2381999SN/A    0, 0, 0, 0, false, false, false, EC_UNKNOWN
2391999SN/A);
2403114Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals(
2411999SN/A    "Secure Monitor Trap",   0x004, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2421999SN/A    4, 2, 0, 0, false, false, false, EC_UNKNOWN
2431999SN/A);
2441999SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals(
2453114Sgblack@eecs.umich.edu    "IRQ",                   0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2461999SN/A    4, 4, 0, 0, false, true,  false, EC_UNKNOWN
2473079Sstever@eecs.umich.edu);
2483079Sstever@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals(
2493114Sgblack@eecs.umich.edu    "Virtual IRQ",           0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2503079Sstever@eecs.umich.edu    4, 4, 0, 0, false, true,  false, EC_INVALID
2512093SN/A);
2522093SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals(
2533114Sgblack@eecs.umich.edu    "FIQ",                   0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2542093SN/A    4, 4, 0, 0, false, true,  true,  EC_UNKNOWN
2552687Sksewell@umich.edu);
2562687Sksewell@umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals(
2573114Sgblack@eecs.umich.edu    "Virtual FIQ",           0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2582687Sksewell@umich.edu    4, 4, 0, 0, false, true,  true,  EC_INVALID
2592238SN/A);
2602238SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals(
2613114Sgblack@eecs.umich.edu    // Some dummy values (SupervisorTrap is AArch64-only)
2622238SN/A    "Supervisor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2632238SN/A    0, 0, 0, 0, false, false, false, EC_UNKNOWN
2642238SN/A);
2653114Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals(
2662238SN/A    // Some dummy values (PCAlignmentFault is AArch64-only)
2672238SN/A    "PC Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2682238SN/A    0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT
2693114Sgblack@eecs.umich.edu);
2702238SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals(
2712238SN/A    // Some dummy values (SPAlignmentFault is AArch64-only)
2722238SN/A    "SP Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2733114Sgblack@eecs.umich.edu    0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT
2742238SN/A);
2752238SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals(
2762238SN/A    // Some dummy values (SError is AArch64-only)
2773114Sgblack@eecs.umich.edu    "SError",                0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC,
2782238SN/A    0, 0, 0, 0, false, true,  true,  EC_SERROR
2792238SN/A);
2802238SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals(
2813114Sgblack@eecs.umich.edu    // Some dummy values (SoftwareBreakpoint is AArch64-only)
2822238SN/A    "Software Breakpoint",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2832238SN/A    0, 0, 0, 0, true, false, false,  EC_SOFTWARE_BREAKPOINT
2842238SN/A);
2853114Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals(
2862238SN/A    // Some dummy values
2876109Ssanchezd@stanford.edu    "ArmSev Flush",          0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2886109Ssanchezd@stanford.edu    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN
2896109Ssanchezd@stanford.edu);
2902238SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals(
2919455Smitch.hayenga+gem5@gmail.com    // Some dummy values (SPAlignmentFault is AArch64-only)
2929455Smitch.hayenga+gem5@gmail.com    "Illegal Inst Set State Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2939455Smitch.hayenga+gem5@gmail.com    0, 0, 0, 0, true, false, false, EC_ILLEGAL_INST
29410203SAli.Saidi@ARM.com);
29510203SAli.Saidi@ARM.com
29610203SAli.Saidi@ARM.comAddr
2979455Smitch.hayenga+gem5@gmail.comArmFault::getVector(ThreadContext *tc)
2989112Smarc.orr@gmail.com{
2999112Smarc.orr@gmail.com    Addr base;
3009112Smarc.orr@gmail.com
3019112Smarc.orr@gmail.com    // ARM ARM issue C B1.8.1
3029112Smarc.orr@gmail.com    bool haveSecurity = ArmSystem::haveSecurity(tc);
3039112Smarc.orr@gmail.com
3049112Smarc.orr@gmail.com    // panic if SCTLR.VE because I have no idea what to do with vectored
3059112Smarc.orr@gmail.com    // interrupts
3069112Smarc.orr@gmail.com    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
3079112Smarc.orr@gmail.com    assert(!sctlr.ve);
3089112Smarc.orr@gmail.com    // Check for invalid modes
3099112Smarc.orr@gmail.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
3109112Smarc.orr@gmail.com    assert(haveSecurity                      || cpsr.mode != MODE_MON);
3119112Smarc.orr@gmail.com    assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
3129112Smarc.orr@gmail.com
3139112Smarc.orr@gmail.com    switch (cpsr.mode)
3149112Smarc.orr@gmail.com    {
3159112Smarc.orr@gmail.com      case MODE_MON:
3169112Smarc.orr@gmail.com        base = tc->readMiscReg(MISCREG_MVBAR);
3179112Smarc.orr@gmail.com        break;
3189112Smarc.orr@gmail.com      case MODE_HYP:
3199112Smarc.orr@gmail.com        base = tc->readMiscReg(MISCREG_HVBAR);
3209112Smarc.orr@gmail.com        break;
3219112Smarc.orr@gmail.com      default:
3229238Slluc.alvarez@bsc.es        if (sctlr.v) {
3239112Smarc.orr@gmail.com            base = HighVecs;
3249112Smarc.orr@gmail.com        } else {
3259112Smarc.orr@gmail.com            base = haveSecurity ? tc->readMiscReg(MISCREG_VBAR) : 0;
3269112Smarc.orr@gmail.com        }
3279112Smarc.orr@gmail.com        break;
3289112Smarc.orr@gmail.com    }
3299112Smarc.orr@gmail.com    return base + offset(tc);
3309112Smarc.orr@gmail.com}
3319112Smarc.orr@gmail.com
3329112Smarc.orr@gmail.comAddr
3339112Smarc.orr@gmail.comArmFault::getVector64(ThreadContext *tc)
3349112Smarc.orr@gmail.com{
3359112Smarc.orr@gmail.com    Addr vbar;
3369112Smarc.orr@gmail.com    switch (toEL) {
3379112Smarc.orr@gmail.com      case EL3:
3389112Smarc.orr@gmail.com        assert(ArmSystem::haveSecurity(tc));
3399112Smarc.orr@gmail.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL3);
3409112Smarc.orr@gmail.com        break;
3419112Smarc.orr@gmail.com      case EL2:
3429112Smarc.orr@gmail.com        assert(ArmSystem::haveVirtualization(tc));
3439112Smarc.orr@gmail.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
3449112Smarc.orr@gmail.com        break;
3459112Smarc.orr@gmail.com      case EL1:
3469112Smarc.orr@gmail.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL1);
3479112Smarc.orr@gmail.com        break;
3489112Smarc.orr@gmail.com      default:
3499112Smarc.orr@gmail.com        panic("Invalid target exception level");
3509112Smarc.orr@gmail.com        break;
3519112Smarc.orr@gmail.com    }
3529112Smarc.orr@gmail.com    return vbar + offset64(tc);
3539112Smarc.orr@gmail.com}
3549112Smarc.orr@gmail.com
3559112Smarc.orr@gmail.comMiscRegIndex
3569112Smarc.orr@gmail.comArmFault::getSyndromeReg64() const
3579112Smarc.orr@gmail.com{
3589112Smarc.orr@gmail.com    switch (toEL) {
3599112Smarc.orr@gmail.com      case EL1:
3609112Smarc.orr@gmail.com        return MISCREG_ESR_EL1;
3619112Smarc.orr@gmail.com      case EL2:
3629112Smarc.orr@gmail.com        return MISCREG_ESR_EL2;
3639112Smarc.orr@gmail.com      case EL3:
3649112Smarc.orr@gmail.com        return MISCREG_ESR_EL3;
3659112Smarc.orr@gmail.com      default:
3669112Smarc.orr@gmail.com        panic("Invalid exception level");
3679112Smarc.orr@gmail.com        break;
3689112Smarc.orr@gmail.com    }
3699112Smarc.orr@gmail.com}
3709112Smarc.orr@gmail.com
3719112Smarc.orr@gmail.comMiscRegIndex
3729112Smarc.orr@gmail.comArmFault::getFaultAddrReg64() const
3739112Smarc.orr@gmail.com{
3749238Slluc.alvarez@bsc.es    switch (toEL) {
3759112Smarc.orr@gmail.com      case EL1:
3769112Smarc.orr@gmail.com        return MISCREG_FAR_EL1;
3779112Smarc.orr@gmail.com      case EL2:
3789112Smarc.orr@gmail.com        return MISCREG_FAR_EL2;
3799112Smarc.orr@gmail.com      case EL3:
3802238SN/A        return MISCREG_FAR_EL3;
3812238SN/A      default:
3822238SN/A        panic("Invalid exception level");
3832238SN/A        break;
3843114Sgblack@eecs.umich.edu    }
3852238SN/A}
3862238SN/A
3872238SN/Avoid
3883114Sgblack@eecs.umich.eduArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
3892238SN/A{
3902238SN/A    uint32_t value;
3912238SN/A    uint32_t exc_class = (uint32_t) ec(tc);
3923114Sgblack@eecs.umich.edu    uint32_t issVal = iss();
3932238SN/A
3942238SN/A    assert(!from64 || ArmSystem::highestELIs64(tc));
3952238SN/A
3963114Sgblack@eecs.umich.edu    value = exc_class << 26;
3972238SN/A
3982238SN/A    // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24,
3991354SN/A    // 0x25) for which the ISS information is not valid (ARMv7).
4001354SN/A    // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not
40110796Sbrandon.potter@amd.com    // valid it is treated as RES1.
40210796Sbrandon.potter@amd.com    if (to64) {
4031354SN/A        value |= 1 << 25;
4041354SN/A    } else if ((bits(exc_class, 5, 3) != 4) ||
4051354SN/A               (bits(exc_class, 2) && bits(issVal, 24))) {
4061354SN/A        if (!machInst.thumb || machInst.bigThumb)
4071354SN/A            value |= 1 << 25;
4081354SN/A    }
4091354SN/A    // Condition code valid for EC[5:4] nonzero
4101354SN/A    if (!from64 && ((bits(exc_class, 5, 4) == 0) &&
4111354SN/A                    (bits(exc_class, 3, 0) != 0))) {
4121354SN/A        if (!machInst.thumb) {
41310796Sbrandon.potter@amd.com            uint32_t      cond;
4141354SN/A            ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode;
41510796Sbrandon.potter@amd.com            // If its on unconditional instruction report with a cond code of
4161354SN/A            // 0xE, ie the unconditional code
4171354SN/A            cond  = (condCode == COND_UC) ? COND_AL : condCode;
4181354SN/A            value |= cond << 20;
4191354SN/A            value |= 1    << 24;
42010796Sbrandon.potter@amd.com        }
42110796Sbrandon.potter@amd.com        value |= bits(issVal, 19, 0);
42210796Sbrandon.potter@amd.com    } else {
42310796Sbrandon.potter@amd.com        value |= issVal;
42410796Sbrandon.potter@amd.com    }
42510796Sbrandon.potter@amd.com    tc->setMiscReg(syndrome_reg, value);
42610796Sbrandon.potter@amd.com}
42710796Sbrandon.potter@amd.com
42810796Sbrandon.potter@amd.comvoid
42910796Sbrandon.potter@amd.comArmFault::update(ThreadContext *tc)
43010796Sbrandon.potter@amd.com{
431360SN/A    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
432360SN/A
433360SN/A    // Determine source exception level and mode
434360SN/A    fromMode = (OperatingMode) (uint8_t) cpsr.mode;
435360SN/A    fromEL = opModeToEL(fromMode);
436360SN/A    if (opModeIs64(fromMode))
437360SN/A        from64 = true;
4383113Sgblack@eecs.umich.edu
4393113Sgblack@eecs.umich.edu    // Determine target exception level (aarch64) or target execution
4403113Sgblack@eecs.umich.edu    // mode (aarch32).
4413113Sgblack@eecs.umich.edu    if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc)) {
4423113Sgblack@eecs.umich.edu        toMode = MODE_MON;
4433113Sgblack@eecs.umich.edu        toEL = EL3;
4443113Sgblack@eecs.umich.edu    } else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc)) {
4453113Sgblack@eecs.umich.edu        toMode = MODE_HYP;
4463113Sgblack@eecs.umich.edu        toEL = EL2;
4473113Sgblack@eecs.umich.edu        hypRouted = true;
4483113Sgblack@eecs.umich.edu    } else {
4493113Sgblack@eecs.umich.edu        toMode = nextMode();
4503113Sgblack@eecs.umich.edu        toEL = opModeToEL(toMode);
4513113Sgblack@eecs.umich.edu    }
4523113Sgblack@eecs.umich.edu
4533113Sgblack@eecs.umich.edu    if (fromEL > toEL)
4544189Sgblack@eecs.umich.edu        toEL = fromEL;
4554189Sgblack@eecs.umich.edu
4563113Sgblack@eecs.umich.edu    to64 = ELIs64(tc, toEL);
4573113Sgblack@eecs.umich.edu
4583113Sgblack@eecs.umich.edu    // The fault specific informations have been updated; it is
4593113Sgblack@eecs.umich.edu    // now possible to use them inside the fault.
4608737Skoansin.tan@gmail.com    faultUpdated = true;
4613113Sgblack@eecs.umich.edu}
4628737Skoansin.tan@gmail.com
4633277Sgblack@eecs.umich.eduvoid
4645515SMichael.Adler@intel.comArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
4655515SMichael.Adler@intel.com{
4665515SMichael.Adler@intel.com
4675515SMichael.Adler@intel.com    // Update fault state informations, like the starting mode (aarch32)
4685515SMichael.Adler@intel.com    // or EL (aarch64) and the ending mode or EL.
4698737Skoansin.tan@gmail.com    // From the update function we are also evaluating if the fault must
4703277Sgblack@eecs.umich.edu    // be handled in AArch64 mode (to64).
4718737Skoansin.tan@gmail.com    update(tc);
4723277Sgblack@eecs.umich.edu
4738737Skoansin.tan@gmail.com    if (to64) {
4743277Sgblack@eecs.umich.edu        // Invoke exception handler in AArch64 state
4758737Skoansin.tan@gmail.com        invoke64(tc, inst);
4763113Sgblack@eecs.umich.edu        return;
4773113Sgblack@eecs.umich.edu    }
4783113Sgblack@eecs.umich.edu
4793113Sgblack@eecs.umich.edu    // ARMv7 (ARM ARM issue C B1.9)
4808737Skoansin.tan@gmail.com
4813113Sgblack@eecs.umich.edu    bool have_security       = ArmSystem::haveSecurity(tc);
4828737Skoansin.tan@gmail.com
4833114Sgblack@eecs.umich.edu    FaultBase::invoke(tc);
4848737Skoansin.tan@gmail.com    if (!FullSystem)
4853114Sgblack@eecs.umich.edu        return;
4868737Skoansin.tan@gmail.com    countStat()++;
4873114Sgblack@eecs.umich.edu
4888737Skoansin.tan@gmail.com    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
4894061Sgblack@eecs.umich.edu    SCR scr = tc->readMiscReg(MISCREG_SCR);
4904061Sgblack@eecs.umich.edu    CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR);
4914061Sgblack@eecs.umich.edu    saved_cpsr.nz = tc->readCCReg(CCREG_NZ);
4928737Skoansin.tan@gmail.com    saved_cpsr.c = tc->readCCReg(CCREG_C);
4933113Sgblack@eecs.umich.edu    saved_cpsr.v = tc->readCCReg(CCREG_V);
4948737Skoansin.tan@gmail.com    saved_cpsr.ge = tc->readCCReg(CCREG_GE);
4953113Sgblack@eecs.umich.edu
4963113Sgblack@eecs.umich.edu    Addr curPc M5_VAR_USED = tc->pcState().pc();
4973113Sgblack@eecs.umich.edu    ITSTATE it = tc->pcState().itstate();
4983113Sgblack@eecs.umich.edu    saved_cpsr.it2 = it.top6;
4993113Sgblack@eecs.umich.edu    saved_cpsr.it1 = it.bottom2;
5003113Sgblack@eecs.umich.edu
5013113Sgblack@eecs.umich.edu    // if we have a valid instruction then use it to annotate this fault with
5023113Sgblack@eecs.umich.edu    // extra information. This is used to generate the correct fault syndrome
5034189Sgblack@eecs.umich.edu    // information
5044189Sgblack@eecs.umich.edu    if (inst) {
5053113Sgblack@eecs.umich.edu        ArmStaticInst *armInst = static_cast<ArmStaticInst *>(inst.get());
5063113Sgblack@eecs.umich.edu        armInst->annotateFault(this);
5073113Sgblack@eecs.umich.edu    }
5088737Skoansin.tan@gmail.com
5093113Sgblack@eecs.umich.edu    // Ensure Secure state if initially in Monitor mode
5108737Skoansin.tan@gmail.com    if (have_security && saved_cpsr.mode == MODE_MON) {
5113113Sgblack@eecs.umich.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
5128737Skoansin.tan@gmail.com        if (scr.ns) {
5133113Sgblack@eecs.umich.edu            scr.ns = 0;
5143113Sgblack@eecs.umich.edu            tc->setMiscRegNoEffect(MISCREG_SCR, scr);
5153113Sgblack@eecs.umich.edu        }
5163113Sgblack@eecs.umich.edu    }
5173113Sgblack@eecs.umich.edu
5183113Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
5193113Sgblack@eecs.umich.edu    cpsr.mode = toMode;
5203113Sgblack@eecs.umich.edu
5213113Sgblack@eecs.umich.edu    // some bits are set differently if we have been routed to hyp mode
5223113Sgblack@eecs.umich.edu    if (cpsr.mode == MODE_HYP) {
5238852Sandreas.hansson@arm.com        SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR);
5243113Sgblack@eecs.umich.edu        cpsr.t = hsctlr.te;
5253113Sgblack@eecs.umich.edu        cpsr.e = hsctlr.ee;
5263113Sgblack@eecs.umich.edu        if (!scr.ea)  {cpsr.a = 1;}
5273113Sgblack@eecs.umich.edu        if (!scr.fiq) {cpsr.f = 1;}
5283113Sgblack@eecs.umich.edu        if (!scr.irq) {cpsr.i = 1;}
5293113Sgblack@eecs.umich.edu    } else if (cpsr.mode == MODE_MON) {
5303113Sgblack@eecs.umich.edu        // Special case handling when entering monitor mode
5313113Sgblack@eecs.umich.edu        cpsr.t = sctlr.te;
5323113Sgblack@eecs.umich.edu        cpsr.e = sctlr.ee;
5333113Sgblack@eecs.umich.edu        cpsr.a = 1;
5348852Sandreas.hansson@arm.com        cpsr.f = 1;
5353113Sgblack@eecs.umich.edu        cpsr.i = 1;
5363113Sgblack@eecs.umich.edu    } else {
5373113Sgblack@eecs.umich.edu        cpsr.t = sctlr.te;
5383113Sgblack@eecs.umich.edu        cpsr.e = sctlr.ee;
5396686Stjones1@inf.ed.ac.uk
5403113Sgblack@eecs.umich.edu        // The *Disable functions are virtual and different per fault
5413113Sgblack@eecs.umich.edu        cpsr.a = cpsr.a | abortDisable(tc);
5423113Sgblack@eecs.umich.edu        cpsr.f = cpsr.f | fiqDisable(tc);
543378SN/A        cpsr.i = 1;
544378SN/A    }
5459141Smarc.orr@gmail.com    cpsr.it1 = cpsr.it2 = 0;
5469141Smarc.orr@gmail.com    cpsr.j = 0;
547360SN/A    tc->setMiscReg(MISCREG_CPSR, cpsr);
5481450SN/A
5493114Sgblack@eecs.umich.edu    // Make sure mailbox sets to one always
5502680Sktlim@umich.edu    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
551360SN/A
5526701Sgblack@eecs.umich.edu    // Clear the exclusive monitor
5536701Sgblack@eecs.umich.edu    tc->setMiscReg(MISCREG_LOCKFLAG, 0);
5546701Sgblack@eecs.umich.edu
555360SN/A    if (cpsr.mode == MODE_HYP) {
5561969SN/A        tc->setMiscReg(MISCREG_ELR_HYP, curPc +
557360SN/A                (saved_cpsr.t ? thumbPcOffset(true)  : armPcOffset(true)));
55810496Ssteve.reinhardt@amd.com    } else {
55910496Ssteve.reinhardt@amd.com        tc->setIntReg(INTREG_LR, curPc +
56010496Ssteve.reinhardt@amd.com                (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false)));
561360SN/A    }
5621458SN/A
563360SN/A    switch (cpsr.mode) {
564360SN/A      case MODE_FIQ:
56510496Ssteve.reinhardt@amd.com        tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
56610496Ssteve.reinhardt@amd.com        break;
56710496Ssteve.reinhardt@amd.com      case MODE_IRQ:
56810496Ssteve.reinhardt@amd.com        tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
5699141Smarc.orr@gmail.com        break;
5701458SN/A      case MODE_SVC:
5719141Smarc.orr@gmail.com        tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
572360SN/A        break;
5739141Smarc.orr@gmail.com      case MODE_MON:
5749141Smarc.orr@gmail.com        assert(have_security);
5759141Smarc.orr@gmail.com        tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr);
576360SN/A        break;
577360SN/A      case MODE_ABORT:
578360SN/A        tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
57910027SChris.Adeniyi-Jones@arm.com        break;
5803114Sgblack@eecs.umich.edu      case MODE_UNDEFINED:
58110027SChris.Adeniyi-Jones@arm.com        tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
582360SN/A        if (ec(tc) != EC_UNKNOWN)
583360SN/A            setSyndrome(tc, MISCREG_HSR);
584360SN/A        break;
5858852Sandreas.hansson@arm.com      case MODE_HYP:
5866701Sgblack@eecs.umich.edu        assert(ArmSystem::haveVirtualization(tc));
5871458SN/A        tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr);
588360SN/A        setSyndrome(tc, MISCREG_HSR);
5896701Sgblack@eecs.umich.edu        break;
5906701Sgblack@eecs.umich.edu      default:
591360SN/A        panic("unknown Mode\n");
592360SN/A    }
593360SN/A
594360SN/A    Addr newPc = getVector(tc);
595360SN/A    DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n",
596360SN/A            name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc);
597360SN/A    PCState pc(newPc);
598360SN/A    pc.thumb(cpsr.t);
599360SN/A    pc.nextThumb(pc.thumb());
600360SN/A    pc.jazelle(cpsr.j);
601360SN/A    pc.nextJazelle(pc.jazelle());
602360SN/A    pc.aarch64(!cpsr.width);
6031706SN/A    pc.nextAArch64(!cpsr.width);
604360SN/A    tc->pcState(pc);
605360SN/A}
606360SN/A
607360SN/Avoid
608360SN/AArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
6093669Sbinkertn@umich.edu{
6103669Sbinkertn@umich.edu    // Determine actual misc. register indices for ELR_ELx and SPSR_ELx
6113669Sbinkertn@umich.edu    MiscRegIndex elr_idx, spsr_idx;
6121706SN/A    switch (toEL) {
6131706SN/A      case EL1:
61410496Ssteve.reinhardt@amd.com        elr_idx = MISCREG_ELR_EL1;
61510496Ssteve.reinhardt@amd.com        spsr_idx = MISCREG_SPSR_EL1;
61610496Ssteve.reinhardt@amd.com        break;
61710496Ssteve.reinhardt@amd.com      case EL2:
61810496Ssteve.reinhardt@amd.com        assert(ArmSystem::haveVirtualization(tc));
61910496Ssteve.reinhardt@amd.com        elr_idx = MISCREG_ELR_EL2;
62010496Ssteve.reinhardt@amd.com        spsr_idx = MISCREG_SPSR_EL2;
62110496Ssteve.reinhardt@amd.com        break;
62210496Ssteve.reinhardt@amd.com      case EL3:
62310496Ssteve.reinhardt@amd.com        assert(ArmSystem::haveSecurity(tc));
62410496Ssteve.reinhardt@amd.com        elr_idx = MISCREG_ELR_EL3;
62510496Ssteve.reinhardt@amd.com        spsr_idx = MISCREG_SPSR_EL3;
62610496Ssteve.reinhardt@amd.com        break;
62710496Ssteve.reinhardt@amd.com      default:
62810496Ssteve.reinhardt@amd.com        panic("Invalid target exception level");
62910496Ssteve.reinhardt@amd.com        break;
63010496Ssteve.reinhardt@amd.com    }
63110496Ssteve.reinhardt@amd.com
63210496Ssteve.reinhardt@amd.com    // Save process state into SPSR_ELx
63310496Ssteve.reinhardt@amd.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
6345795Ssaidi@eecs.umich.edu    CPSR spsr = cpsr;
6359143Ssteve.reinhardt@amd.com    spsr.nz = tc->readCCReg(CCREG_NZ);
6369142Ssteve.reinhardt@amd.com    spsr.c = tc->readCCReg(CCREG_C);
6379142Ssteve.reinhardt@amd.com    spsr.v = tc->readCCReg(CCREG_V);
6389143Ssteve.reinhardt@amd.com    if (from64) {
6395795Ssaidi@eecs.umich.edu        // Force some bitfields to 0
6409143Ssteve.reinhardt@amd.com        spsr.q = 0;
6415795Ssaidi@eecs.umich.edu        spsr.it1 = 0;
6425795Ssaidi@eecs.umich.edu        spsr.j = 0;
6435795Ssaidi@eecs.umich.edu        spsr.res0_23_22 = 0;
6449143Ssteve.reinhardt@amd.com        spsr.ge = 0;
6455795Ssaidi@eecs.umich.edu        spsr.it2 = 0;
646360SN/A        spsr.t = 0;
6479143Ssteve.reinhardt@amd.com    } else {
6489143Ssteve.reinhardt@amd.com        spsr.ge = tc->readCCReg(CCREG_GE);
6499143Ssteve.reinhardt@amd.com        ITSTATE it = tc->pcState().itstate();
6509143Ssteve.reinhardt@amd.com        spsr.it2 = it.top6;
651360SN/A        spsr.it1 = it.bottom2;
652360SN/A        // Force some bitfields to 0
65310027SChris.Adeniyi-Jones@arm.com        spsr.res0_23_22 = 0;
65410027SChris.Adeniyi-Jones@arm.com        spsr.ss = 0;
65510027SChris.Adeniyi-Jones@arm.com    }
65610027SChris.Adeniyi-Jones@arm.com    tc->setMiscReg(spsr_idx, spsr);
65710027SChris.Adeniyi-Jones@arm.com
65810027SChris.Adeniyi-Jones@arm.com    // Save preferred return address into ELR_ELx
65910027SChris.Adeniyi-Jones@arm.com    Addr curr_pc = tc->pcState().pc();
66010027SChris.Adeniyi-Jones@arm.com    Addr ret_addr = curr_pc;
66110027SChris.Adeniyi-Jones@arm.com    if (from64)
66210027SChris.Adeniyi-Jones@arm.com        ret_addr += armPcElrOffset();
66310027SChris.Adeniyi-Jones@arm.com    else
66410027SChris.Adeniyi-Jones@arm.com        ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset();
66510027SChris.Adeniyi-Jones@arm.com    tc->setMiscReg(elr_idx, ret_addr);
66610027SChris.Adeniyi-Jones@arm.com
66710027SChris.Adeniyi-Jones@arm.com    Addr vec_address = getVector64(tc);
66810027SChris.Adeniyi-Jones@arm.com
66910027SChris.Adeniyi-Jones@arm.com    // Update process state
67010027SChris.Adeniyi-Jones@arm.com    OperatingMode64 mode = 0;
67110027SChris.Adeniyi-Jones@arm.com    mode.spX = 1;
67210027SChris.Adeniyi-Jones@arm.com    mode.el = toEL;
67310027SChris.Adeniyi-Jones@arm.com    mode.width = 0;
67410027SChris.Adeniyi-Jones@arm.com    cpsr.mode = mode;
67510633Smichaelupton@gmail.com    cpsr.daif = 0xf;
67610633Smichaelupton@gmail.com    cpsr.il = 0;
67710633Smichaelupton@gmail.com    cpsr.ss = 0;
67810633Smichaelupton@gmail.com    tc->setMiscReg(MISCREG_CPSR, cpsr);
67910633Smichaelupton@gmail.com
68010633Smichaelupton@gmail.com    // Set PC to start of exception handler
68110633Smichaelupton@gmail.com    Addr new_pc = purifyTaggedAddr(vec_address, tc, toEL);
68210633Smichaelupton@gmail.com    DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x "
68310633Smichaelupton@gmail.com            "elr:%#x newVec: %#x\n", name(), cpsr, curr_pc, ret_addr, new_pc);
68410633Smichaelupton@gmail.com    PCState pc(new_pc);
68510633Smichaelupton@gmail.com    pc.aarch64(!cpsr.width);
68610633Smichaelupton@gmail.com    pc.nextAArch64(!cpsr.width);
68710633Smichaelupton@gmail.com    tc->pcState(pc);
68810633Smichaelupton@gmail.com
68910203SAli.Saidi@ARM.com    // If we have a valid instruction then use it to annotate this fault with
69010203SAli.Saidi@ARM.com    // extra information. This is used to generate the correct fault syndrome
69110203SAli.Saidi@ARM.com    // information
69210203SAli.Saidi@ARM.com    if (inst)
69310203SAli.Saidi@ARM.com        static_cast<ArmStaticInst *>(inst.get())->annotateFault(this);
69410203SAli.Saidi@ARM.com    // Save exception syndrome
69510203SAli.Saidi@ARM.com    if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ))
69610203SAli.Saidi@ARM.com        setSyndrome(tc, getSyndromeReg64());
69710203SAli.Saidi@ARM.com}
69810203SAli.Saidi@ARM.com
69910203SAli.Saidi@ARM.comvoid
70010203SAli.Saidi@ARM.comReset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
70110203SAli.Saidi@ARM.com{
70210203SAli.Saidi@ARM.com    if (FullSystem) {
70310203SAli.Saidi@ARM.com        tc->getCpuPtr()->clearInterrupts(tc->threadId());
70410203SAli.Saidi@ARM.com        tc->clearArchRegs();
70510203SAli.Saidi@ARM.com    }
70610203SAli.Saidi@ARM.com    if (!ArmSystem::highestELIs64(tc)) {
70710203SAli.Saidi@ARM.com        ArmFault::invoke(tc, inst);
70810203SAli.Saidi@ARM.com        tc->setMiscReg(MISCREG_VMPIDR,
70910203SAli.Saidi@ARM.com                       getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc));
71010203SAli.Saidi@ARM.com
71110203SAli.Saidi@ARM.com        // Unless we have SMC code to get us there, boot in HYP!
71210203SAli.Saidi@ARM.com        if (ArmSystem::haveVirtualization(tc) &&
71310203SAli.Saidi@ARM.com            !ArmSystem::haveSecurity(tc)) {
71410203SAli.Saidi@ARM.com            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
7156640Svince@csl.cornell.edu            cpsr.mode = MODE_HYP;
7166640Svince@csl.cornell.edu            tc->setMiscReg(MISCREG_CPSR, cpsr);
7176640Svince@csl.cornell.edu        }
7186640Svince@csl.cornell.edu    } else {
7196640Svince@csl.cornell.edu        // Advance the PC to the IMPLEMENTATION DEFINED reset value
7206640Svince@csl.cornell.edu        PCState pc = ArmSystem::resetAddr64(tc);
7216640Svince@csl.cornell.edu        pc.aarch64(true);
7226701Sgblack@eecs.umich.edu        pc.nextAArch64(true);
7236701Sgblack@eecs.umich.edu        tc->pcState(pc);
72410793Sbrandon.potter@amd.com    }
7256640Svince@csl.cornell.edu}
7266701Sgblack@eecs.umich.edu
7276701Sgblack@eecs.umich.eduvoid
7286640Svince@csl.cornell.eduUndefinedInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
7298706Sandreas.hansson@arm.com{
7306640Svince@csl.cornell.edu    if (FullSystem) {
7316701Sgblack@eecs.umich.edu        ArmFault::invoke(tc, inst);
7326640Svince@csl.cornell.edu        return;
733360SN/A    }
7341999SN/A
7351999SN/A    // If the mnemonic isn't defined this has to be an unknown instruction.
7361999SN/A    assert(unknown || mnemonic != NULL);
7373114Sgblack@eecs.umich.edu    if (disabled) {
7382680Sktlim@umich.edu        panic("Attempted to execute disabled instruction "
7391999SN/A                "'%s' (inst 0x%08x)", mnemonic, machInst);
7401999SN/A    } else if (unknown) {
7411999SN/A        panic("Attempted to execute unknown instruction (inst 0x%08x)",
7426701Sgblack@eecs.umich.edu              machInst);
7438852Sandreas.hansson@arm.com    } else {
7446701Sgblack@eecs.umich.edu        panic("Attempted to execute unimplemented instruction "
7451999SN/A                "'%s' (inst 0x%08x)", mnemonic, machInst);
7466701Sgblack@eecs.umich.edu    }
7471999SN/A}
7486701Sgblack@eecs.umich.edu
7491999SN/Abool
7501999SN/AUndefinedInstruction::routeToHyp(ThreadContext *tc) const
7511999SN/A{
7521999SN/A    bool toHyp;
7531999SN/A
7543669Sbinkertn@umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
7553669Sbinkertn@umich.edu    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
7563669Sbinkertn@umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
7571999SN/A
7581999SN/A    // if in Hyp mode then stay in Hyp mode
7591999SN/A    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
7602218SN/A    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
7611999SN/A    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
7621999SN/A    return toHyp;
7631999SN/A}
7641999SN/A
7651999SN/Auint32_t
7661999SN/AUndefinedInstruction::iss() const
7671999SN/A{
7681999SN/A
7693114Sgblack@eecs.umich.edu    // If UndefinedInstruction is routed to hypervisor, iss field is 0.
7702680Sktlim@umich.edu    if (hypRouted) {
7711999SN/A        return 0;
7726701Sgblack@eecs.umich.edu    }
7736701Sgblack@eecs.umich.edu
7741999SN/A    if (overrideEc == EC_INVALID)
7751999SN/A        return issRaw;
7761999SN/A
7771999SN/A    uint32_t new_iss = 0;
7781999SN/A    uint32_t op0, op1, op2, CRn, CRm, Rt, dir;
7796701Sgblack@eecs.umich.edu
7801999SN/A    dir = bits(machInst, 21, 21);
7811999SN/A    op0 = bits(machInst, 20, 19);
7821999SN/A    op1 = bits(machInst, 18, 16);
7831999SN/A    CRn = bits(machInst, 15, 12);
7841999SN/A    CRm = bits(machInst, 11, 8);
7851999SN/A    op2 = bits(machInst, 7, 5);
7861999SN/A    Rt = bits(machInst, 4, 0);
7871999SN/A
7882218SN/A    new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 |
7891999SN/A            Rt << 5 | CRm << 1 | dir;
7901999SN/A
7911999SN/A    return new_iss;
7921999SN/A}
7935877Shsul@eecs.umich.edu
7945877Shsul@eecs.umich.eduvoid
7955877Shsul@eecs.umich.eduSupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
7965877Shsul@eecs.umich.edu{
7975877Shsul@eecs.umich.edu    if (FullSystem) {
7986701Sgblack@eecs.umich.edu        ArmFault::invoke(tc, inst);
7996701Sgblack@eecs.umich.edu        return;
8006701Sgblack@eecs.umich.edu    }
8016701Sgblack@eecs.umich.edu
8026701Sgblack@eecs.umich.edu    // As of now, there isn't a 32 bit thumb version of this instruction.
80310027SChris.Adeniyi-Jones@arm.com    assert(!machInst.bigThumb);
80410027SChris.Adeniyi-Jones@arm.com    uint32_t callNum;
80510027SChris.Adeniyi-Jones@arm.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
80610027SChris.Adeniyi-Jones@arm.com    OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
80710027SChris.Adeniyi-Jones@arm.com    if (opModeIs64(mode))
8085877Shsul@eecs.umich.edu        callNum = tc->readIntReg(INTREG_X8);
80910318Sandreas.hansson@arm.com    else
81010318Sandreas.hansson@arm.com        callNum = tc->readIntReg(INTREG_R7);
8115877Shsul@eecs.umich.edu    Fault fault;
8125877Shsul@eecs.umich.edu    tc->syscall(callNum, &fault);
8135877Shsul@eecs.umich.edu
8145877Shsul@eecs.umich.edu    // Advance the PC since that won't happen automatically.
81510486Stjablin@gmail.com    PCState pc = tc->pcState();
81610486Stjablin@gmail.com    assert(inst);
8175877Shsul@eecs.umich.edu    inst->advancePC(pc);
81810027SChris.Adeniyi-Jones@arm.com    tc->pcState(pc);
81910027SChris.Adeniyi-Jones@arm.com}
8205877Shsul@eecs.umich.edu
8218601Ssteve.reinhardt@amd.combool
8225877Shsul@eecs.umich.eduSupervisorCall::routeToHyp(ThreadContext *tc) const
8235877Shsul@eecs.umich.edu{
8245877Shsul@eecs.umich.edu    bool toHyp;
82510027SChris.Adeniyi-Jones@arm.com
8265877Shsul@eecs.umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
8275877Shsul@eecs.umich.edu    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
8285877Shsul@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
82910027SChris.Adeniyi-Jones@arm.com
83010027SChris.Adeniyi-Jones@arm.com    // if in Hyp mode then stay in Hyp mode
83110027SChris.Adeniyi-Jones@arm.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
83210027SChris.Adeniyi-Jones@arm.com    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
83310027SChris.Adeniyi-Jones@arm.com    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
83410027SChris.Adeniyi-Jones@arm.com    return toHyp;
8355877Shsul@eecs.umich.edu}
83610027SChris.Adeniyi-Jones@arm.com
83710027SChris.Adeniyi-Jones@arm.comExceptionClass
83810027SChris.Adeniyi-Jones@arm.comSupervisorCall::ec(ThreadContext *tc) const
83910027SChris.Adeniyi-Jones@arm.com{
84010027SChris.Adeniyi-Jones@arm.com    return (overrideEc != EC_INVALID) ? overrideEc :
84110027SChris.Adeniyi-Jones@arm.com        (from64 ? EC_SVC_64 : vals.ec);
84210027SChris.Adeniyi-Jones@arm.com}
84310027SChris.Adeniyi-Jones@arm.com
84410027SChris.Adeniyi-Jones@arm.comuint32_t
84510027SChris.Adeniyi-Jones@arm.comSupervisorCall::iss() const
84610027SChris.Adeniyi-Jones@arm.com{
84710027SChris.Adeniyi-Jones@arm.com    // Even if we have a 24 bit imm from an arm32 instruction then we only use
84810027SChris.Adeniyi-Jones@arm.com    // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC).
8495877Shsul@eecs.umich.edu    return issRaw & 0xFFFF;
8505877Shsul@eecs.umich.edu}
8515877Shsul@eecs.umich.edu
85210027SChris.Adeniyi-Jones@arm.comuint32_t
85310027SChris.Adeniyi-Jones@arm.comSecureMonitorCall::iss() const
8548601Ssteve.reinhardt@amd.com{
85510027SChris.Adeniyi-Jones@arm.com    if (from64)
8565877Shsul@eecs.umich.edu        return bits(machInst, 20, 5);
8575877Shsul@eecs.umich.edu    return 0;
8581999SN/A}
859378SN/A
860360SN/AExceptionClass
8611450SN/AUndefinedInstruction::ec(ThreadContext *tc) const
8623114Sgblack@eecs.umich.edu{
8632680Sktlim@umich.edu    // If UndefinedInstruction is routed to hypervisor,
864360SN/A    // HSR.EC field is 0.
865360SN/A    if (hypRouted)
866360SN/A        return EC_UNKNOWN;
8676701Sgblack@eecs.umich.edu    else
8688852Sandreas.hansson@arm.com        return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
8696701Sgblack@eecs.umich.edu}
8706701Sgblack@eecs.umich.edu
8716701Sgblack@eecs.umich.edu
8726701Sgblack@eecs.umich.eduHypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) :
873360SN/A        ArmFaultVals<HypervisorCall>(_machInst, _imm)
8743669Sbinkertn@umich.edu{}
8753669Sbinkertn@umich.edu
8763669Sbinkertn@umich.eduExceptionClass
877360SN/AHypervisorCall::ec(ThreadContext *tc) const
878360SN/A{
879360SN/A    return from64 ? EC_HVC_64 : vals.ec;
880360SN/A}
8812218SN/A
882360SN/AExceptionClass
8838706Sandreas.hansson@arm.comHypervisorTrap::ec(ThreadContext *tc) const
884360SN/A{
8851458SN/A    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
886360SN/A}
887360SN/A
888360SN/Atemplate<class T>
8895074Ssaidi@eecs.umich.eduFaultOffset
8905074Ssaidi@eecs.umich.eduArmFaultVals<T>::offset(ThreadContext *tc)
8915074Ssaidi@eecs.umich.edu{
8925074Ssaidi@eecs.umich.edu    bool isHypTrap = false;
8935074Ssaidi@eecs.umich.edu
8945074Ssaidi@eecs.umich.edu    // Normally we just use the exception vector from the table at the top if
8955074Ssaidi@eecs.umich.edu    // this file, however if this exception has caused a transition to hype
8965074Ssaidi@eecs.umich.edu    // mode, and its an exception type that would only do this if it has been
8976701Sgblack@eecs.umich.edu    // trapped then we use the hyp trap vector instead of the normal vector
8988852Sandreas.hansson@arm.com    if (vals.hypTrappable) {
8996701Sgblack@eecs.umich.edu        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
9005074Ssaidi@eecs.umich.edu        if (cpsr.mode == MODE_HYP) {
9016701Sgblack@eecs.umich.edu            CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
9025074Ssaidi@eecs.umich.edu            isHypTrap = spsr.mode != MODE_HYP;
9035074Ssaidi@eecs.umich.edu        }
9045074Ssaidi@eecs.umich.edu    }
9055074Ssaidi@eecs.umich.edu    return isHypTrap ? 0x14 : vals.offset;
9065208Ssaidi@eecs.umich.edu}
9075208Ssaidi@eecs.umich.edu
9085208Ssaidi@eecs.umich.edutemplate<class T>
9095208Ssaidi@eecs.umich.eduFaultOffset
9105074Ssaidi@eecs.umich.eduArmFaultVals<T>::offset64(ThreadContext *tc)
9115074Ssaidi@eecs.umich.edu{
9125208Ssaidi@eecs.umich.edu    if (toEL == fromEL) {
9135074Ssaidi@eecs.umich.edu        if (opModeIsT(fromMode))
9145074Ssaidi@eecs.umich.edu            return vals.currELTOffset;
9155074Ssaidi@eecs.umich.edu        return vals.currELHOffset;
9165074Ssaidi@eecs.umich.edu    } else {
9178706Sandreas.hansson@arm.com        bool lower_32 = false;
9185074Ssaidi@eecs.umich.edu        if (toEL == EL3) {
9195074Ssaidi@eecs.umich.edu            if (!inSecureState(tc) && ArmSystem::haveEL(tc, EL2))
9205074Ssaidi@eecs.umich.edu                lower_32 = ELIs32(tc, EL2);
9215074Ssaidi@eecs.umich.edu            else
9225074Ssaidi@eecs.umich.edu                lower_32 = ELIs32(tc, EL1);
92310027SChris.Adeniyi-Jones@arm.com        } else {
92410027SChris.Adeniyi-Jones@arm.com            lower_32 = ELIs32(tc, static_cast<ExceptionLevel>(toEL - 1));
92510027SChris.Adeniyi-Jones@arm.com        }
92610027SChris.Adeniyi-Jones@arm.com
92710027SChris.Adeniyi-Jones@arm.com        if (lower_32)
92810027SChris.Adeniyi-Jones@arm.com            return vals.lowerEL32Offset;
92910027SChris.Adeniyi-Jones@arm.com        return vals.lowerEL64Offset;
93010027SChris.Adeniyi-Jones@arm.com    }
93110027SChris.Adeniyi-Jones@arm.com}
93210793Sbrandon.potter@amd.com
93310027SChris.Adeniyi-Jones@arm.com// void
93410027SChris.Adeniyi-Jones@arm.com// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx)
93510027SChris.Adeniyi-Jones@arm.com// {
93610027SChris.Adeniyi-Jones@arm.com//     ESR esr = 0;
93710027SChris.Adeniyi-Jones@arm.com//     esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32;
93810027SChris.Adeniyi-Jones@arm.com//     esr.il = !machInst.thumb;
93910027SChris.Adeniyi-Jones@arm.com//     if (machInst.aarch64)
94010027SChris.Adeniyi-Jones@arm.com//         esr.imm16 = bits(machInst.instBits, 20, 5);
94110027SChris.Adeniyi-Jones@arm.com//     else if (machInst.thumb)
94210027SChris.Adeniyi-Jones@arm.com//         esr.imm16 = bits(machInst.instBits, 7, 0);
94310027SChris.Adeniyi-Jones@arm.com//     else
94410027SChris.Adeniyi-Jones@arm.com//         esr.imm16 = bits(machInst.instBits, 15, 0);
94510027SChris.Adeniyi-Jones@arm.com//     tc->setMiscReg(esr_idx, esr);
94610027SChris.Adeniyi-Jones@arm.com// }
94710027SChris.Adeniyi-Jones@arm.com
94810027SChris.Adeniyi-Jones@arm.comvoid
94910027SChris.Adeniyi-Jones@arm.comSecureMonitorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
95010027SChris.Adeniyi-Jones@arm.com{
95110027SChris.Adeniyi-Jones@arm.com    if (FullSystem) {
95210027SChris.Adeniyi-Jones@arm.com        ArmFault::invoke(tc, inst);
95310027SChris.Adeniyi-Jones@arm.com        return;
95410027SChris.Adeniyi-Jones@arm.com    }
95510027SChris.Adeniyi-Jones@arm.com}
95610027SChris.Adeniyi-Jones@arm.com
95710027SChris.Adeniyi-Jones@arm.comExceptionClass
95810027SChris.Adeniyi-Jones@arm.comSecureMonitorCall::ec(ThreadContext *tc) const
95910027SChris.Adeniyi-Jones@arm.com{
9601999SN/A    return (from64 ? EC_SMC_64 : vals.ec);
9611999SN/A}
9621999SN/A
9633114Sgblack@eecs.umich.edubool
9642680Sktlim@umich.eduSupervisorTrap::routeToHyp(ThreadContext *tc) const
9651999SN/A{
9666701Sgblack@eecs.umich.edu    bool toHyp = false;
9676701Sgblack@eecs.umich.edu
9686701Sgblack@eecs.umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
9691999SN/A    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
9701999SN/A    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
9711999SN/A
9721999SN/A    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
9731999SN/A    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.el == EL0);
9742764Sstever@eecs.umich.edu    return toHyp;
9752064SN/A}
9762064SN/A
9772064SN/Auint32_t
9782064SN/ASupervisorTrap::iss() const
9791999SN/A{
9802064SN/A    // If SupervisorTrap is routed to hypervisor, iss field is 0.
9811999SN/A    if (hypRouted) {
9821999SN/A        return 0;
9832218SN/A    }
9841999SN/A    return issRaw;
9858706Sandreas.hansson@arm.com}
9861999SN/A
9871999SN/AExceptionClass
9881999SN/ASupervisorTrap::ec(ThreadContext *tc) const
9891999SN/A{
9901999SN/A    if (hypRouted)
991378SN/A        return EC_UNKNOWN;
992360SN/A    else
9931450SN/A        return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
9943114Sgblack@eecs.umich.edu}
9952680Sktlim@umich.edu
996360SN/AExceptionClass
997360SN/ASecureMonitorTrap::ec(ThreadContext *tc) const
998360SN/A{
9996701Sgblack@eecs.umich.edu    return (overrideEc != EC_INVALID) ? overrideEc :
10008852Sandreas.hansson@arm.com        (from64 ? EC_SMC_64 : vals.ec);
10016701Sgblack@eecs.umich.edu}
10026701Sgblack@eecs.umich.edu
10036701Sgblack@eecs.umich.edutemplate<class T>
10046701Sgblack@eecs.umich.eduvoid
1005360SN/AAbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
10063669Sbinkertn@umich.edu{
10073669Sbinkertn@umich.edu    if (tranMethod == ArmFault::UnknownTran) {
10083669Sbinkertn@umich.edu        tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran
1009360SN/A                                             : ArmFault::VmsaTran;
1010360SN/A
1011360SN/A        if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) {
1012360SN/A            // See ARM ARM B3-1416
10131458SN/A            bool override_LPAE = false;
1014360SN/A            TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S);
10158706Sandreas.hansson@arm.com            TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS);
1016360SN/A            if (ttbcr_s.eae) {
10171458SN/A                override_LPAE = true;
1018360SN/A            } else {
1019360SN/A                // Unimplemented code option, not seen in testing.  May need
10201999SN/A                // extension according to the manual exceprt above.
10211999SN/A                DPRINTF(Faults, "Warning: Incomplete translation method "
10221999SN/A                        "override detected.\n");
10233114Sgblack@eecs.umich.edu            }
10242680Sktlim@umich.edu            if (override_LPAE)
10251999SN/A                tranMethod = ArmFault::LpaeTran;
10261999SN/A        }
10271999SN/A    }
10286701Sgblack@eecs.umich.edu
10298852Sandreas.hansson@arm.com    if (source == ArmFault::AsynchronousExternalAbort) {
10306701Sgblack@eecs.umich.edu        tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
10316701Sgblack@eecs.umich.edu    }
10326701Sgblack@eecs.umich.edu    // Get effective fault source encoding
10336701Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
10341999SN/A
10353669Sbinkertn@umich.edu    // source must be determined BEFORE invoking generic routines which will
10363669Sbinkertn@umich.edu    // try to set hsr etc. and are based upon source!
10373669Sbinkertn@umich.edu    ArmFaultVals<T>::invoke(tc, inst);
10382764Sstever@eecs.umich.edu
10392064SN/A    if (!this->to64) {  // AArch32
10402064SN/A        FSR  fsr  = getFsr(tc);
10412064SN/A        if (cpsr.mode == MODE_HYP) {
10421999SN/A            tc->setMiscReg(T::HFarIndex, faultAddr);
10431999SN/A        } else if (stage2) {
10442064SN/A            tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf);
10451999SN/A            tc->setMiscReg(T::HFarIndex,  OVAddr);
10461999SN/A        } else {
10471999SN/A            tc->setMiscReg(T::FsrIndex, fsr);
10481999SN/A            tc->setMiscReg(T::FarIndex, faultAddr);
10498706Sandreas.hansson@arm.com        }
10501999SN/A        DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\
10511999SN/A                "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod);
10521999SN/A    } else {  // AArch64
10531999SN/A        // Set the FAR register.  Nothing else to do if we are in AArch64 state
1054378SN/A        // because the syndrome register has already been set inside invoke64()
1055360SN/A        if (stage2) {
10561450SN/A            // stage 2 fault, set HPFAR_EL2 to the faulting IPA
10573114Sgblack@eecs.umich.edu            // and FAR_EL2 to the Original VA
10582680Sktlim@umich.edu            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr);
1059360SN/A            tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
10606701Sgblack@eecs.umich.edu
10616701Sgblack@eecs.umich.edu            DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
10626701Sgblack@eecs.umich.edu                    OVAddr, faultAddr);
1063360SN/A        } else {
10641969SN/A            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
1065360SN/A        }
1066360SN/A    }
10671458SN/A}
1068360SN/A
1069360SN/Atemplate<class T>
1070360SN/Avoid
1071360SN/AAbortFault<T>::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
1072360SN/A{
10731458SN/A    srcEncoded = getFaultStatusCode(tc);
1074360SN/A    if (srcEncoded == ArmFault::FaultSourceInvalid) {
10758706Sandreas.hansson@arm.com        panic("Invalid fault source\n");
10762021SN/A    }
10771458SN/A    ArmFault::setSyndrome(tc, syndrome_reg);
1078360SN/A}
1079360SN/A
1080360SN/Atemplate<class T>
10811706SN/Auint8_t
10821706SN/AAbortFault<T>::getFaultStatusCode(ThreadContext *tc) const
10831706SN/A{
10843114Sgblack@eecs.umich.edu
10852680Sktlim@umich.edu    panic_if(!this->faultUpdated,
10861706SN/A             "Trying to use un-updated ArmFault internal variables\n");
10871706SN/A
10881706SN/A    uint8_t fsc = 0;
10896701Sgblack@eecs.umich.edu
10908852Sandreas.hansson@arm.com    if (!this->to64) {
10916701Sgblack@eecs.umich.edu        // AArch32
10926701Sgblack@eecs.umich.edu        assert(tranMethod != ArmFault::UnknownTran);
10936701Sgblack@eecs.umich.edu        if (tranMethod == ArmFault::LpaeTran) {
10946701Sgblack@eecs.umich.edu            fsc = ArmFault::longDescFaultSources[source];
10951706SN/A        } else {
10963669Sbinkertn@umich.edu            fsc = ArmFault::shortDescFaultSources[source];
10973669Sbinkertn@umich.edu        }
10983669Sbinkertn@umich.edu    } else {
10991706SN/A        // AArch64
11001706SN/A        fsc = ArmFault::aarch64FaultSources[source];
11011706SN/A    }
11021706SN/A
11032218SN/A    return fsc;
11041706SN/A}
11058706Sandreas.hansson@arm.com
11061706SN/Atemplate<class T>
11071706SN/AFSR
11081706SN/AAbortFault<T>::getFsr(ThreadContext *tc) const
11091706SN/A{
11101706SN/A    FSR fsr = 0;
11111706SN/A
11121706SN/A    auto fsc = getFaultStatusCode(tc);
11131706SN/A
11143114Sgblack@eecs.umich.edu    // AArch32
11152680Sktlim@umich.edu    assert(tranMethod != ArmFault::UnknownTran);
11161706SN/A    if (tranMethod == ArmFault::LpaeTran) {
11176701Sgblack@eecs.umich.edu        fsr.status = fsc;
11186701Sgblack@eecs.umich.edu        fsr.lpae   = 1;
11196701Sgblack@eecs.umich.edu    } else {
11201706SN/A        fsr.fsLow  = bits(fsc, 3, 0);
11211706SN/A        fsr.fsHigh = bits(fsc, 4);
11221706SN/A        fsr.domain = static_cast<uint8_t>(domain);
11231706SN/A    }
11241706SN/A
11251706SN/A    fsr.wnr = (write ? 1 : 0);
11261706SN/A    fsr.ext = 0;
11271706SN/A
11282218SN/A    return fsr;
11291706SN/A}
11308706Sandreas.hansson@arm.com
11311706SN/Atemplate<class T>
11321706SN/Abool
11331706SN/AAbortFault<T>::abortDisable(ThreadContext *tc)
11341706SN/A{
11351706SN/A    if (ArmSystem::haveSecurity(tc)) {
11361999SN/A        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
11371999SN/A        return (!scr.ns || scr.aw);
11381999SN/A    }
11393114Sgblack@eecs.umich.edu    return true;
11402680Sktlim@umich.edu}
11411999SN/A
11426701Sgblack@eecs.umich.edutemplate<class T>
11436701Sgblack@eecs.umich.eduvoid
11441999SN/AAbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val)
11451999SN/A{
11461999SN/A    switch (id)
11471999SN/A    {
11481999SN/A      case ArmFault::S1PTW:
11498852Sandreas.hansson@arm.com        s1ptw = val;
11506701Sgblack@eecs.umich.edu        break;
11516701Sgblack@eecs.umich.edu      case ArmFault::OVA:
11521999SN/A        OVAddr = val;
11536227Snate@binkert.org        break;
11541999SN/A
11552461SN/A      // Just ignore unknown ID's
11568852Sandreas.hansson@arm.com      default:
11578852Sandreas.hansson@arm.com        break;
11588737Skoansin.tan@gmail.com    }
11591999SN/A}
11608852Sandreas.hansson@arm.com
11618852Sandreas.hansson@arm.comtemplate<class T>
11621999SN/Auint32_t
11631999SN/AAbortFault<T>::iss() const
11641999SN/A{
11651999SN/A    uint32_t val;
11666227Snate@binkert.org
11671999SN/A    val  = srcEncoded & 0x3F;
11681999SN/A    val |= write << 6;
11691999SN/A    val |= s1ptw << 7;
11702218SN/A    return (val);
11711999SN/A}
117210629Sjthestness@gmail.com
11731999SN/Atemplate<class T>
11741999SN/Abool
11751999SN/AAbortFault<T>::isMMUFault() const
1176378SN/A{
1177378SN/A    // NOTE: Not relying on LL information being aligned to lowest bits here
1178378SN/A    return
1179378SN/A         (source == ArmFault::AlignmentFault)     ||
1180378SN/A        ((source >= ArmFault::TranslationLL) &&
11818324Ssteve.reinhardt@amd.com         (source <  ArmFault::TranslationLL + 4)) ||
11828324Ssteve.reinhardt@amd.com        ((source >= ArmFault::AccessFlagLL) &&
1183360SN/A         (source <  ArmFault::AccessFlagLL + 4))  ||
11841450SN/A        ((source >= ArmFault::DomainLL) &&
11853114Sgblack@eecs.umich.edu         (source <  ArmFault::DomainLL + 4))      ||
1186360SN/A        ((source >= ArmFault::PermissionLL) &&
11876701Sgblack@eecs.umich.edu         (source <  ArmFault::PermissionLL + 4));
11886701Sgblack@eecs.umich.edu}
11896701Sgblack@eecs.umich.edu
11906701Sgblack@eecs.umich.eduExceptionClass
11916701Sgblack@eecs.umich.eduPrefetchAbort::ec(ThreadContext *tc) const
11928324Ssteve.reinhardt@amd.com{
119310486Stjablin@gmail.com    if (to64) {
1194360SN/A        // AArch64
11959008Sgblack@eecs.umich.edu        if (toEL == fromEL)
11969008Sgblack@eecs.umich.edu            return EC_PREFETCH_ABORT_CURR_EL;
11979008Sgblack@eecs.umich.edu        else
11988324Ssteve.reinhardt@amd.com            return EC_PREFETCH_ABORT_LOWER_EL;
11998324Ssteve.reinhardt@amd.com    } else {
12008324Ssteve.reinhardt@amd.com        // AArch32
12018324Ssteve.reinhardt@amd.com        // Abort faults have different EC codes depending on whether
12028324Ssteve.reinhardt@amd.com        // the fault originated within HYP mode, or not. So override
12038324Ssteve.reinhardt@amd.com        // the method and add the extra adjustment of the EC value.
12048324Ssteve.reinhardt@amd.com
12058324Ssteve.reinhardt@amd.com        ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec;
12068324Ssteve.reinhardt@amd.com
12078324Ssteve.reinhardt@amd.com        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
12088324Ssteve.reinhardt@amd.com        if (spsr.mode == MODE_HYP) {
12098324Ssteve.reinhardt@amd.com            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
12108324Ssteve.reinhardt@amd.com        }
12118324Ssteve.reinhardt@amd.com        return ec;
12128324Ssteve.reinhardt@amd.com    }
12135877Shsul@eecs.umich.edu}
121410486Stjablin@gmail.com
121510486Stjablin@gmail.combool
121610318Sandreas.hansson@arm.comPrefetchAbort::routeToMonitor(ThreadContext *tc) const
121710486Stjablin@gmail.com{
12182544SN/A    SCR scr = 0;
121910486Stjablin@gmail.com    if (from64)
122010486Stjablin@gmail.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
12212544SN/A    else
1222360SN/A        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1223360SN/A
12248600Ssteve.reinhardt@amd.com    return scr.ea && !isMMUFault();
12258600Ssteve.reinhardt@amd.com}
12268600Ssteve.reinhardt@amd.com
12278600Ssteve.reinhardt@amd.combool
12288600Ssteve.reinhardt@amd.comPrefetchAbort::routeToHyp(ThreadContext *tc) const
12298600Ssteve.reinhardt@amd.com{
12308600Ssteve.reinhardt@amd.com    bool toHyp;
12318600Ssteve.reinhardt@amd.com
12328600Ssteve.reinhardt@amd.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
12338600Ssteve.reinhardt@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
12348600Ssteve.reinhardt@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
12358600Ssteve.reinhardt@amd.com    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
12368600Ssteve.reinhardt@amd.com
12378600Ssteve.reinhardt@amd.com    // if in Hyp mode then stay in Hyp mode
123810485SMichael.Adler@intel.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
123910485SMichael.Adler@intel.com    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
12408600Ssteve.reinhardt@amd.com    toHyp |= (stage2 ||
12418600Ssteve.reinhardt@amd.com                ( (source ==               DebugEvent) && hdcr.tde && (cpsr.mode !=  MODE_HYP)) ||
12428600Ssteve.reinhardt@amd.com                ( (source == SynchronousExternalAbort) && hcr.tge  && (cpsr.mode == MODE_USER))
12438600Ssteve.reinhardt@amd.com             ) && !inSecureState(tc);
12448600Ssteve.reinhardt@amd.com    return toHyp;
12458600Ssteve.reinhardt@amd.com}
12462544SN/A
12472544SN/AExceptionClass
12488600Ssteve.reinhardt@amd.comDataAbort::ec(ThreadContext *tc) const
12498600Ssteve.reinhardt@amd.com{
12508600Ssteve.reinhardt@amd.com    if (to64) {
12518600Ssteve.reinhardt@amd.com        // AArch64
12528600Ssteve.reinhardt@amd.com        if (source == ArmFault::AsynchronousExternalAbort) {
12538600Ssteve.reinhardt@amd.com            panic("Asynchronous External Abort should be handled with "
12548600Ssteve.reinhardt@amd.com                    "SystemErrors (SErrors)!");
12558600Ssteve.reinhardt@amd.com        }
12568600Ssteve.reinhardt@amd.com        if (toEL == fromEL)
12578600Ssteve.reinhardt@amd.com            return EC_DATA_ABORT_CURR_EL;
12586672Sgblack@eecs.umich.edu        else
12598600Ssteve.reinhardt@amd.com            return EC_DATA_ABORT_LOWER_EL;
12608601Ssteve.reinhardt@amd.com    } else {
12612544SN/A        // AArch32
12621458SN/A        // Abort faults have different EC codes depending on whether
1263360SN/A        // the fault originated within HYP mode, or not. So override
1264360SN/A        // the method and add the extra adjustment of the EC value.
1265378SN/A
1266360SN/A        ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec;
12671450SN/A
12683114Sgblack@eecs.umich.edu        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
12692680Sktlim@umich.edu        if (spsr.mode == MODE_HYP) {
1270360SN/A            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
12716701Sgblack@eecs.umich.edu        }
12726701Sgblack@eecs.umich.edu        return ec;
12736701Sgblack@eecs.umich.edu    }
1274360SN/A}
1275360SN/A
12762064SN/Abool
12775877Shsul@eecs.umich.eduDataAbort::routeToMonitor(ThreadContext *tc) const
12782064SN/A{
12798737Skoansin.tan@gmail.com    SCR scr = 0;
12808737Skoansin.tan@gmail.com    if (from64)
12812064SN/A        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1282360SN/A    else
12835877Shsul@eecs.umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
12845877Shsul@eecs.umich.edu
12855877Shsul@eecs.umich.edu    return scr.ea && !isMMUFault();
12868737Skoansin.tan@gmail.com}
12878737Skoansin.tan@gmail.com
12885877Shsul@eecs.umich.edubool
12895877Shsul@eecs.umich.eduDataAbort::routeToHyp(ThreadContext *tc) const
12902064SN/A{
129110794Sbrandon.potter@amd.com    bool toHyp;
129210794Sbrandon.potter@amd.com
12932064SN/A    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1294360SN/A    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1295360SN/A    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
12968706Sandreas.hansson@arm.com    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
12971458SN/A
1298360SN/A    // if in Hyp mode then stay in Hyp mode
1299360SN/A    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
130010796Sbrandon.potter@amd.com    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
130110796Sbrandon.potter@amd.com    toHyp |= (stage2 ||
130210796Sbrandon.potter@amd.com                ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) ||
130310796Sbrandon.potter@amd.com                                               ((source == DebugEvent) && hdcr.tde) )
130410796Sbrandon.potter@amd.com                ) ||
130510796Sbrandon.potter@amd.com                ( (cpsr.mode == MODE_USER) && hcr.tge &&
130610796Sbrandon.potter@amd.com                  ((source == AlignmentFault)            ||
130710796Sbrandon.potter@amd.com                   (source == SynchronousExternalAbort))
130810796Sbrandon.potter@amd.com                )
130910796Sbrandon.potter@amd.com             ) && !inSecureState(tc);
131010796Sbrandon.potter@amd.com    return toHyp;
131110796Sbrandon.potter@amd.com}
131210796Sbrandon.potter@amd.com
131310796Sbrandon.potter@amd.comuint32_t
131410796Sbrandon.potter@amd.comDataAbort::iss() const
131510796Sbrandon.potter@amd.com{
131610796Sbrandon.potter@amd.com    uint32_t val;
131710796Sbrandon.potter@amd.com
131810796Sbrandon.potter@amd.com    // Add on the data abort specific fields to the generic abort ISS value
1319378SN/A    val  = AbortFault<DataAbort>::iss();
1320360SN/A    // ISS is valid if not caused by a stage 1 page table walk, and when taken
13211450SN/A    // to AArch64 only when directed to EL2
13223114Sgblack@eecs.umich.edu    if (!s1ptw && (!to64 || toEL == EL2)) {
13232680Sktlim@umich.edu        val |= isv << 24;
1324360SN/A        if (isv) {
13256701Sgblack@eecs.umich.edu            val |= sas << 22;
13266701Sgblack@eecs.umich.edu            val |= sse << 21;
1327360SN/A            val |= srt << 16;
132810796Sbrandon.potter@amd.com            // AArch64 only. These assignments are safe on AArch32 as well
1329360SN/A            // because these vars are initialized to false
13306109Ssanchezd@stanford.edu            val |= sf << 15;
13316109Ssanchezd@stanford.edu            val |= ar << 14;
1332360SN/A        }
13338706Sandreas.hansson@arm.com    }
1334360SN/A    return (val);
13351458SN/A}
1336360SN/A
1337360SN/Avoid
1338360SN/ADataAbort::annotate(AnnotationIDs id, uint64_t val)
13391999SN/A{
13401999SN/A    AbortFault<DataAbort>::annotate(id, val);
13411999SN/A    switch (id)
13423114Sgblack@eecs.umich.edu    {
13432680Sktlim@umich.edu      case SAS:
13441999SN/A        isv = true;
13451999SN/A        sas = val;
13461999SN/A        break;
13476701Sgblack@eecs.umich.edu      case SSE:
13488852Sandreas.hansson@arm.com        isv = true;
13496701Sgblack@eecs.umich.edu        sse = val;
13506701Sgblack@eecs.umich.edu        break;
13516701Sgblack@eecs.umich.edu      case SRT:
13521999SN/A        isv = true;
13536701Sgblack@eecs.umich.edu        srt = val;
13546701Sgblack@eecs.umich.edu        break;
13558706Sandreas.hansson@arm.com      case SF:
13561999SN/A        isv = true;
13571999SN/A        sf  = val;
13581999SN/A        break;
13591999SN/A      case AR:
13608737Skoansin.tan@gmail.com        isv = true;
13618737Skoansin.tan@gmail.com        ar  = val;
13621999SN/A        break;
13633669Sbinkertn@umich.edu      // Just ignore unknown ID's
13643669Sbinkertn@umich.edu      default:
13653669Sbinkertn@umich.edu        break;
13663669Sbinkertn@umich.edu    }
13671999SN/A}
13681999SN/A
13691999SN/Avoid
13701999SN/AVirtualDataAbort::invoke(ThreadContext *tc, const StaticInstPtr &inst)
13711999SN/A{
13721999SN/A    AbortFault<VirtualDataAbort>::invoke(tc, inst);
13731999SN/A    HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
1374378SN/A    hcr.va = 0;
1375360SN/A    tc->setMiscRegNoEffect(MISCREG_HCR, hcr);
13761450SN/A}
13773114Sgblack@eecs.umich.edu
13782680Sktlim@umich.edubool
1379360SN/AInterrupt::routeToMonitor(ThreadContext *tc) const
13806701Sgblack@eecs.umich.edu{
13816701Sgblack@eecs.umich.edu    assert(ArmSystem::haveSecurity(tc));
13826701Sgblack@eecs.umich.edu    SCR scr = 0;
1383360SN/A    if (from64)
13843670Sbinkertn@umich.edu        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
13853670Sbinkertn@umich.edu    else
1386360SN/A        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1387360SN/A    return scr.irq;
1388360SN/A}
1389360SN/A
1390360SN/Abool
1391360SN/AInterrupt::routeToHyp(ThreadContext *tc) const
1392360SN/A{
1393360SN/A    bool toHyp;
1394360SN/A
1395360SN/A    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1396360SN/A    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1397360SN/A    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1398360SN/A    // Determine whether IRQs are routed to Hyp mode.
1399360SN/A    toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) ||
1400360SN/A            (cpsr.mode == MODE_HYP);
1401360SN/A    return toHyp;
1402360SN/A}
14033670Sbinkertn@umich.edu
14043670Sbinkertn@umich.edubool
140510796Sbrandon.potter@amd.comInterrupt::abortDisable(ThreadContext *tc)
14068737Skoansin.tan@gmail.com{
14078737Skoansin.tan@gmail.com    if (ArmSystem::haveSecurity(tc)) {
14083670Sbinkertn@umich.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
14093670Sbinkertn@umich.edu        return (!scr.ns || scr.aw);
14103670Sbinkertn@umich.edu    }
14113670Sbinkertn@umich.edu    return true;
14123670Sbinkertn@umich.edu}
14133670Sbinkertn@umich.edu
14143670Sbinkertn@umich.eduVirtualInterrupt::VirtualInterrupt()
14153670Sbinkertn@umich.edu{}
14163670Sbinkertn@umich.edu
14173670Sbinkertn@umich.edubool
14183670Sbinkertn@umich.eduFastInterrupt::routeToMonitor(ThreadContext *tc) const
14193670Sbinkertn@umich.edu{
14203670Sbinkertn@umich.edu    assert(ArmSystem::haveSecurity(tc));
14218706Sandreas.hansson@arm.com    SCR scr = 0;
1422360SN/A    if (from64)
14231458SN/A        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1424360SN/A    else
1425360SN/A        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
14266683Stjones1@inf.ed.ac.uk    return scr.fiq;
14276683Stjones1@inf.ed.ac.uk}
14286683Stjones1@inf.ed.ac.uk
14296683Stjones1@inf.ed.ac.ukbool
14306683Stjones1@inf.ed.ac.ukFastInterrupt::routeToHyp(ThreadContext *tc) const
14316683Stjones1@inf.ed.ac.uk{
14326701Sgblack@eecs.umich.edu    bool toHyp;
14336701Sgblack@eecs.umich.edu
14346683Stjones1@inf.ed.ac.uk    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
14356683Stjones1@inf.ed.ac.uk    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
14367823Ssteve.reinhardt@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
14376683Stjones1@inf.ed.ac.uk    // Determine whether IRQs are routed to Hyp mode.
14386683Stjones1@inf.ed.ac.uk    toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) ||
14396683Stjones1@inf.ed.ac.uk            (cpsr.mode == MODE_HYP);
14406683Stjones1@inf.ed.ac.uk    return toHyp;
14416683Stjones1@inf.ed.ac.uk}
14426683Stjones1@inf.ed.ac.uk
14438737Skoansin.tan@gmail.combool
14446683Stjones1@inf.ed.ac.ukFastInterrupt::abortDisable(ThreadContext *tc)
14456683Stjones1@inf.ed.ac.uk{
14468706Sandreas.hansson@arm.com    if (ArmSystem::haveSecurity(tc)) {
14476683Stjones1@inf.ed.ac.uk        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
14486683Stjones1@inf.ed.ac.uk        return (!scr.ns || scr.aw);
14496683Stjones1@inf.ed.ac.uk    }
14506683Stjones1@inf.ed.ac.uk    return true;
14512553SN/A}
14526684Stjones1@inf.ed.ac.uk
14536684Stjones1@inf.ed.ac.ukbool
14546684Stjones1@inf.ed.ac.ukFastInterrupt::fiqDisable(ThreadContext *tc)
14556684Stjones1@inf.ed.ac.uk{
14566684Stjones1@inf.ed.ac.uk    if (ArmSystem::haveVirtualization(tc)) {
14576684Stjones1@inf.ed.ac.uk        return true;
14586684Stjones1@inf.ed.ac.uk    } else if (ArmSystem::haveSecurity(tc)) {
145910796Sbrandon.potter@amd.com        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
14606684Stjones1@inf.ed.ac.uk        return (!scr.ns || scr.fw);
14616684Stjones1@inf.ed.ac.uk    }
14626701Sgblack@eecs.umich.edu    return true;
14636701Sgblack@eecs.umich.edu}
14646684Stjones1@inf.ed.ac.uk
14656684Stjones1@inf.ed.ac.ukVirtualFastInterrupt::VirtualFastInterrupt()
14668737Skoansin.tan@gmail.com{}
14678852Sandreas.hansson@arm.com
14688852Sandreas.hansson@arm.comvoid
14696684Stjones1@inf.ed.ac.ukPCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
14706684Stjones1@inf.ed.ac.uk{
14716684Stjones1@inf.ed.ac.uk    ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
14722553SN/A    assert(from64);
14732553SN/A    // Set the FAR
14741354SN/A    tc->setMiscReg(getFaultAddrReg64(), faultPC);
1475}
1476
1477bool
1478PCAlignmentFault::routeToHyp(ThreadContext *tc) const
1479{
1480    bool toHyp = false;
1481
1482    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1483    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
1484    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1485
1486    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
1487    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.el == EL0);
1488    return toHyp;
1489}
1490
1491SPAlignmentFault::SPAlignmentFault()
1492{}
1493
1494SystemError::SystemError()
1495{}
1496
1497void
1498SystemError::invoke(ThreadContext *tc, const StaticInstPtr &inst)
1499{
1500    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
1501    ArmFault::invoke(tc, inst);
1502}
1503
1504bool
1505SystemError::routeToMonitor(ThreadContext *tc) const
1506{
1507    assert(ArmSystem::haveSecurity(tc));
1508    assert(from64);
1509    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1510    return scr.ea;
1511}
1512
1513bool
1514SystemError::routeToHyp(ThreadContext *tc) const
1515{
1516    bool toHyp;
1517    assert(from64);
1518
1519    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1520    HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1521
1522    toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) ||
1523            (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc));
1524    return toHyp;
1525}
1526
1527
1528SoftwareBreakpoint::SoftwareBreakpoint(ExtMachInst _mach_inst, uint32_t _iss)
1529    : ArmFaultVals<SoftwareBreakpoint>(_mach_inst, _iss)
1530{}
1531
1532bool
1533SoftwareBreakpoint::routeToHyp(ThreadContext *tc) const
1534{
1535    assert(from64);
1536
1537    const bool have_el2 = ArmSystem::haveVirtualization(tc);
1538
1539    const HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
1540    const HDCR mdcr  = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
1541
1542    return have_el2 && !inSecureState(tc) && fromEL <= EL1 &&
1543        (hcr.tge || mdcr.tde);
1544}
1545
1546void
1547ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
1548    DPRINTF(Faults, "Invoking ArmSev Fault\n");
1549    if (!FullSystem)
1550        return;
1551
1552    // Set sev_mailbox to 1, clear the pending interrupt from remote
1553    // SEV execution and let pipeline continue as pcState is still
1554    // valid.
1555    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
1556    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0);
1557}
1558
1559// Instantiate all the templates to make the linker happy
1560template class ArmFaultVals<Reset>;
1561template class ArmFaultVals<UndefinedInstruction>;
1562template class ArmFaultVals<SupervisorCall>;
1563template class ArmFaultVals<SecureMonitorCall>;
1564template class ArmFaultVals<HypervisorCall>;
1565template class ArmFaultVals<PrefetchAbort>;
1566template class ArmFaultVals<DataAbort>;
1567template class ArmFaultVals<VirtualDataAbort>;
1568template class ArmFaultVals<HypervisorTrap>;
1569template class ArmFaultVals<Interrupt>;
1570template class ArmFaultVals<VirtualInterrupt>;
1571template class ArmFaultVals<FastInterrupt>;
1572template class ArmFaultVals<VirtualFastInterrupt>;
1573template class ArmFaultVals<SupervisorTrap>;
1574template class ArmFaultVals<SecureMonitorTrap>;
1575template class ArmFaultVals<PCAlignmentFault>;
1576template class ArmFaultVals<SPAlignmentFault>;
1577template class ArmFaultVals<SystemError>;
1578template class ArmFaultVals<SoftwareBreakpoint>;
1579template class ArmFaultVals<ArmSev>;
1580template class AbortFault<PrefetchAbort>;
1581template class AbortFault<DataAbort>;
1582template class AbortFault<VirtualDataAbort>;
1583
1584
1585IllegalInstSetStateFault::IllegalInstSetStateFault()
1586{}
1587
1588
1589} // namespace ArmISA
1590