faults.cc revision 13394:ebe487b6f18a
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"
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"
5211799Sbrandon.potter@amd.com#include "base/compiler.hh"
5311799Sbrandon.potter@amd.com#include "base/trace.hh"
5411799Sbrandon.potter@amd.com#include "cpu/base.hh"
5511799Sbrandon.potter@amd.com#include "cpu/thread_context.hh"
5611799Sbrandon.potter@amd.com#include "debug/Faults.hh"
5711799Sbrandon.potter@amd.com#include "sim/full_system.hh"
58360SN/A
59360SN/Anamespace ArmISA
60360SN/A{
61360SN/A
62360SN/Auint8_t ArmFault::shortDescFaultSources[] = {
63360SN/A    0x01,  // AlignmentFault
641809SN/A    0x04,  // InstructionCacheMaintenance
6511800Sbrandon.potter@amd.com    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
6611392Sbrandon.potter@amd.com    0x0c,  // SynchExtAbtOnTranslTableWalkL1
671809SN/A    0x0e,  // SynchExtAbtOnTranslTableWalkL2
6811392Sbrandon.potter@amd.com    0xff,  // SynchExtAbtOnTranslTableWalkL3 (INVALID)
6911383Sbrandon.potter@amd.com    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
703113Sgblack@eecs.umich.edu    0x1c,  // SynchPtyErrOnTranslTableWalkL1
7111799Sbrandon.potter@amd.com    0x1e,  // SynchPtyErrOnTranslTableWalkL2
7211759Sbrandon.potter@amd.com    0xff,  // SynchPtyErrOnTranslTableWalkL3 (INVALID)
7311812Sbaz21@cam.ac.uk    0xff,  // TranslationL0 (INVALID)
7411812Sbaz21@cam.ac.uk    0x05,  // TranslationL1
7511799Sbrandon.potter@amd.com    0x07,  // TranslationL2
768229Snate@binkert.org    0xff,  // TranslationL3 (INVALID)
778229Snate@binkert.org    0xff,  // AccessFlagL0 (INVALID)
7811594Santhony.gutierrez@amd.com    0x03,  // AccessFlagL1
797075Snate@binkert.org    0x06,  // AccessFlagL2
808229Snate@binkert.org    0xff,  // AccessFlagL3 (INVALID)
8111856Sbrandon.potter@amd.com    0xff,  // DomainL0 (INVALID)
827075Snate@binkert.org    0x09,  // DomainL1
83360SN/A    0x0b,  // DomainL2
8411800Sbrandon.potter@amd.com    0xff,  // DomainL3 (INVALID)
8511392Sbrandon.potter@amd.com    0xff,  // PermissionL0 (INVALID)
862462SN/A    0x0d,  // PermissionL1
871354SN/A    0x0f,  // PermissionL2
886216Snate@binkert.org    0xff,  // PermissionL3 (INVALID)
896658Snate@binkert.org    0x02,  // DebugEvent
902474SN/A    0x08,  // SynchronousExternalAbort
912680Sktlim@umich.edu    0x10,  // TLBConflictAbort
928229Snate@binkert.org    0x19,  // SynchPtyErrOnMemoryAccess
9310496Ssteve.reinhardt@amd.com    0x16,  // AsynchronousExternalAbort
948229Snate@binkert.org    0x18,  // AsynchPtyErrOnMemoryAccess
9511794Sbrandon.potter@amd.com    0xff,  // AddressSizeL0 (INVALID)
9610497Ssteve.reinhardt@amd.com    0xff,  // AddressSizeL1 (INVALID)
9711794Sbrandon.potter@amd.com    0xff,  // AddressSizeL2 (INVALID)
98360SN/A    0xff,  // AddressSizeL3 (INVALID)
9911794Sbrandon.potter@amd.com    0x40,  // PrefetchTLBMiss
100360SN/A    0x80   // PrefetchUncacheable
101360SN/A};
102360SN/A
103360SN/Astatic_assert(sizeof(ArmFault::shortDescFaultSources) ==
104360SN/A              ArmFault::NumFaultSources,
105360SN/A              "Invalid size of ArmFault::shortDescFaultSources[]");
106360SN/A
107360SN/Auint8_t ArmFault::longDescFaultSources[] = {
108360SN/A    0x21,  // AlignmentFault
109360SN/A    0xff,  // InstructionCacheMaintenance (INVALID)
110378SN/A    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
1111706SN/A    0x15,  // SynchExtAbtOnTranslTableWalkL1
11211851Sbrandon.potter@amd.com    0x16,  // SynchExtAbtOnTranslTableWalkL2
113378SN/A    0x17,  // SynchExtAbtOnTranslTableWalkL3
114378SN/A    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
115378SN/A    0x1d,  // SynchPtyErrOnTranslTableWalkL1
116378SN/A    0x1e,  // SynchPtyErrOnTranslTableWalkL2
117378SN/A    0x1f,  // SynchPtyErrOnTranslTableWalkL3
1181706SN/A    0xff,  // TranslationL0 (INVALID)
11911851Sbrandon.potter@amd.com    0x05,  // TranslationL1
120360SN/A    0x06,  // TranslationL2
12111760Sbrandon.potter@amd.com    0x07,  // TranslationL3
12211760Sbrandon.potter@amd.com    0xff,  // AccessFlagL0 (INVALID)
12311851Sbrandon.potter@amd.com    0x09,  // AccessFlagL1
12411760Sbrandon.potter@amd.com    0x0a,  // AccessFlagL2
1256109Ssanchezd@stanford.edu    0x0b,  // AccessFlagL3
1261706SN/A    0xff,  // DomainL0 (INVALID)
12711851Sbrandon.potter@amd.com    0x3d,  // DomainL1
128378SN/A    0x3e,  // DomainL2
1296109Ssanchezd@stanford.edu    0xff,  // DomainL3 (RESERVED)
1306109Ssanchezd@stanford.edu    0xff,  // PermissionL0 (INVALID)
13111851Sbrandon.potter@amd.com    0x0d,  // PermissionL1
1326109Ssanchezd@stanford.edu    0x0e,  // PermissionL2
133378SN/A    0x0f,  // PermissionL3
1341706SN/A    0x22,  // DebugEvent
13511851Sbrandon.potter@amd.com    0x10,  // SynchronousExternalAbort
136378SN/A    0x30,  // TLBConflictAbort
1375748SSteve.Reinhardt@amd.com    0x18,  // SynchPtyErrOnMemoryAccess
1385748SSteve.Reinhardt@amd.com    0x11,  // AsynchronousExternalAbort
13911851Sbrandon.potter@amd.com    0x19,  // AsynchPtyErrOnMemoryAccess
140378SN/A    0xff,  // AddressSizeL0 (INVALID)
141378SN/A    0xff,  // AddressSizeL1 (INVALID)
1421706SN/A    0xff,  // AddressSizeL2 (INVALID)
14311851Sbrandon.potter@amd.com    0xff,  // AddressSizeL3 (INVALID)
144378SN/A    0x40,  // PrefetchTLBMiss
145378SN/A    0x80   // PrefetchUncacheable
1461706SN/A};
14711851Sbrandon.potter@amd.com
148378SN/Astatic_assert(sizeof(ArmFault::longDescFaultSources) ==
149378SN/A              ArmFault::NumFaultSources,
1501706SN/A              "Invalid size of ArmFault::longDescFaultSources[]");
15111851Sbrandon.potter@amd.com
152378SN/Auint8_t ArmFault::aarch64FaultSources[] = {
153378SN/A    0x21,  // AlignmentFault
1541706SN/A    0xff,  // InstructionCacheMaintenance (INVALID)
15511851Sbrandon.potter@amd.com    0x14,  // SynchExtAbtOnTranslTableWalkL0
156378SN/A    0x15,  // SynchExtAbtOnTranslTableWalkL1
1574118Sgblack@eecs.umich.edu    0x16,  // SynchExtAbtOnTranslTableWalkL2
1584118Sgblack@eecs.umich.edu    0x17,  // SynchExtAbtOnTranslTableWalkL3
15911851Sbrandon.potter@amd.com    0x1c,  // SynchPtyErrOnTranslTableWalkL0
1604118Sgblack@eecs.umich.edu    0x1d,  // SynchPtyErrOnTranslTableWalkL1
161378SN/A    0x1e,  // SynchPtyErrOnTranslTableWalkL2
1621706SN/A    0x1f,  // SynchPtyErrOnTranslTableWalkL3
16311851Sbrandon.potter@amd.com    0x04,  // TranslationL0
164378SN/A    0x05,  // TranslationL1
165378SN/A    0x06,  // TranslationL2
1661706SN/A    0x07,  // TranslationL3
16711851Sbrandon.potter@amd.com    0x08,  // AccessFlagL0
168360SN/A    0x09,  // AccessFlagL1
1695513SMichael.Adler@intel.com    0x0a,  // AccessFlagL2
1705513SMichael.Adler@intel.com    0x0b,  // AccessFlagL3
17111851Sbrandon.potter@amd.com    // @todo: Section & Page Domain Fault in AArch64?
1725513SMichael.Adler@intel.com    0xff,  // DomainL0 (INVALID)
17310203SAli.Saidi@ARM.com    0xff,  // DomainL1 (INVALID)
17410203SAli.Saidi@ARM.com    0xff,  // DomainL2 (INVALID)
17511851Sbrandon.potter@amd.com    0xff,  // DomainL3 (INVALID)
17610203SAli.Saidi@ARM.com    0x0c,  // PermissionL0
1775513SMichael.Adler@intel.com    0x0d,  // PermissionL1
17811851Sbrandon.potter@amd.com    0x0e,  // PermissionL2
1795513SMichael.Adler@intel.com    0x0f,  // PermissionL3
180511SN/A    0x22,  // DebugEvent
18110633Smichaelupton@gmail.com    0x10,  // SynchronousExternalAbort
18211851Sbrandon.potter@amd.com    0x30,  // TLBConflictAbort
18310633Smichaelupton@gmail.com    0x18,  // SynchPtyErrOnMemoryAccess
1841706SN/A    0xff,  // AsynchronousExternalAbort (INVALID)
18511851Sbrandon.potter@amd.com    0xff,  // AsynchPtyErrOnMemoryAccess (INVALID)
186511SN/A    0x00,  // AddressSizeL0
1875513SMichael.Adler@intel.com    0x01,  // AddressSizeL1
1885513SMichael.Adler@intel.com    0x02,  // AddressSizeL2
18911851Sbrandon.potter@amd.com    0x03,  // AddressSizeL3
1905513SMichael.Adler@intel.com    0x40,  // PrefetchTLBMiss
191511SN/A    0x80   // PrefetchUncacheable
1921706SN/A};
19311851Sbrandon.potter@amd.com
1941706SN/Astatic_assert(sizeof(ArmFault::aarch64FaultSources) ==
1951706SN/A              ArmFault::NumFaultSources,
1961706SN/A              "Invalid size of ArmFault::aarch64FaultSources[]");
1971706SN/A
19811851Sbrandon.potter@amd.com// Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode,
1991706SN/A//         {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap,
2001706SN/A//         {A, F} disable, class, stat
2011706SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals(
2021706SN/A    // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED
20311851Sbrandon.potter@amd.com    // location in AArch64)
2041706SN/A    "Reset",                 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
205511SN/A    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN
2066703Svince@csl.cornell.edu);
2076703Svince@csl.cornell.edutemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals(
20811851Sbrandon.potter@amd.com    "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
2096703Svince@csl.cornell.edu    4, 2, 0, 0, true,  false, false, EC_UNKNOWN
2106685Stjones1@inf.ed.ac.uk);
2116685Stjones1@inf.ed.ac.uktemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals(
21211851Sbrandon.potter@amd.com    "Supervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2136685Stjones1@inf.ed.ac.uk    4, 2, 4, 2, true,  false, false, EC_SVC_TO_HYP
2146685Stjones1@inf.ed.ac.uk);
2155513SMichael.Adler@intel.comtemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals(
2165513SMichael.Adler@intel.com    "Secure Monitor Call",   0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON,
21711851Sbrandon.potter@amd.com    4, 4, 4, 4, false, true,  true,  EC_SMC_TO_HYP
2185513SMichael.Adler@intel.com);
21911885Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals(
22011885Sbrandon.potter@amd.com    "Hypervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
22111885Sbrandon.potter@amd.com    4, 4, 4, 4, true,  false, false, EC_HVC
2225513SMichael.Adler@intel.com);
2231999SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals(
2241999SN/A    "Prefetch Abort",        0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
22511851Sbrandon.potter@amd.com    4, 4, 0, 0, true,  true,  false, EC_PREFETCH_ABORT_TO_HYP
2261999SN/A);
22711885Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals(
22811885Sbrandon.potter@amd.com    "Data Abort",            0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
22911885Sbrandon.potter@amd.com    8, 8, 0, 0, true,  true,  false, EC_DATA_ABORT_TO_HYP
2301999SN/A);
2311999SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals(
2321999SN/A    "Virtual Data Abort",    0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
23311851Sbrandon.potter@amd.com    8, 8, 0, 0, true,  true,  false, EC_INVALID
2341999SN/A);
2353079Sstever@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals(
2363079Sstever@eecs.umich.edu    // @todo: double check these values
23711851Sbrandon.potter@amd.com    "Hypervisor Trap",       0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2383079Sstever@eecs.umich.edu    0, 0, 0, 0, false, false, false, EC_UNKNOWN
23911875Sbrandon.potter@amd.com);
2402093SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals(
24111851Sbrandon.potter@amd.com    "Secure Monitor Trap",   0x004, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2422093SN/A    4, 2, 0, 0, false, false, false, EC_UNKNOWN
2432687Sksewell@umich.edu);
2442687Sksewell@umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals(
24511851Sbrandon.potter@amd.com    "IRQ",                   0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2462687Sksewell@umich.edu    4, 4, 0, 0, false, true,  false, EC_UNKNOWN
2472238SN/A);
2482238SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals(
24911851Sbrandon.potter@amd.com    "Virtual IRQ",           0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2502238SN/A    4, 4, 0, 0, false, true,  false, EC_INVALID
2512238SN/A);
2522238SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals(
25311851Sbrandon.potter@amd.com    "FIQ",                   0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2542238SN/A    4, 4, 0, 0, false, true,  true,  EC_UNKNOWN
2552238SN/A);
2562238SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals(
25711851Sbrandon.potter@amd.com    "Virtual FIQ",           0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2582238SN/A    4, 4, 0, 0, false, true,  true,  EC_INVALID
2592238SN/A);
2602238SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals(
26111851Sbrandon.potter@amd.com    "Illegal Inst Set State Fault",   0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
2622238SN/A    4, 2, 0, 0, true, false, false, EC_ILLEGAL_INST
2632238SN/A);
2642238SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals(
26511851Sbrandon.potter@amd.com    // Some dummy values (SupervisorTrap is AArch64-only)
2662238SN/A    "Supervisor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2672238SN/A    0, 0, 0, 0, false, false, false, EC_UNKNOWN
2682238SN/A);
26911851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals(
2702238SN/A    // Some dummy values (PCAlignmentFault is AArch64-only)
2712238SN/A    "PC Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2722238SN/A    0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT
27311851Sbrandon.potter@amd.com);
2742238SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals(
2756109Ssanchezd@stanford.edu    // Some dummy values (SPAlignmentFault is AArch64-only)
2766109Ssanchezd@stanford.edu    "SP Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
27711851Sbrandon.potter@amd.com    0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT
2782238SN/A);
2799455Smitch.hayenga+gem5@gmail.comtemplate<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals(
2809455Smitch.hayenga+gem5@gmail.com    // Some dummy values (SError is AArch64-only)
28111851Sbrandon.potter@amd.com    "SError",                0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC,
28210203SAli.Saidi@ARM.com    0, 0, 0, 0, false, true,  true,  EC_SERROR
28311851Sbrandon.potter@amd.com);
28411851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals(
2859455Smitch.hayenga+gem5@gmail.com    // Some dummy values (SoftwareBreakpoint is AArch64-only)
2869112Smarc.orr@gmail.com    "Software Breakpoint",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2879112Smarc.orr@gmail.com    0, 0, 0, 0, true, false, false,  EC_SOFTWARE_BREAKPOINT
2889112Smarc.orr@gmail.com);
2899112Smarc.orr@gmail.comtemplate<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals(
2909112Smarc.orr@gmail.com    // Some dummy values
29111851Sbrandon.potter@amd.com    "ArmSev Flush",          0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2929112Smarc.orr@gmail.com    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN
2939112Smarc.orr@gmail.com);
2949112Smarc.orr@gmail.com
2959112Smarc.orr@gmail.comAddr
2969112Smarc.orr@gmail.comArmFault::getVector(ThreadContext *tc)
2979112Smarc.orr@gmail.com{
2989112Smarc.orr@gmail.com    Addr base;
2999112Smarc.orr@gmail.com
3009112Smarc.orr@gmail.com    // ARM ARM issue C B1.8.1
3019112Smarc.orr@gmail.com    bool haveSecurity = ArmSystem::haveSecurity(tc);
3029112Smarc.orr@gmail.com
3039112Smarc.orr@gmail.com    // Check for invalid modes
3049112Smarc.orr@gmail.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
3059112Smarc.orr@gmail.com    assert(haveSecurity                      || cpsr.mode != MODE_MON);
3069112Smarc.orr@gmail.com    assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
3079112Smarc.orr@gmail.com
3089112Smarc.orr@gmail.com    switch (cpsr.mode)
3099112Smarc.orr@gmail.com    {
3109238Slluc.alvarez@bsc.es      case MODE_MON:
3119112Smarc.orr@gmail.com        base = tc->readMiscReg(MISCREG_MVBAR);
3129112Smarc.orr@gmail.com        break;
3139112Smarc.orr@gmail.com      case MODE_HYP:
3149112Smarc.orr@gmail.com        base = tc->readMiscReg(MISCREG_HVBAR);
3159112Smarc.orr@gmail.com        break;
3169112Smarc.orr@gmail.com      default:
3179112Smarc.orr@gmail.com        SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
3189112Smarc.orr@gmail.com        if (sctlr.v) {
3199112Smarc.orr@gmail.com            base = HighVecs;
3209112Smarc.orr@gmail.com        } else {
32111367Sandreas.hansson@arm.com            base = haveSecurity ? tc->readMiscReg(MISCREG_VBAR) : 0;
3229112Smarc.orr@gmail.com        }
32311321Ssteve.reinhardt@amd.com        break;
3249112Smarc.orr@gmail.com    }
3259112Smarc.orr@gmail.com    return base + offset(tc);
3269112Smarc.orr@gmail.com}
3279112Smarc.orr@gmail.com
3289112Smarc.orr@gmail.comAddr
3299112Smarc.orr@gmail.comArmFault::getVector64(ThreadContext *tc)
3309112Smarc.orr@gmail.com{
3319112Smarc.orr@gmail.com    Addr vbar;
3329112Smarc.orr@gmail.com    switch (toEL) {
3339112Smarc.orr@gmail.com      case EL3:
3349112Smarc.orr@gmail.com        assert(ArmSystem::haveSecurity(tc));
3359112Smarc.orr@gmail.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL3);
3369112Smarc.orr@gmail.com        break;
3379112Smarc.orr@gmail.com      case EL2:
3389112Smarc.orr@gmail.com        assert(ArmSystem::haveVirtualization(tc));
3399112Smarc.orr@gmail.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
3409112Smarc.orr@gmail.com        break;
3419112Smarc.orr@gmail.com      case EL1:
3429112Smarc.orr@gmail.com        vbar = tc->readMiscReg(MISCREG_VBAR_EL1);
3439112Smarc.orr@gmail.com        break;
3449112Smarc.orr@gmail.com      default:
3459112Smarc.orr@gmail.com        panic("Invalid target exception level");
3469112Smarc.orr@gmail.com        break;
3479112Smarc.orr@gmail.com    }
3489112Smarc.orr@gmail.com    return vbar + offset64(tc);
3499112Smarc.orr@gmail.com}
3509112Smarc.orr@gmail.com
3519112Smarc.orr@gmail.comMiscRegIndex
3529112Smarc.orr@gmail.comArmFault::getSyndromeReg64() const
35311321Ssteve.reinhardt@amd.com{
3549112Smarc.orr@gmail.com    switch (toEL) {
3559112Smarc.orr@gmail.com      case EL1:
3569112Smarc.orr@gmail.com        return MISCREG_ESR_EL1;
3579112Smarc.orr@gmail.com      case EL2:
3589112Smarc.orr@gmail.com        return MISCREG_ESR_EL2;
3599112Smarc.orr@gmail.com      case EL3:
3609112Smarc.orr@gmail.com        return MISCREG_ESR_EL3;
3619112Smarc.orr@gmail.com      default:
3629238Slluc.alvarez@bsc.es        panic("Invalid exception level");
3639112Smarc.orr@gmail.com        break;
3649112Smarc.orr@gmail.com    }
3659112Smarc.orr@gmail.com}
3669112Smarc.orr@gmail.com
3679112Smarc.orr@gmail.comMiscRegIndex
3682238SN/AArmFault::getFaultAddrReg64() const
3692238SN/A{
3702238SN/A    switch (toEL) {
3712238SN/A      case EL1:
37211851Sbrandon.potter@amd.com        return MISCREG_FAR_EL1;
3732238SN/A      case EL2:
3742238SN/A        return MISCREG_FAR_EL2;
3752238SN/A      case EL3:
37611851Sbrandon.potter@amd.com        return MISCREG_FAR_EL3;
3772238SN/A      default:
3782238SN/A        panic("Invalid exception level");
3792238SN/A        break;
38011851Sbrandon.potter@amd.com    }
3812238SN/A}
3822238SN/A
3832238SN/Avoid
38411851Sbrandon.potter@amd.comArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
3852238SN/A{
3862238SN/A    uint32_t value;
3871354SN/A    uint32_t exc_class = (uint32_t) ec(tc);
3881354SN/A    uint32_t issVal = iss();
38910796Sbrandon.potter@amd.com
39010796Sbrandon.potter@amd.com    assert(!from64 || ArmSystem::highestELIs64(tc));
3911354SN/A
3921354SN/A    value = exc_class << 26;
3931354SN/A
3941354SN/A    // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24,
3951354SN/A    // 0x25) for which the ISS information is not valid (ARMv7).
3961354SN/A    // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not
3971354SN/A    // valid it is treated as RES1.
3981354SN/A    if (to64) {
3991354SN/A        value |= 1 << 25;
4001354SN/A    } else if ((bits(exc_class, 5, 3) != 4) ||
40110796Sbrandon.potter@amd.com               (bits(exc_class, 2) && bits(issVal, 24))) {
4021354SN/A        if (!machInst.thumb || machInst.bigThumb)
40310796Sbrandon.potter@amd.com            value |= 1 << 25;
4041354SN/A    }
4051354SN/A    // Condition code valid for EC[5:4] nonzero
4061354SN/A    if (!from64 && ((bits(exc_class, 5, 4) == 0) &&
4071354SN/A                    (bits(exc_class, 3, 0) != 0))) {
40810796Sbrandon.potter@amd.com        if (!machInst.thumb) {
40910796Sbrandon.potter@amd.com            uint32_t      cond;
41010796Sbrandon.potter@amd.com            ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode;
41110796Sbrandon.potter@amd.com            // If its on unconditional instruction report with a cond code of
41210796Sbrandon.potter@amd.com            // 0xE, ie the unconditional code
41310796Sbrandon.potter@amd.com            cond  = (condCode == COND_UC) ? COND_AL : condCode;
41410796Sbrandon.potter@amd.com            value |= cond << 20;
41510796Sbrandon.potter@amd.com            value |= 1    << 24;
41610796Sbrandon.potter@amd.com        }
41710796Sbrandon.potter@amd.com        value |= bits(issVal, 19, 0);
41810796Sbrandon.potter@amd.com    } else {
419360SN/A        value |= issVal;
420360SN/A    }
421360SN/A    tc->setMiscReg(syndrome_reg, value);
422360SN/A}
423360SN/A
424360SN/Avoid
425360SN/AArmFault::update(ThreadContext *tc)
42611759Sbrandon.potter@amd.com{
4273113Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
4283113Sgblack@eecs.umich.edu
4293113Sgblack@eecs.umich.edu    // Determine source exception level and mode
4303113Sgblack@eecs.umich.edu    fromMode = (OperatingMode) (uint8_t) cpsr.mode;
4313113Sgblack@eecs.umich.edu    fromEL = opModeToEL(fromMode);
4323113Sgblack@eecs.umich.edu    if (opModeIs64(fromMode))
4333113Sgblack@eecs.umich.edu        from64 = true;
4343113Sgblack@eecs.umich.edu
4353113Sgblack@eecs.umich.edu    // Determine target exception level (aarch64) or target execution
4363113Sgblack@eecs.umich.edu    // mode (aarch32).
4373113Sgblack@eecs.umich.edu    if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc)) {
4383113Sgblack@eecs.umich.edu        toMode = MODE_MON;
4393113Sgblack@eecs.umich.edu        toEL = EL3;
4403113Sgblack@eecs.umich.edu    } else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc)) {
4413113Sgblack@eecs.umich.edu        toMode = MODE_HYP;
4423113Sgblack@eecs.umich.edu        toEL = EL2;
4434189Sgblack@eecs.umich.edu        hypRouted = true;
4444189Sgblack@eecs.umich.edu    } else {
4453113Sgblack@eecs.umich.edu        toMode = nextMode();
4463113Sgblack@eecs.umich.edu        toEL = opModeToEL(toMode);
4473113Sgblack@eecs.umich.edu    }
4483113Sgblack@eecs.umich.edu
4498737Skoansin.tan@gmail.com    if (fromEL > toEL)
4503113Sgblack@eecs.umich.edu        toEL = fromEL;
4518737Skoansin.tan@gmail.com
4523277Sgblack@eecs.umich.edu    to64 = ELIs64(tc, toEL);
4535515SMichael.Adler@intel.com
4545515SMichael.Adler@intel.com    // The fault specific informations have been updated; it is
4555515SMichael.Adler@intel.com    // now possible to use them inside the fault.
4565515SMichael.Adler@intel.com    faultUpdated = true;
4575515SMichael.Adler@intel.com}
4588737Skoansin.tan@gmail.com
4593277Sgblack@eecs.umich.eduvoid
4608737Skoansin.tan@gmail.comArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
4613277Sgblack@eecs.umich.edu{
4628737Skoansin.tan@gmail.com
4633277Sgblack@eecs.umich.edu    // Update fault state informations, like the starting mode (aarch32)
4648737Skoansin.tan@gmail.com    // or EL (aarch64) and the ending mode or EL.
4653113Sgblack@eecs.umich.edu    // From the update function we are also evaluating if the fault must
4663113Sgblack@eecs.umich.edu    // be handled in AArch64 mode (to64).
4673113Sgblack@eecs.umich.edu    update(tc);
4683113Sgblack@eecs.umich.edu
4698737Skoansin.tan@gmail.com    if (to64) {
4703113Sgblack@eecs.umich.edu        // Invoke exception handler in AArch64 state
4718737Skoansin.tan@gmail.com        invoke64(tc, inst);
4723114Sgblack@eecs.umich.edu        return;
4738737Skoansin.tan@gmail.com    }
4743114Sgblack@eecs.umich.edu
4758737Skoansin.tan@gmail.com    // ARMv7 (ARM ARM issue C B1.9)
4763114Sgblack@eecs.umich.edu
4778737Skoansin.tan@gmail.com    bool have_security       = ArmSystem::haveSecurity(tc);
4784061Sgblack@eecs.umich.edu
4794061Sgblack@eecs.umich.edu    FaultBase::invoke(tc);
4804061Sgblack@eecs.umich.edu    if (!FullSystem)
4818737Skoansin.tan@gmail.com        return;
4823113Sgblack@eecs.umich.edu    countStat()++;
4838737Skoansin.tan@gmail.com
4843113Sgblack@eecs.umich.edu    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
4853113Sgblack@eecs.umich.edu    SCR scr = tc->readMiscReg(MISCREG_SCR);
4863113Sgblack@eecs.umich.edu    CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR);
4873113Sgblack@eecs.umich.edu    saved_cpsr.nz = tc->readCCReg(CCREG_NZ);
4883113Sgblack@eecs.umich.edu    saved_cpsr.c = tc->readCCReg(CCREG_C);
4893113Sgblack@eecs.umich.edu    saved_cpsr.v = tc->readCCReg(CCREG_V);
4903113Sgblack@eecs.umich.edu    saved_cpsr.ge = tc->readCCReg(CCREG_GE);
4913113Sgblack@eecs.umich.edu
4924189Sgblack@eecs.umich.edu    Addr curPc M5_VAR_USED = tc->pcState().pc();
4934189Sgblack@eecs.umich.edu    ITSTATE it = tc->pcState().itstate();
4943113Sgblack@eecs.umich.edu    saved_cpsr.it2 = it.top6;
4953113Sgblack@eecs.umich.edu    saved_cpsr.it1 = it.bottom2;
4963113Sgblack@eecs.umich.edu
4978737Skoansin.tan@gmail.com    // if we have a valid instruction then use it to annotate this fault with
4983113Sgblack@eecs.umich.edu    // extra information. This is used to generate the correct fault syndrome
4998737Skoansin.tan@gmail.com    // information
5003113Sgblack@eecs.umich.edu    if (inst) {
5018737Skoansin.tan@gmail.com        ArmStaticInst *armInst = static_cast<ArmStaticInst *>(inst.get());
5023113Sgblack@eecs.umich.edu        armInst->annotateFault(this);
5033113Sgblack@eecs.umich.edu    }
5043113Sgblack@eecs.umich.edu
5053113Sgblack@eecs.umich.edu    // Ensure Secure state if initially in Monitor mode
5063113Sgblack@eecs.umich.edu    if (have_security && saved_cpsr.mode == MODE_MON) {
5073113Sgblack@eecs.umich.edu        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
5083113Sgblack@eecs.umich.edu        if (scr.ns) {
5093113Sgblack@eecs.umich.edu            scr.ns = 0;
5103113Sgblack@eecs.umich.edu            tc->setMiscRegNoEffect(MISCREG_SCR, scr);
5113113Sgblack@eecs.umich.edu        }
5128852Sandreas.hansson@arm.com    }
5133113Sgblack@eecs.umich.edu
5143113Sgblack@eecs.umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
5153113Sgblack@eecs.umich.edu    cpsr.mode = toMode;
5163113Sgblack@eecs.umich.edu
5173113Sgblack@eecs.umich.edu    // some bits are set differently if we have been routed to hyp mode
5183113Sgblack@eecs.umich.edu    if (cpsr.mode == MODE_HYP) {
5193113Sgblack@eecs.umich.edu        SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR);
5203113Sgblack@eecs.umich.edu        cpsr.t = hsctlr.te;
5213113Sgblack@eecs.umich.edu        cpsr.e = hsctlr.ee;
5223113Sgblack@eecs.umich.edu        if (!scr.ea)  {cpsr.a = 1;}
5238852Sandreas.hansson@arm.com        if (!scr.fiq) {cpsr.f = 1;}
5243113Sgblack@eecs.umich.edu        if (!scr.irq) {cpsr.i = 1;}
5253113Sgblack@eecs.umich.edu    } else if (cpsr.mode == MODE_MON) {
5263113Sgblack@eecs.umich.edu        // Special case handling when entering monitor mode
5273113Sgblack@eecs.umich.edu        cpsr.t = sctlr.te;
5286686Stjones1@inf.ed.ac.uk        cpsr.e = sctlr.ee;
5293113Sgblack@eecs.umich.edu        cpsr.a = 1;
5303113Sgblack@eecs.umich.edu        cpsr.f = 1;
5313113Sgblack@eecs.umich.edu        cpsr.i = 1;
53211759Sbrandon.potter@amd.com    } else {
53311759Sbrandon.potter@amd.com        cpsr.t = sctlr.te;
53411759Sbrandon.potter@amd.com        cpsr.e = sctlr.ee;
53511759Sbrandon.potter@amd.com
53611759Sbrandon.potter@amd.com        // The *Disable functions are virtual and different per fault
53711759Sbrandon.potter@amd.com        cpsr.a = cpsr.a | abortDisable(tc);
53811759Sbrandon.potter@amd.com        cpsr.f = cpsr.f | fiqDisable(tc);
53911812Sbaz21@cam.ac.uk        cpsr.i = 1;
54011812Sbaz21@cam.ac.uk    }
54111812Sbaz21@cam.ac.uk    cpsr.it1 = cpsr.it2 = 0;
54211759Sbrandon.potter@amd.com    cpsr.j = 0;
54311812Sbaz21@cam.ac.uk    tc->setMiscReg(MISCREG_CPSR, cpsr);
54411759Sbrandon.potter@amd.com
54511759Sbrandon.potter@amd.com    // Make sure mailbox sets to one always
54611759Sbrandon.potter@amd.com    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
54711759Sbrandon.potter@amd.com
54811759Sbrandon.potter@amd.com    // Clear the exclusive monitor
54911759Sbrandon.potter@amd.com    tc->setMiscReg(MISCREG_LOCKFLAG, 0);
55011759Sbrandon.potter@amd.com
55111812Sbaz21@cam.ac.uk    if (cpsr.mode == MODE_HYP) {
55211812Sbaz21@cam.ac.uk        tc->setMiscReg(MISCREG_ELR_HYP, curPc +
55311812Sbaz21@cam.ac.uk                (saved_cpsr.t ? thumbPcOffset(true)  : armPcOffset(true)));
55411812Sbaz21@cam.ac.uk    } else {
55511812Sbaz21@cam.ac.uk        tc->setIntReg(INTREG_LR, curPc +
55611812Sbaz21@cam.ac.uk                (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false)));
55711812Sbaz21@cam.ac.uk    }
55811759Sbrandon.potter@amd.com
55911759Sbrandon.potter@amd.com    switch (cpsr.mode) {
56011812Sbaz21@cam.ac.uk      case MODE_FIQ:
56111812Sbaz21@cam.ac.uk        tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
56211759Sbrandon.potter@amd.com        break;
56311812Sbaz21@cam.ac.uk      case MODE_IRQ:
56411812Sbaz21@cam.ac.uk        tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
56511812Sbaz21@cam.ac.uk        break;
56611812Sbaz21@cam.ac.uk      case MODE_SVC:
56711812Sbaz21@cam.ac.uk        tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
56811812Sbaz21@cam.ac.uk        break;
56911812Sbaz21@cam.ac.uk      case MODE_MON:
57011759Sbrandon.potter@amd.com        assert(have_security);
57111759Sbrandon.potter@amd.com        tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr);
57211759Sbrandon.potter@amd.com        break;
57311759Sbrandon.potter@amd.com      case MODE_ABORT:
574378SN/A        tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
575378SN/A        break;
5769141Smarc.orr@gmail.com      case MODE_UNDEFINED:
5779141Smarc.orr@gmail.com        tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
578360SN/A        if (ec(tc) != EC_UNKNOWN)
5791450SN/A            setSyndrome(tc, MISCREG_HSR);
58011856Sbrandon.potter@amd.com        break;
581360SN/A      case MODE_HYP:
5826701Sgblack@eecs.umich.edu        assert(ArmSystem::haveVirtualization(tc));
58311856Sbrandon.potter@amd.com        tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr);
58411856Sbrandon.potter@amd.com        setSyndrome(tc, MISCREG_HSR);
585360SN/A        break;
58610930Sbrandon.potter@amd.com      default:
587360SN/A        panic("unknown Mode\n");
58811856Sbrandon.potter@amd.com    }
58911856Sbrandon.potter@amd.com
59010496Ssteve.reinhardt@amd.com    Addr newPc = getVector(tc);
59111856Sbrandon.potter@amd.com    DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n",
59211856Sbrandon.potter@amd.com            name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc);
5931458SN/A    PCState pc(newPc);
594360SN/A    pc.thumb(cpsr.t);
59511856Sbrandon.potter@amd.com    pc.nextThumb(pc.thumb());
59611856Sbrandon.potter@amd.com    pc.jazelle(cpsr.j);
59711856Sbrandon.potter@amd.com    pc.nextJazelle(pc.jazelle());
59811856Sbrandon.potter@amd.com    pc.aarch64(!cpsr.width);
59911856Sbrandon.potter@amd.com    pc.nextAArch64(!cpsr.width);
60011856Sbrandon.potter@amd.com    pc.illegalExec(false);
60111856Sbrandon.potter@amd.com    tc->pcState(pc);
60211856Sbrandon.potter@amd.com}
60310496Ssteve.reinhardt@amd.com
60411856Sbrandon.potter@amd.comvoid
60511856Sbrandon.potter@amd.comArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
60611856Sbrandon.potter@amd.com{
60711856Sbrandon.potter@amd.com    // Determine actual misc. register indices for ELR_ELx and SPSR_ELx
60811856Sbrandon.potter@amd.com    MiscRegIndex elr_idx, spsr_idx;
60910930Sbrandon.potter@amd.com    switch (toEL) {
6109141Smarc.orr@gmail.com      case EL1:
611360SN/A        elr_idx = MISCREG_ELR_EL1;
612360SN/A        spsr_idx = MISCREG_SPSR_EL1;
613360SN/A        break;
61410027SChris.Adeniyi-Jones@arm.com      case EL2:
61511851Sbrandon.potter@amd.com        assert(ArmSystem::haveVirtualization(tc));
61610027SChris.Adeniyi-Jones@arm.com        elr_idx = MISCREG_ELR_EL2;
617360SN/A        spsr_idx = MISCREG_SPSR_EL2;
618360SN/A        break;
619360SN/A      case EL3:
6208852Sandreas.hansson@arm.com        assert(ArmSystem::haveSecurity(tc));
6216701Sgblack@eecs.umich.edu        elr_idx = MISCREG_ELR_EL3;
6221458SN/A        spsr_idx = MISCREG_SPSR_EL3;
623360SN/A        break;
6246701Sgblack@eecs.umich.edu      default:
6256701Sgblack@eecs.umich.edu        panic("Invalid target exception level");
626360SN/A        break;
627360SN/A    }
628360SN/A
629360SN/A    // Save process state into SPSR_ELx
630360SN/A    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
631360SN/A    CPSR spsr = cpsr;
632360SN/A    spsr.nz = tc->readCCReg(CCREG_NZ);
633360SN/A    spsr.c = tc->readCCReg(CCREG_C);
634360SN/A    spsr.v = tc->readCCReg(CCREG_V);
635360SN/A    if (from64) {
636360SN/A        // Force some bitfields to 0
637360SN/A        spsr.q = 0;
6381706SN/A        spsr.it1 = 0;
639360SN/A        spsr.j = 0;
640360SN/A        spsr.res0_23_22 = 0;
641360SN/A        spsr.ge = 0;
642360SN/A        spsr.it2 = 0;
643360SN/A        spsr.t = 0;
6443669Sbinkertn@umich.edu    } else {
6453669Sbinkertn@umich.edu        spsr.ge = tc->readCCReg(CCREG_GE);
6463669Sbinkertn@umich.edu        ITSTATE it = tc->pcState().itstate();
6471706SN/A        spsr.it2 = it.top6;
6481706SN/A        spsr.it1 = it.bottom2;
64910496Ssteve.reinhardt@amd.com        // Force some bitfields to 0
65010496Ssteve.reinhardt@amd.com        spsr.res0_23_22 = 0;
65110496Ssteve.reinhardt@amd.com        spsr.ss = 0;
65210496Ssteve.reinhardt@amd.com    }
65310496Ssteve.reinhardt@amd.com    tc->setMiscReg(spsr_idx, spsr);
65410496Ssteve.reinhardt@amd.com
65510496Ssteve.reinhardt@amd.com    // Save preferred return address into ELR_ELx
65610496Ssteve.reinhardt@amd.com    Addr curr_pc = tc->pcState().pc();
65710496Ssteve.reinhardt@amd.com    Addr ret_addr = curr_pc;
65810496Ssteve.reinhardt@amd.com    if (from64)
65911856Sbrandon.potter@amd.com        ret_addr += armPcElrOffset();
66010496Ssteve.reinhardt@amd.com    else
66110496Ssteve.reinhardt@amd.com        ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset();
66210496Ssteve.reinhardt@amd.com    tc->setMiscReg(elr_idx, ret_addr);
66310496Ssteve.reinhardt@amd.com
66410496Ssteve.reinhardt@amd.com    Addr vec_address = getVector64(tc);
66510496Ssteve.reinhardt@amd.com
66610496Ssteve.reinhardt@amd.com    // Update process state
66710496Ssteve.reinhardt@amd.com    OperatingMode64 mode = 0;
66810496Ssteve.reinhardt@amd.com    mode.spX = 1;
6695795Ssaidi@eecs.umich.edu    mode.el = toEL;
6709143Ssteve.reinhardt@amd.com    mode.width = 0;
6719142Ssteve.reinhardt@amd.com    cpsr.mode = mode;
6729142Ssteve.reinhardt@amd.com    cpsr.daif = 0xf;
6739143Ssteve.reinhardt@amd.com    cpsr.il = 0;
6745795Ssaidi@eecs.umich.edu    cpsr.ss = 0;
6759143Ssteve.reinhardt@amd.com    tc->setMiscReg(MISCREG_CPSR, cpsr);
6765795Ssaidi@eecs.umich.edu
6775795Ssaidi@eecs.umich.edu    // Set PC to start of exception handler
6785795Ssaidi@eecs.umich.edu    Addr new_pc = purifyTaggedAddr(vec_address, tc, toEL);
6799143Ssteve.reinhardt@amd.com    DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x "
6805795Ssaidi@eecs.umich.edu            "elr:%#x newVec: %#x\n", name(), cpsr, curr_pc, ret_addr, new_pc);
681360SN/A    PCState pc(new_pc);
6829143Ssteve.reinhardt@amd.com    pc.aarch64(!cpsr.width);
6839143Ssteve.reinhardt@amd.com    pc.nextAArch64(!cpsr.width);
6849143Ssteve.reinhardt@amd.com    pc.illegalExec(false);
68511856Sbrandon.potter@amd.com    tc->pcState(pc);
68611856Sbrandon.potter@amd.com
68711856Sbrandon.potter@amd.com    // If we have a valid instruction then use it to annotate this fault with
688360SN/A    // extra information. This is used to generate the correct fault syndrome
689360SN/A    // information
69010027SChris.Adeniyi-Jones@arm.com    if (inst)
69110027SChris.Adeniyi-Jones@arm.com        static_cast<ArmStaticInst *>(inst.get())->annotateFault(this);
69210027SChris.Adeniyi-Jones@arm.com    // Save exception syndrome
69311851Sbrandon.potter@amd.com    if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ))
69410027SChris.Adeniyi-Jones@arm.com        setSyndrome(tc, getSyndromeReg64());
69510027SChris.Adeniyi-Jones@arm.com}
69610027SChris.Adeniyi-Jones@arm.com
69710027SChris.Adeniyi-Jones@arm.comvoid
69810027SChris.Adeniyi-Jones@arm.comReset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
69910027SChris.Adeniyi-Jones@arm.com{
70010027SChris.Adeniyi-Jones@arm.com    if (FullSystem) {
70110027SChris.Adeniyi-Jones@arm.com        tc->getCpuPtr()->clearInterrupts(tc->threadId());
70211851Sbrandon.potter@amd.com        tc->clearArchRegs();
70311851Sbrandon.potter@amd.com    }
70410027SChris.Adeniyi-Jones@arm.com    if (!ArmSystem::highestELIs64(tc)) {
70510027SChris.Adeniyi-Jones@arm.com        ArmFault::invoke(tc, inst);
70610027SChris.Adeniyi-Jones@arm.com        tc->setMiscReg(MISCREG_VMPIDR,
70710027SChris.Adeniyi-Jones@arm.com                       getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc));
70810027SChris.Adeniyi-Jones@arm.com
70910027SChris.Adeniyi-Jones@arm.com        // Unless we have SMC code to get us there, boot in HYP!
71010027SChris.Adeniyi-Jones@arm.com        if (ArmSystem::haveVirtualization(tc) &&
71110027SChris.Adeniyi-Jones@arm.com            !ArmSystem::haveSecurity(tc)) {
71210633Smichaelupton@gmail.com            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
71310633Smichaelupton@gmail.com            cpsr.mode = MODE_HYP;
71410633Smichaelupton@gmail.com            tc->setMiscReg(MISCREG_CPSR, cpsr);
71511851Sbrandon.potter@amd.com        }
71610633Smichaelupton@gmail.com    } else {
71710633Smichaelupton@gmail.com        // Advance the PC to the IMPLEMENTATION DEFINED reset value
71810633Smichaelupton@gmail.com        PCState pc = ArmSystem::resetAddr64(tc);
71910633Smichaelupton@gmail.com        pc.aarch64(true);
72010633Smichaelupton@gmail.com        pc.nextAArch64(true);
72110633Smichaelupton@gmail.com        tc->pcState(pc);
72210633Smichaelupton@gmail.com    }
72310633Smichaelupton@gmail.com}
72410633Smichaelupton@gmail.com
72510633Smichaelupton@gmail.comvoid
72610203SAli.Saidi@ARM.comUndefinedInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
72710203SAli.Saidi@ARM.com{
72810203SAli.Saidi@ARM.com    if (FullSystem) {
72911851Sbrandon.potter@amd.com        ArmFault::invoke(tc, inst);
73011851Sbrandon.potter@amd.com        return;
73110203SAli.Saidi@ARM.com    }
73210203SAli.Saidi@ARM.com
73310203SAli.Saidi@ARM.com    // If the mnemonic isn't defined this has to be an unknown instruction.
73410203SAli.Saidi@ARM.com    assert(unknown || mnemonic != NULL);
73510203SAli.Saidi@ARM.com    if (disabled) {
73610203SAli.Saidi@ARM.com        panic("Attempted to execute disabled instruction "
73710203SAli.Saidi@ARM.com                "'%s' (inst 0x%08x)", mnemonic, machInst);
73810203SAli.Saidi@ARM.com    } else if (unknown) {
73910203SAli.Saidi@ARM.com        panic("Attempted to execute unknown instruction (inst 0x%08x)",
74010203SAli.Saidi@ARM.com              machInst);
74110203SAli.Saidi@ARM.com    } else {
74211851Sbrandon.potter@amd.com        panic("Attempted to execute unimplemented instruction "
74311851Sbrandon.potter@amd.com                "'%s' (inst 0x%08x)", mnemonic, machInst);
74410203SAli.Saidi@ARM.com    }
74510203SAli.Saidi@ARM.com}
74610203SAli.Saidi@ARM.com
74710203SAli.Saidi@ARM.combool
74810203SAli.Saidi@ARM.comUndefinedInstruction::routeToHyp(ThreadContext *tc) const
74910203SAli.Saidi@ARM.com{
75010203SAli.Saidi@ARM.com    bool toHyp;
75110203SAli.Saidi@ARM.com
75210850SGiacomo.Gabrielli@arm.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
75310850SGiacomo.Gabrielli@arm.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
75410850SGiacomo.Gabrielli@arm.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
75511851Sbrandon.potter@amd.com
75610850SGiacomo.Gabrielli@arm.com    // if in Hyp mode then stay in Hyp mode
75710850SGiacomo.Gabrielli@arm.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
75810850SGiacomo.Gabrielli@arm.com    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
75910850SGiacomo.Gabrielli@arm.com    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
76010850SGiacomo.Gabrielli@arm.com    return toHyp;
76110850SGiacomo.Gabrielli@arm.com}
76210850SGiacomo.Gabrielli@arm.com
76310850SGiacomo.Gabrielli@arm.comuint32_t
76410850SGiacomo.Gabrielli@arm.comUndefinedInstruction::iss() const
76510850SGiacomo.Gabrielli@arm.com{
76610850SGiacomo.Gabrielli@arm.com
76710850SGiacomo.Gabrielli@arm.com    // If UndefinedInstruction is routed to hypervisor, iss field is 0.
76810850SGiacomo.Gabrielli@arm.com    if (hypRouted) {
76910850SGiacomo.Gabrielli@arm.com        return 0;
77010850SGiacomo.Gabrielli@arm.com    }
77110850SGiacomo.Gabrielli@arm.com
77210850SGiacomo.Gabrielli@arm.com    if (overrideEc == EC_INVALID)
77310850SGiacomo.Gabrielli@arm.com        return issRaw;
77410850SGiacomo.Gabrielli@arm.com
77510850SGiacomo.Gabrielli@arm.com    uint32_t new_iss = 0;
77610850SGiacomo.Gabrielli@arm.com    uint32_t op0, op1, op2, CRn, CRm, Rt, dir;
77710850SGiacomo.Gabrielli@arm.com
77810850SGiacomo.Gabrielli@arm.com    dir = bits(machInst, 21, 21);
77910850SGiacomo.Gabrielli@arm.com    op0 = bits(machInst, 20, 19);
78010850SGiacomo.Gabrielli@arm.com    op1 = bits(machInst, 18, 16);
78110850SGiacomo.Gabrielli@arm.com    CRn = bits(machInst, 15, 12);
78210850SGiacomo.Gabrielli@arm.com    CRm = bits(machInst, 11, 8);
78310850SGiacomo.Gabrielli@arm.com    op2 = bits(machInst, 7, 5);
78410850SGiacomo.Gabrielli@arm.com    Rt = bits(machInst, 4, 0);
78510850SGiacomo.Gabrielli@arm.com
78610850SGiacomo.Gabrielli@arm.com    new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 |
78710850SGiacomo.Gabrielli@arm.com            Rt << 5 | CRm << 1 | dir;
7886640Svince@csl.cornell.edu
7896640Svince@csl.cornell.edu    return new_iss;
7906640Svince@csl.cornell.edu}
79111851Sbrandon.potter@amd.com
79211851Sbrandon.potter@amd.comvoid
7936640Svince@csl.cornell.eduSupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
7946640Svince@csl.cornell.edu{
7956701Sgblack@eecs.umich.edu    if (FullSystem) {
7966701Sgblack@eecs.umich.edu        ArmFault::invoke(tc, inst);
79710793Sbrandon.potter@amd.com        return;
7986640Svince@csl.cornell.edu    }
79911758Sbrandon.potter@amd.com
80011758Sbrandon.potter@amd.com    // As of now, there isn't a 32 bit thumb version of this instruction.
80111758Sbrandon.potter@amd.com    assert(!machInst.bigThumb);
8026640Svince@csl.cornell.edu    uint32_t callNum;
8038706Sandreas.hansson@arm.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
8046640Svince@csl.cornell.edu    OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
8056701Sgblack@eecs.umich.edu    if (opModeIs64(mode))
8066640Svince@csl.cornell.edu        callNum = tc->readIntReg(INTREG_X8);
807360SN/A    else
8081999SN/A        callNum = tc->readIntReg(INTREG_R7);
8091999SN/A    Fault fault;
8101999SN/A    tc->syscall(callNum, &fault);
81111851Sbrandon.potter@amd.com
8122680Sktlim@umich.edu    // Advance the PC since that won't happen automatically.
8131999SN/A    PCState pc = tc->pcState();
8141999SN/A    assert(inst);
8151999SN/A    inst->advancePC(pc);
8166701Sgblack@eecs.umich.edu    tc->pcState(pc);
8178852Sandreas.hansson@arm.com}
8186701Sgblack@eecs.umich.edu
8191999SN/Abool
8206701Sgblack@eecs.umich.eduSupervisorCall::routeToHyp(ThreadContext *tc) const
8211999SN/A{
8226701Sgblack@eecs.umich.edu    bool toHyp;
8231999SN/A
8241999SN/A    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
8251999SN/A    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
8261999SN/A    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
8271999SN/A
8283669Sbinkertn@umich.edu    // if in Hyp mode then stay in Hyp mode
8293669Sbinkertn@umich.edu    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
8303669Sbinkertn@umich.edu    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
8311999SN/A    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
8321999SN/A    return toHyp;
8331999SN/A}
8342218SN/A
8351999SN/AExceptionClass
8361999SN/ASupervisorCall::ec(ThreadContext *tc) const
8371999SN/A{
8381999SN/A    return (overrideEc != EC_INVALID) ? overrideEc :
8391999SN/A        (from64 ? EC_SVC_64 : vals.ec);
8401999SN/A}
8411999SN/A
8421999SN/Auint32_t
84311856Sbrandon.potter@amd.comSupervisorCall::iss() const
8441999SN/A{
8456701Sgblack@eecs.umich.edu    // Even if we have a 24 bit imm from an arm32 instruction then we only use
84611856Sbrandon.potter@amd.com    // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC).
84711856Sbrandon.potter@amd.com    return issRaw & 0xFFFF;
84810931Sbrandon.potter@amd.com}
84911856Sbrandon.potter@amd.com
85011856Sbrandon.potter@amd.comuint32_t
8511999SN/ASecureMonitorCall::iss() const
85211856Sbrandon.potter@amd.com{
8531999SN/A    if (from64)
85411856Sbrandon.potter@amd.com        return bits(machInst, 20, 5);
8551999SN/A    return 0;
85611856Sbrandon.potter@amd.com}
8571999SN/A
85811856Sbrandon.potter@amd.comExceptionClass
8591999SN/AUndefinedInstruction::ec(ThreadContext *tc) const
8601999SN/A{
8615877Shsul@eecs.umich.edu    // If UndefinedInstruction is routed to hypervisor,
8625877Shsul@eecs.umich.edu    // HSR.EC field is 0.
8635877Shsul@eecs.umich.edu    if (hypRouted)
86411851Sbrandon.potter@amd.com        return EC_UNKNOWN;
8655877Shsul@eecs.umich.edu    else
8666701Sgblack@eecs.umich.edu        return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
8676701Sgblack@eecs.umich.edu}
8686701Sgblack@eecs.umich.edu
8696701Sgblack@eecs.umich.edu
8706701Sgblack@eecs.umich.eduHypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) :
87110027SChris.Adeniyi-Jones@arm.com        ArmFaultVals<HypervisorCall>(_machInst, _imm)
87210027SChris.Adeniyi-Jones@arm.com{}
87310027SChris.Adeniyi-Jones@arm.com
87410027SChris.Adeniyi-Jones@arm.comExceptionClass
87510027SChris.Adeniyi-Jones@arm.comHypervisorCall::ec(ThreadContext *tc) const
8765877Shsul@eecs.umich.edu{
87710318Sandreas.hansson@arm.com    return from64 ? EC_HVC_64 : vals.ec;
87810318Sandreas.hansson@arm.com}
8795877Shsul@eecs.umich.edu
8805877Shsul@eecs.umich.eduExceptionClass
8815877Shsul@eecs.umich.eduHypervisorTrap::ec(ThreadContext *tc) const
8825877Shsul@eecs.umich.edu{
88310486Stjablin@gmail.com    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
88410486Stjablin@gmail.com}
8855877Shsul@eecs.umich.edu
88610027SChris.Adeniyi-Jones@arm.comtemplate<class T>
88710027SChris.Adeniyi-Jones@arm.comFaultOffset
8885877Shsul@eecs.umich.eduArmFaultVals<T>::offset(ThreadContext *tc)
8898601Ssteve.reinhardt@amd.com{
8905877Shsul@eecs.umich.edu    bool isHypTrap = false;
8915877Shsul@eecs.umich.edu
8925877Shsul@eecs.umich.edu    // Normally we just use the exception vector from the table at the top if
89310027SChris.Adeniyi-Jones@arm.com    // this file, however if this exception has caused a transition to hype
8945877Shsul@eecs.umich.edu    // mode, and its an exception type that would only do this if it has been
8955877Shsul@eecs.umich.edu    // trapped then we use the hyp trap vector instead of the normal vector
8965877Shsul@eecs.umich.edu    if (vals.hypTrappable) {
89710027SChris.Adeniyi-Jones@arm.com        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
89810027SChris.Adeniyi-Jones@arm.com        if (cpsr.mode == MODE_HYP) {
89910027SChris.Adeniyi-Jones@arm.com            CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
90010027SChris.Adeniyi-Jones@arm.com            isHypTrap = spsr.mode != MODE_HYP;
90110027SChris.Adeniyi-Jones@arm.com        }
90210027SChris.Adeniyi-Jones@arm.com    }
9035877Shsul@eecs.umich.edu    return isHypTrap ? 0x14 : vals.offset;
90410027SChris.Adeniyi-Jones@arm.com}
90510027SChris.Adeniyi-Jones@arm.com
90610027SChris.Adeniyi-Jones@arm.comtemplate<class T>
90710027SChris.Adeniyi-Jones@arm.comFaultOffset
90810027SChris.Adeniyi-Jones@arm.comArmFaultVals<T>::offset64(ThreadContext *tc)
90910027SChris.Adeniyi-Jones@arm.com{
91010027SChris.Adeniyi-Jones@arm.com    if (toEL == fromEL) {
91110027SChris.Adeniyi-Jones@arm.com        if (opModeIsT(fromMode))
91210027SChris.Adeniyi-Jones@arm.com            return vals.currELTOffset;
91310027SChris.Adeniyi-Jones@arm.com        return vals.currELHOffset;
91410027SChris.Adeniyi-Jones@arm.com    } else {
91510027SChris.Adeniyi-Jones@arm.com        bool lower_32 = false;
91610027SChris.Adeniyi-Jones@arm.com        if (toEL == EL3) {
9175877Shsul@eecs.umich.edu            if (!inSecureState(tc) && ArmSystem::haveEL(tc, EL2))
9185877Shsul@eecs.umich.edu                lower_32 = ELIs32(tc, EL2);
9195877Shsul@eecs.umich.edu            else
92010027SChris.Adeniyi-Jones@arm.com                lower_32 = ELIs32(tc, EL1);
92110027SChris.Adeniyi-Jones@arm.com        } else {
9228601Ssteve.reinhardt@amd.com            lower_32 = ELIs32(tc, static_cast<ExceptionLevel>(toEL - 1));
92310027SChris.Adeniyi-Jones@arm.com        }
9245877Shsul@eecs.umich.edu
9255877Shsul@eecs.umich.edu        if (lower_32)
9261999SN/A            return vals.lowerEL32Offset;
927378SN/A        return vals.lowerEL64Offset;
928360SN/A    }
9291450SN/A}
93011851Sbrandon.potter@amd.com
9312680Sktlim@umich.edu// void
932360SN/A// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx)
933360SN/A// {
934360SN/A//     ESR esr = 0;
9356701Sgblack@eecs.umich.edu//     esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32;
9368852Sandreas.hansson@arm.com//     esr.il = !machInst.thumb;
9376701Sgblack@eecs.umich.edu//     if (machInst.aarch64)
9386701Sgblack@eecs.umich.edu//         esr.imm16 = bits(machInst.instBits, 20, 5);
9396701Sgblack@eecs.umich.edu//     else if (machInst.thumb)
9406701Sgblack@eecs.umich.edu//         esr.imm16 = bits(machInst.instBits, 7, 0);
941360SN/A//     else
9423669Sbinkertn@umich.edu//         esr.imm16 = bits(machInst.instBits, 15, 0);
9433669Sbinkertn@umich.edu//     tc->setMiscReg(esr_idx, esr);
9443669Sbinkertn@umich.edu// }
945360SN/A
946360SN/Avoid
947360SN/ASecureMonitorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
948360SN/A{
9492218SN/A    if (FullSystem) {
950360SN/A        ArmFault::invoke(tc, inst);
9518706Sandreas.hansson@arm.com        return;
952360SN/A    }
9531458SN/A}
954360SN/A
955360SN/AExceptionClass
956360SN/ASecureMonitorCall::ec(ThreadContext *tc) const
9575074Ssaidi@eecs.umich.edu{
9585074Ssaidi@eecs.umich.edu    return (from64 ? EC_SMC_64 : vals.ec);
9595074Ssaidi@eecs.umich.edu}
96011851Sbrandon.potter@amd.com
9615074Ssaidi@eecs.umich.edubool
9625074Ssaidi@eecs.umich.eduSupervisorTrap::routeToHyp(ThreadContext *tc) const
9635074Ssaidi@eecs.umich.edu{
9645074Ssaidi@eecs.umich.edu    bool toHyp = false;
9656701Sgblack@eecs.umich.edu
9668852Sandreas.hansson@arm.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
9676701Sgblack@eecs.umich.edu    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
9685074Ssaidi@eecs.umich.edu    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
9696701Sgblack@eecs.umich.edu
9705074Ssaidi@eecs.umich.edu    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
9715074Ssaidi@eecs.umich.edu    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.el == EL0);
9725074Ssaidi@eecs.umich.edu    return toHyp;
9735074Ssaidi@eecs.umich.edu}
9745208Ssaidi@eecs.umich.edu
9755208Ssaidi@eecs.umich.eduuint32_t
9765208Ssaidi@eecs.umich.eduSupervisorTrap::iss() const
9775208Ssaidi@eecs.umich.edu{
9785074Ssaidi@eecs.umich.edu    // If SupervisorTrap is routed to hypervisor, iss field is 0.
9795074Ssaidi@eecs.umich.edu    if (hypRouted) {
9805208Ssaidi@eecs.umich.edu        return 0;
9815074Ssaidi@eecs.umich.edu    }
9825074Ssaidi@eecs.umich.edu    return issRaw;
9835074Ssaidi@eecs.umich.edu}
9845074Ssaidi@eecs.umich.edu
9858706Sandreas.hansson@arm.comExceptionClass
9865074Ssaidi@eecs.umich.eduSupervisorTrap::ec(ThreadContext *tc) const
9875074Ssaidi@eecs.umich.edu{
9885074Ssaidi@eecs.umich.edu    if (hypRouted)
9895074Ssaidi@eecs.umich.edu        return EC_UNKNOWN;
9905074Ssaidi@eecs.umich.edu    else
99110027SChris.Adeniyi-Jones@arm.com        return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
99210027SChris.Adeniyi-Jones@arm.com}
99310027SChris.Adeniyi-Jones@arm.com
99411851Sbrandon.potter@amd.comExceptionClass
99510027SChris.Adeniyi-Jones@arm.comSecureMonitorTrap::ec(ThreadContext *tc) const
99610027SChris.Adeniyi-Jones@arm.com{
99710027SChris.Adeniyi-Jones@arm.com    return (overrideEc != EC_INVALID) ? overrideEc :
99810027SChris.Adeniyi-Jones@arm.com        (from64 ? EC_SMC_64 : vals.ec);
99910027SChris.Adeniyi-Jones@arm.com}
100010793Sbrandon.potter@amd.com
100110027SChris.Adeniyi-Jones@arm.comtemplate<class T>
100210027SChris.Adeniyi-Jones@arm.comvoid
100310027SChris.Adeniyi-Jones@arm.comAbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
100410027SChris.Adeniyi-Jones@arm.com{
100510027SChris.Adeniyi-Jones@arm.com    if (tranMethod == ArmFault::UnknownTran) {
100610027SChris.Adeniyi-Jones@arm.com        tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran
100710027SChris.Adeniyi-Jones@arm.com                                             : ArmFault::VmsaTran;
100810027SChris.Adeniyi-Jones@arm.com
100910027SChris.Adeniyi-Jones@arm.com        if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) {
101010027SChris.Adeniyi-Jones@arm.com            // See ARM ARM B3-1416
101110027SChris.Adeniyi-Jones@arm.com            bool override_LPAE = false;
101210027SChris.Adeniyi-Jones@arm.com            TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S);
101310027SChris.Adeniyi-Jones@arm.com            TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS);
101410027SChris.Adeniyi-Jones@arm.com            if (ttbcr_s.eae) {
101510027SChris.Adeniyi-Jones@arm.com                override_LPAE = true;
101610027SChris.Adeniyi-Jones@arm.com            } else {
101710027SChris.Adeniyi-Jones@arm.com                // Unimplemented code option, not seen in testing.  May need
101810027SChris.Adeniyi-Jones@arm.com                // extension according to the manual exceprt above.
101910027SChris.Adeniyi-Jones@arm.com                DPRINTF(Faults, "Warning: Incomplete translation method "
102010027SChris.Adeniyi-Jones@arm.com                        "override detected.\n");
102110027SChris.Adeniyi-Jones@arm.com            }
102210027SChris.Adeniyi-Jones@arm.com            if (override_LPAE)
102310027SChris.Adeniyi-Jones@arm.com                tranMethod = ArmFault::LpaeTran;
102410027SChris.Adeniyi-Jones@arm.com        }
102510027SChris.Adeniyi-Jones@arm.com    }
102610027SChris.Adeniyi-Jones@arm.com
102710027SChris.Adeniyi-Jones@arm.com    if (source == ArmFault::AsynchronousExternalAbort) {
10281999SN/A        tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
10291999SN/A    }
10301999SN/A    // Get effective fault source encoding
103111856Sbrandon.potter@amd.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
10321999SN/A
10336701Sgblack@eecs.umich.edu    // source must be determined BEFORE invoking generic routines which will
103411856Sbrandon.potter@amd.com    // try to set hsr etc. and are based upon source!
103511856Sbrandon.potter@amd.com    ArmFaultVals<T>::invoke(tc, inst);
103610931Sbrandon.potter@amd.com
103711856Sbrandon.potter@amd.com    if (!this->to64) {  // AArch32
103811856Sbrandon.potter@amd.com        FSR  fsr  = getFsr(tc);
10391999SN/A        if (cpsr.mode == MODE_HYP) {
104011856Sbrandon.potter@amd.com            tc->setMiscReg(T::HFarIndex, faultAddr);
10411999SN/A        } else if (stage2) {
10422764Sstever@eecs.umich.edu            tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf);
10432064SN/A            tc->setMiscReg(T::HFarIndex,  OVAddr);
104410931Sbrandon.potter@amd.com        } else {
10452064SN/A            tc->setMiscReg(T::FsrIndex, fsr);
10462064SN/A            tc->setMiscReg(T::FarIndex, faultAddr);
104710931Sbrandon.potter@amd.com        }
10482064SN/A        DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\
10491999SN/A                "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod);
10501999SN/A    } else {  // AArch64
10512218SN/A        // Set the FAR register.  Nothing else to do if we are in AArch64 state
10521999SN/A        // because the syndrome register has already been set inside invoke64()
105310931Sbrandon.potter@amd.com        if (stage2) {
10541999SN/A            // stage 2 fault, set HPFAR_EL2 to the faulting IPA
10551999SN/A            // and FAR_EL2 to the Original VA
10561999SN/A            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr);
10571999SN/A            tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
10581999SN/A
1059378SN/A            DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
1060360SN/A                    OVAddr, faultAddr);
10611450SN/A        } else {
106211851Sbrandon.potter@amd.com            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
10632680Sktlim@umich.edu        }
1064360SN/A    }
1065360SN/A}
1066360SN/A
10676701Sgblack@eecs.umich.edutemplate<class T>
10688852Sandreas.hansson@arm.comvoid
10696701Sgblack@eecs.umich.eduAbortFault<T>::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
10706701Sgblack@eecs.umich.edu{
10716701Sgblack@eecs.umich.edu    srcEncoded = getFaultStatusCode(tc);
10726701Sgblack@eecs.umich.edu    if (srcEncoded == ArmFault::FaultSourceInvalid) {
1073360SN/A        panic("Invalid fault source\n");
10743669Sbinkertn@umich.edu    }
10753669Sbinkertn@umich.edu    ArmFault::setSyndrome(tc, syndrome_reg);
10763669Sbinkertn@umich.edu}
1077360SN/A
1078360SN/Atemplate<class T>
1079360SN/Auint8_t
1080360SN/AAbortFault<T>::getFaultStatusCode(ThreadContext *tc) const
10811458SN/A{
1082360SN/A
10838706Sandreas.hansson@arm.com    panic_if(!this->faultUpdated,
1084360SN/A             "Trying to use un-updated ArmFault internal variables\n");
10851458SN/A
1086360SN/A    uint8_t fsc = 0;
1087360SN/A
10881999SN/A    if (!this->to64) {
10891999SN/A        // AArch32
10901999SN/A        assert(tranMethod != ArmFault::UnknownTran);
109111851Sbrandon.potter@amd.com        if (tranMethod == ArmFault::LpaeTran) {
10922680Sktlim@umich.edu            fsc = ArmFault::longDescFaultSources[source];
10931999SN/A        } else {
10941999SN/A            fsc = ArmFault::shortDescFaultSources[source];
10951999SN/A        }
10966701Sgblack@eecs.umich.edu    } else {
10978852Sandreas.hansson@arm.com        // AArch64
10986701Sgblack@eecs.umich.edu        fsc = ArmFault::aarch64FaultSources[source];
10996701Sgblack@eecs.umich.edu    }
11006701Sgblack@eecs.umich.edu
11016701Sgblack@eecs.umich.edu    return fsc;
11021999SN/A}
11033669Sbinkertn@umich.edu
11043669Sbinkertn@umich.edutemplate<class T>
11053669Sbinkertn@umich.eduFSR
11062764Sstever@eecs.umich.eduAbortFault<T>::getFsr(ThreadContext *tc) const
11072064SN/A{
11082064SN/A    FSR fsr = 0;
11092064SN/A
11101999SN/A    auto fsc = getFaultStatusCode(tc);
11111999SN/A
11122064SN/A    // AArch32
11131999SN/A    assert(tranMethod != ArmFault::UnknownTran);
11141999SN/A    if (tranMethod == ArmFault::LpaeTran) {
11151999SN/A        fsr.status = fsc;
11161999SN/A        fsr.lpae   = 1;
11178706Sandreas.hansson@arm.com    } else {
11181999SN/A        fsr.fsLow  = bits(fsc, 3, 0);
11191999SN/A        fsr.fsHigh = bits(fsc, 4);
11201999SN/A        fsr.domain = static_cast<uint8_t>(domain);
11211999SN/A    }
1122378SN/A
1123360SN/A    fsr.wnr = (write ? 1 : 0);
11241450SN/A    fsr.ext = 0;
112511856Sbrandon.potter@amd.com
1126360SN/A    return fsr;
11276701Sgblack@eecs.umich.edu}
112811856Sbrandon.potter@amd.com
112911856Sbrandon.potter@amd.comtemplate<class T>
1130360SN/Abool
113111380Salexandru.dutu@amd.comAbortFault<T>::abortDisable(ThreadContext *tc)
1132360SN/A{
113311856Sbrandon.potter@amd.com    if (ArmSystem::haveSecurity(tc)) {
113411856Sbrandon.potter@amd.com        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
11351458SN/A        return (!scr.ns || scr.aw);
113611856Sbrandon.potter@amd.com    }
1137360SN/A    return true;
1138360SN/A}
113910931Sbrandon.potter@amd.com
1140360SN/Atemplate<class T>
1141360SN/Avoid
11421458SN/AAbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val)
1143360SN/A{
114410931Sbrandon.potter@amd.com    switch (id)
11452021SN/A    {
11461458SN/A      case ArmFault::S1PTW:
1147360SN/A        s1ptw = val;
1148360SN/A        break;
1149360SN/A      case ArmFault::OVA:
11501706SN/A        OVAddr = val;
11511706SN/A        break;
11521706SN/A
115311851Sbrandon.potter@amd.com      // Just ignore unknown ID's
11542680Sktlim@umich.edu      default:
11551706SN/A        break;
115611799Sbrandon.potter@amd.com    }
115711799Sbrandon.potter@amd.com}
115811799Sbrandon.potter@amd.com
11591706SN/Atemplate<class T>
11601706SN/Auint32_t
11616701Sgblack@eecs.umich.eduAbortFault<T>::iss() const
11628852Sandreas.hansson@arm.com{
11636701Sgblack@eecs.umich.edu    uint32_t val;
11646701Sgblack@eecs.umich.edu
11656701Sgblack@eecs.umich.edu    val  = srcEncoded & 0x3F;
11666701Sgblack@eecs.umich.edu    val |= write << 6;
11671706SN/A    val |= s1ptw << 7;
11683669Sbinkertn@umich.edu    return (val);
11693669Sbinkertn@umich.edu}
11703669Sbinkertn@umich.edu
11711706SN/Atemplate<class T>
11721706SN/Abool
11731706SN/AAbortFault<T>::isMMUFault() const
11741706SN/A{
11752218SN/A    // NOTE: Not relying on LL information being aligned to lowest bits here
11761706SN/A    return
117711759Sbrandon.potter@amd.com         (source == ArmFault::AlignmentFault)     ||
117811799Sbrandon.potter@amd.com        ((source >= ArmFault::TranslationLL) &&
11791706SN/A         (source <  ArmFault::TranslationLL + 4)) ||
11801706SN/A        ((source >= ArmFault::AccessFlagLL) &&
11811706SN/A         (source <  ArmFault::AccessFlagLL + 4))  ||
11821706SN/A        ((source >= ArmFault::DomainLL) &&
11831706SN/A         (source <  ArmFault::DomainLL + 4))      ||
11841706SN/A        ((source >= ArmFault::PermissionLL) &&
11851706SN/A         (source <  ArmFault::PermissionLL + 4));
118611856Sbrandon.potter@amd.com}
11871706SN/A
11886701Sgblack@eecs.umich.eduExceptionClass
118911856Sbrandon.potter@amd.comPrefetchAbort::ec(ThreadContext *tc) const
119011856Sbrandon.potter@amd.com{
11911706SN/A    if (to64) {
119211856Sbrandon.potter@amd.com        // AArch64
119311856Sbrandon.potter@amd.com        if (toEL == fromEL)
11941706SN/A            return EC_PREFETCH_ABORT_CURR_EL;
119511856Sbrandon.potter@amd.com        else
11961706SN/A            return EC_PREFETCH_ABORT_LOWER_EL;
11971706SN/A    } else {
119810931Sbrandon.potter@amd.com        // AArch32
11991706SN/A        // Abort faults have different EC codes depending on whether
12001706SN/A        // the fault originated within HYP mode, or not. So override
12012218SN/A        // the method and add the extra adjustment of the EC value.
12021706SN/A
120311759Sbrandon.potter@amd.com        ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec;
12041706SN/A
12051706SN/A        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
12061706SN/A        if (spsr.mode == MODE_HYP) {
12071706SN/A            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
12081706SN/A        }
12091999SN/A        return ec;
12101999SN/A    }
12111999SN/A}
121211856Sbrandon.potter@amd.com
12131999SN/Abool
12146701Sgblack@eecs.umich.eduPrefetchAbort::routeToMonitor(ThreadContext *tc) const
121511856Sbrandon.potter@amd.com{
121610931Sbrandon.potter@amd.com    SCR scr = 0;
121711856Sbrandon.potter@amd.com    if (from64)
121811856Sbrandon.potter@amd.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
12191999SN/A    else
122011856Sbrandon.potter@amd.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
12211999SN/A
122211856Sbrandon.potter@amd.com    return scr.ea && !isMMUFault();
122311856Sbrandon.potter@amd.com}
122411856Sbrandon.potter@amd.com
12251999SN/Abool
12266227Snate@binkert.orgPrefetchAbort::routeToHyp(ThreadContext *tc) const
12271999SN/A{
12282461SN/A    bool toHyp;
122911856Sbrandon.potter@amd.com
123011856Sbrandon.potter@amd.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
12318737Skoansin.tan@gmail.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
12321999SN/A    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
123311856Sbrandon.potter@amd.com    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
123411856Sbrandon.potter@amd.com
12351999SN/A    // if in Hyp mode then stay in Hyp mode
12361999SN/A    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
123710931Sbrandon.potter@amd.com    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
12381999SN/A    toHyp |= (stage2 ||
12396227Snate@binkert.org                ( (source ==               DebugEvent) && hdcr.tde && (cpsr.mode !=  MODE_HYP)) ||
12401999SN/A                ( (source == SynchronousExternalAbort) && hcr.tge  && (cpsr.mode == MODE_USER))
12411999SN/A             ) && !inSecureState(tc);
12421999SN/A    return toHyp;
12432218SN/A}
12441999SN/A
124510629Sjthestness@gmail.comExceptionClass
12461999SN/ADataAbort::ec(ThreadContext *tc) const
12471999SN/A{
124811385Sbrandon.potter@amd.com    if (to64) {
1249360SN/A        // AArch64
12501450SN/A        if (source == ArmFault::AsynchronousExternalAbort) {
125111851Sbrandon.potter@amd.com            panic("Asynchronous External Abort should be handled with "
125211385Sbrandon.potter@amd.com                    "SystemErrors (SErrors)!");
1253360SN/A        }
12546701Sgblack@eecs.umich.edu        if (toEL == fromEL)
12556701Sgblack@eecs.umich.edu            return EC_DATA_ABORT_CURR_EL;
12566701Sgblack@eecs.umich.edu        else
125711383Sbrandon.potter@amd.com            return EC_DATA_ABORT_LOWER_EL;
125811383Sbrandon.potter@amd.com    } else {
12598324Ssteve.reinhardt@amd.com        // AArch32
126010486Stjablin@gmail.com        // Abort faults have different EC codes depending on whether
1261360SN/A        // the fault originated within HYP mode, or not. So override
126211385Sbrandon.potter@amd.com        // the method and add the extra adjustment of the EC value.
126311385Sbrandon.potter@amd.com
12649008Sgblack@eecs.umich.edu        ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec;
126511383Sbrandon.potter@amd.com
126611383Sbrandon.potter@amd.com        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
126711383Sbrandon.potter@amd.com        if (spsr.mode == MODE_HYP) {
126811383Sbrandon.potter@amd.com            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
126911383Sbrandon.potter@amd.com        }
127011383Sbrandon.potter@amd.com        return ec;
127111383Sbrandon.potter@amd.com    }
127211383Sbrandon.potter@amd.com}
127311383Sbrandon.potter@amd.com
12748324Ssteve.reinhardt@amd.combool
127511383Sbrandon.potter@amd.comDataAbort::routeToMonitor(ThreadContext *tc) const
127611383Sbrandon.potter@amd.com{
127711383Sbrandon.potter@amd.com    SCR scr = 0;
127811383Sbrandon.potter@amd.com    if (from64)
127911383Sbrandon.potter@amd.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
128011383Sbrandon.potter@amd.com    else
128111383Sbrandon.potter@amd.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
128211383Sbrandon.potter@amd.com
128311383Sbrandon.potter@amd.com    return scr.ea && !isMMUFault();
128411383Sbrandon.potter@amd.com}
128511383Sbrandon.potter@amd.com
128611383Sbrandon.potter@amd.combool
128711383Sbrandon.potter@amd.comDataAbort::routeToHyp(ThreadContext *tc) const
128811383Sbrandon.potter@amd.com{
128911383Sbrandon.potter@amd.com    bool toHyp;
129011383Sbrandon.potter@amd.com
129111383Sbrandon.potter@amd.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
129211383Sbrandon.potter@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
129311383Sbrandon.potter@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
129411383Sbrandon.potter@amd.com    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
129511383Sbrandon.potter@amd.com
129611383Sbrandon.potter@amd.com    // if in Hyp mode then stay in Hyp mode
129711383Sbrandon.potter@amd.com    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
129811383Sbrandon.potter@amd.com    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
12998324Ssteve.reinhardt@amd.com    toHyp |= (stage2 ||
13005877Shsul@eecs.umich.edu                ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) ||
130110486Stjablin@gmail.com                                               ((source == DebugEvent) && hdcr.tde) )
130210486Stjablin@gmail.com                ) ||
130311383Sbrandon.potter@amd.com                ( (cpsr.mode == MODE_USER) && hcr.tge &&
130411383Sbrandon.potter@amd.com                  ((source == AlignmentFault)            ||
130511383Sbrandon.potter@amd.com                   (source == SynchronousExternalAbort))
130611856Sbrandon.potter@amd.com                )
130711624Smichael.lebeane@amd.com             ) && !inSecureState(tc);
130811856Sbrandon.potter@amd.com    return toHyp;
130911856Sbrandon.potter@amd.com}
131011856Sbrandon.potter@amd.com
131111856Sbrandon.potter@amd.comuint32_t
131211624Smichael.lebeane@amd.comDataAbort::iss() const
131311624Smichael.lebeane@amd.com{
131411624Smichael.lebeane@amd.com    uint32_t val;
131511856Sbrandon.potter@amd.com
131611856Sbrandon.potter@amd.com    // Add on the data abort specific fields to the generic abort ISS value
131711383Sbrandon.potter@amd.com    val  = AbortFault<DataAbort>::iss();
131811856Sbrandon.potter@amd.com    // ISS is valid if not caused by a stage 1 page table walk, and when taken
1319360SN/A    // to AArch64 only when directed to EL2
132011383Sbrandon.potter@amd.com    if (!s1ptw && (!to64 || toEL == EL2)) {
132111383Sbrandon.potter@amd.com        val |= isv << 24;
13228600Ssteve.reinhardt@amd.com        if (isv) {
132311383Sbrandon.potter@amd.com            val |= sas << 22;
132411383Sbrandon.potter@amd.com            val |= sse << 21;
132511383Sbrandon.potter@amd.com            val |= srt << 16;
13268600Ssteve.reinhardt@amd.com            // AArch64 only. These assignments are safe on AArch32 as well
13272544SN/A            // because these vars are initialized to false
13282544SN/A            val |= sf << 15;
132911383Sbrandon.potter@amd.com            val |= ar << 14;
133011383Sbrandon.potter@amd.com        }
133111383Sbrandon.potter@amd.com    }
133211386Ssteve.reinhardt@amd.com    return (val);
133311386Ssteve.reinhardt@amd.com}
133411383Sbrandon.potter@amd.com
133511383Sbrandon.potter@amd.comvoid
133611383Sbrandon.potter@amd.comDataAbort::annotate(AnnotationIDs id, uint64_t val)
133711383Sbrandon.potter@amd.com{
133811383Sbrandon.potter@amd.com    AbortFault<DataAbort>::annotate(id, val);
133911383Sbrandon.potter@amd.com    switch (id)
134011383Sbrandon.potter@amd.com    {
134111383Sbrandon.potter@amd.com      case SAS:
134211383Sbrandon.potter@amd.com        isv = true;
134311383Sbrandon.potter@amd.com        sas = val;
134411383Sbrandon.potter@amd.com        break;
134511383Sbrandon.potter@amd.com      case SSE:
134611383Sbrandon.potter@amd.com        isv = true;
134711383Sbrandon.potter@amd.com        sse = val;
134811383Sbrandon.potter@amd.com        break;
13498600Ssteve.reinhardt@amd.com      case SRT:
13506672Sgblack@eecs.umich.edu        isv = true;
13518600Ssteve.reinhardt@amd.com        srt = val;
135211383Sbrandon.potter@amd.com        break;
135311383Sbrandon.potter@amd.com      case SF:
135411383Sbrandon.potter@amd.com        isv = true;
13558601Ssteve.reinhardt@amd.com        sf  = val;
13562544SN/A        break;
135711383Sbrandon.potter@amd.com      case AR:
135811383Sbrandon.potter@amd.com        isv = true;
135911383Sbrandon.potter@amd.com        ar  = val;
136011383Sbrandon.potter@amd.com        break;
136111383Sbrandon.potter@amd.com      // Just ignore unknown ID's
136211383Sbrandon.potter@amd.com      default:
136311383Sbrandon.potter@amd.com        break;
136411383Sbrandon.potter@amd.com    }
136511383Sbrandon.potter@amd.com}
136611383Sbrandon.potter@amd.com
136711383Sbrandon.potter@amd.comvoid
136811383Sbrandon.potter@amd.comVirtualDataAbort::invoke(ThreadContext *tc, const StaticInstPtr &inst)
136911383Sbrandon.potter@amd.com{
137011383Sbrandon.potter@amd.com    AbortFault<VirtualDataAbort>::invoke(tc, inst);
137111383Sbrandon.potter@amd.com    HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
137211383Sbrandon.potter@amd.com    hcr.va = 0;
137311383Sbrandon.potter@amd.com    tc->setMiscRegNoEffect(MISCREG_HCR, hcr);
137411383Sbrandon.potter@amd.com}
137511383Sbrandon.potter@amd.com
137611383Sbrandon.potter@amd.combool
137711383Sbrandon.potter@amd.comInterrupt::routeToMonitor(ThreadContext *tc) const
137811383Sbrandon.potter@amd.com{
137911383Sbrandon.potter@amd.com    assert(ArmSystem::haveSecurity(tc));
138011383Sbrandon.potter@amd.com    SCR scr = 0;
138111383Sbrandon.potter@amd.com    if (from64)
138211383Sbrandon.potter@amd.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
138311383Sbrandon.potter@amd.com    else
138411383Sbrandon.potter@amd.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
138511383Sbrandon.potter@amd.com    return scr.irq;
138611383Sbrandon.potter@amd.com}
138711383Sbrandon.potter@amd.com
138811383Sbrandon.potter@amd.combool
138911392Sbrandon.potter@amd.comInterrupt::routeToHyp(ThreadContext *tc) const
139011392Sbrandon.potter@amd.com{
139111392Sbrandon.potter@amd.com    bool toHyp;
139211392Sbrandon.potter@amd.com
139311392Sbrandon.potter@amd.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
139411392Sbrandon.potter@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
139511392Sbrandon.potter@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
139611392Sbrandon.potter@amd.com    // Determine whether IRQs are routed to Hyp mode.
139711392Sbrandon.potter@amd.com    toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) ||
139811392Sbrandon.potter@amd.com            (cpsr.mode == MODE_HYP);
139911392Sbrandon.potter@amd.com    return toHyp;
140011392Sbrandon.potter@amd.com}
140111392Sbrandon.potter@amd.com
140211392Sbrandon.potter@amd.combool
140311856Sbrandon.potter@amd.comInterrupt::abortDisable(ThreadContext *tc)
140411856Sbrandon.potter@amd.com{
140511856Sbrandon.potter@amd.com    if (ArmSystem::haveSecurity(tc)) {
140611392Sbrandon.potter@amd.com        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
140711392Sbrandon.potter@amd.com        return (!scr.ns || scr.aw);
140811392Sbrandon.potter@amd.com    }
140911392Sbrandon.potter@amd.com    return true;
141011392Sbrandon.potter@amd.com}
141111392Sbrandon.potter@amd.com
141211392Sbrandon.potter@amd.comVirtualInterrupt::VirtualInterrupt()
141311392Sbrandon.potter@amd.com{}
141411383Sbrandon.potter@amd.com
141511383Sbrandon.potter@amd.combool
141611383Sbrandon.potter@amd.comFastInterrupt::routeToMonitor(ThreadContext *tc) const
141711383Sbrandon.potter@amd.com{
141811383Sbrandon.potter@amd.com    assert(ArmSystem::haveSecurity(tc));
14191458SN/A    SCR scr = 0;
1420360SN/A    if (from64)
1421360SN/A        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
142211593Santhony.gutierrez@amd.com    else
142311593Santhony.gutierrez@amd.com        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
142411851Sbrandon.potter@amd.com    return scr.fiq;
142511593Santhony.gutierrez@amd.com}
142611593Santhony.gutierrez@amd.com
142711593Santhony.gutierrez@amd.combool
142811593Santhony.gutierrez@amd.comFastInterrupt::routeToHyp(ThreadContext *tc) const
142911593Santhony.gutierrez@amd.com{
143011593Santhony.gutierrez@amd.com    bool toHyp;
143111593Santhony.gutierrez@amd.com
143211856Sbrandon.potter@amd.com    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
143311856Sbrandon.potter@amd.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
143411593Santhony.gutierrez@amd.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
143511856Sbrandon.potter@amd.com    // Determine whether IRQs are routed to Hyp mode.
143611593Santhony.gutierrez@amd.com    toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) ||
143711593Santhony.gutierrez@amd.com            (cpsr.mode == MODE_HYP);
143811593Santhony.gutierrez@amd.com    return toHyp;
143911593Santhony.gutierrez@amd.com}
144011594Santhony.gutierrez@amd.com
144111593Santhony.gutierrez@amd.combool
144211593Santhony.gutierrez@amd.comFastInterrupt::abortDisable(ThreadContext *tc)
144311593Santhony.gutierrez@amd.com{
144411593Santhony.gutierrez@amd.com    if (ArmSystem::haveSecurity(tc)) {
144511385Sbrandon.potter@amd.com        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
144611385Sbrandon.potter@amd.com        return (!scr.ns || scr.aw);
144711385Sbrandon.potter@amd.com    }
144811851Sbrandon.potter@amd.com    return true;
144911385Sbrandon.potter@amd.com}
145011385Sbrandon.potter@amd.com
145111385Sbrandon.potter@amd.combool
145211385Sbrandon.potter@amd.comFastInterrupt::fiqDisable(ThreadContext *tc)
145311385Sbrandon.potter@amd.com{
145411385Sbrandon.potter@amd.com    if (ArmSystem::haveVirtualization(tc)) {
145511385Sbrandon.potter@amd.com        return true;
145611851Sbrandon.potter@amd.com    } else if (ArmSystem::haveSecurity(tc)) {
145711385Sbrandon.potter@amd.com        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
145811385Sbrandon.potter@amd.com        return (!scr.ns || scr.fw);
145911385Sbrandon.potter@amd.com    }
146011385Sbrandon.potter@amd.com    return true;
1461378SN/A}
1462360SN/A
14631450SN/AVirtualFastInterrupt::VirtualFastInterrupt()
146411851Sbrandon.potter@amd.com{}
146511851Sbrandon.potter@amd.com
1466360SN/Avoid
14676701Sgblack@eecs.umich.eduPCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
14686701Sgblack@eecs.umich.edu{
14696701Sgblack@eecs.umich.edu    ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
1470360SN/A    assert(from64);
1471360SN/A    // Set the FAR
14722064SN/A    tc->setMiscReg(getFaultAddrReg64(), faultPC);
14735877Shsul@eecs.umich.edu}
14742064SN/A
14758737Skoansin.tan@gmail.combool
14768737Skoansin.tan@gmail.comPCAlignmentFault::routeToHyp(ThreadContext *tc) const
14772064SN/A{
1478360SN/A    bool toHyp = false;
14795877Shsul@eecs.umich.edu
14805877Shsul@eecs.umich.edu    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
14815877Shsul@eecs.umich.edu    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
14828737Skoansin.tan@gmail.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
14838737Skoansin.tan@gmail.com
14845877Shsul@eecs.umich.edu    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
14855877Shsul@eecs.umich.edu    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.el == EL0);
14862064SN/A    return toHyp;
148710794Sbrandon.potter@amd.com}
148810794Sbrandon.potter@amd.com
14892064SN/ASPAlignmentFault::SPAlignmentFault()
1490360SN/A{}
1491360SN/A
14928706Sandreas.hansson@arm.comSystemError::SystemError()
14931458SN/A{}
1494360SN/A
1495360SN/Avoid
149610796Sbrandon.potter@amd.comSystemError::invoke(ThreadContext *tc, const StaticInstPtr &inst)
149710796Sbrandon.potter@amd.com{
149810796Sbrandon.potter@amd.com    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
149911851Sbrandon.potter@amd.com    ArmFault::invoke(tc, inst);
150010796Sbrandon.potter@amd.com}
150110796Sbrandon.potter@amd.com
150210796Sbrandon.potter@amd.combool
150310796Sbrandon.potter@amd.comSystemError::routeToMonitor(ThreadContext *tc) const
150410796Sbrandon.potter@amd.com{
150510796Sbrandon.potter@amd.com    assert(ArmSystem::haveSecurity(tc));
150610796Sbrandon.potter@amd.com    assert(from64);
150710796Sbrandon.potter@amd.com    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
150810796Sbrandon.potter@amd.com    return scr.ea;
150910796Sbrandon.potter@amd.com}
151010796Sbrandon.potter@amd.com
151110796Sbrandon.potter@amd.combool
151210796Sbrandon.potter@amd.comSystemError::routeToHyp(ThreadContext *tc) const
151310796Sbrandon.potter@amd.com{
151410796Sbrandon.potter@amd.com    bool toHyp;
151511337SMichael.Lebeane@amd.com    assert(from64);
151611337SMichael.Lebeane@amd.com
151711337SMichael.Lebeane@amd.com    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
151811851Sbrandon.potter@amd.com    HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
151911337SMichael.Lebeane@amd.com
152011337SMichael.Lebeane@amd.com    toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) ||
152111337SMichael.Lebeane@amd.com            (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc));
152211337SMichael.Lebeane@amd.com    return toHyp;
152311337SMichael.Lebeane@amd.com}
152411337SMichael.Lebeane@amd.com
152511337SMichael.Lebeane@amd.com
152611337SMichael.Lebeane@amd.comSoftwareBreakpoint::SoftwareBreakpoint(ExtMachInst _mach_inst, uint32_t _iss)
152711337SMichael.Lebeane@amd.com    : ArmFaultVals<SoftwareBreakpoint>(_mach_inst, _iss)
152811337SMichael.Lebeane@amd.com{}
152911337SMichael.Lebeane@amd.com
153011337SMichael.Lebeane@amd.combool
153111337SMichael.Lebeane@amd.comSoftwareBreakpoint::routeToHyp(ThreadContext *tc) const
1532378SN/A{
1533360SN/A    const bool have_el2 = ArmSystem::haveVirtualization(tc);
15341450SN/A
153511851Sbrandon.potter@amd.com    const HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
153611851Sbrandon.potter@amd.com    const HDCR mdcr  = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
1537360SN/A
15386701Sgblack@eecs.umich.edu    return have_el2 && !inSecureState(tc) && fromEL <= EL1 &&
15396701Sgblack@eecs.umich.edu        (hcr.tge || mdcr.tde);
1540360SN/A}
154110796Sbrandon.potter@amd.com
1542360SN/AExceptionClass
15436109Ssanchezd@stanford.eduSoftwareBreakpoint::ec(ThreadContext *tc) const
15446109Ssanchezd@stanford.edu{
1545360SN/A    return from64 ? EC_SOFTWARE_BREAKPOINT_64 : vals.ec;
15468706Sandreas.hansson@arm.com}
1547360SN/A
15481458SN/Avoid
1549360SN/AArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
1550360SN/A    DPRINTF(Faults, "Invoking ArmSev Fault\n");
1551360SN/A    if (!FullSystem)
15521999SN/A        return;
15531999SN/A
15541999SN/A    // Set sev_mailbox to 1, clear the pending interrupt from remote
155511851Sbrandon.potter@amd.com    // SEV execution and let pipeline continue as pcState is still
15562680Sktlim@umich.edu    // valid.
15571999SN/A    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
15581999SN/A    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0);
15591999SN/A}
15606701Sgblack@eecs.umich.edu
15618852Sandreas.hansson@arm.com// Instantiate all the templates to make the linker happy
15626701Sgblack@eecs.umich.edutemplate class ArmFaultVals<Reset>;
15636701Sgblack@eecs.umich.edutemplate class ArmFaultVals<UndefinedInstruction>;
15646701Sgblack@eecs.umich.edutemplate class ArmFaultVals<SupervisorCall>;
15651999SN/Atemplate class ArmFaultVals<SecureMonitorCall>;
15666701Sgblack@eecs.umich.edutemplate class ArmFaultVals<HypervisorCall>;
15676701Sgblack@eecs.umich.edutemplate class ArmFaultVals<PrefetchAbort>;
15688706Sandreas.hansson@arm.comtemplate class ArmFaultVals<DataAbort>;
15691999SN/Atemplate class ArmFaultVals<VirtualDataAbort>;
15701999SN/Atemplate class ArmFaultVals<HypervisorTrap>;
15711999SN/Atemplate class ArmFaultVals<Interrupt>;
15721999SN/Atemplate class ArmFaultVals<VirtualInterrupt>;
15738737Skoansin.tan@gmail.comtemplate class ArmFaultVals<FastInterrupt>;
15748737Skoansin.tan@gmail.comtemplate class ArmFaultVals<VirtualFastInterrupt>;
15751999SN/Atemplate class ArmFaultVals<SupervisorTrap>;
15763669Sbinkertn@umich.edutemplate class ArmFaultVals<SecureMonitorTrap>;
15773669Sbinkertn@umich.edutemplate class ArmFaultVals<PCAlignmentFault>;
15783669Sbinkertn@umich.edutemplate class ArmFaultVals<SPAlignmentFault>;
15793669Sbinkertn@umich.edutemplate class ArmFaultVals<SystemError>;
15801999SN/Atemplate class ArmFaultVals<SoftwareBreakpoint>;
15811999SN/Atemplate class ArmFaultVals<ArmSev>;
15821999SN/Atemplate class AbortFault<PrefetchAbort>;
15831999SN/Atemplate class AbortFault<DataAbort>;
15841999SN/Atemplate class AbortFault<VirtualDataAbort>;
15851999SN/A
15861999SN/A
1587378SN/AIllegalInstSetStateFault::IllegalInstSetStateFault()
1588360SN/A{}
15891450SN/A
159011851Sbrandon.potter@amd.com
15912680Sktlim@umich.edu} // namespace ArmISA
1592360SN/A