faults.cc revision 12259:f787f664d57a
12810SN/A/*
29614Srene.dejong@arm.com * Copyright (c) 2010, 2012-2014, 2016-2017 ARM Limited
38856Sandreas.hansson@arm.com * All rights reserved
48856Sandreas.hansson@arm.com *
58856Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
68856Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
78856Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
88856Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
98856Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
108856Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
118856Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
128856Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
138856Sandreas.hansson@arm.com *
142810SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
152810SN/A * Copyright (c) 2007-2008 The Florida State University
162810SN/A * All rights reserved.
172810SN/A *
182810SN/A * Redistribution and use in source and binary forms, with or without
192810SN/A * modification, are permitted provided that the following conditions are
202810SN/A * met: redistributions of source code must retain the above copyright
212810SN/A * notice, this list of conditions and the following disclaimer;
222810SN/A * redistributions in binary form must reproduce the above copyright
232810SN/A * notice, this list of conditions and the following disclaimer in the
242810SN/A * documentation and/or other materials provided with the distribution;
252810SN/A * neither the name of the copyright holders nor the names of its
262810SN/A * contributors may be used to endorse or promote products derived from
272810SN/A * this software without specific prior written permission.
282810SN/A *
292810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
302810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
322810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
332810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
352810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
382810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
392810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402810SN/A *
412810SN/A * Authors: Ali Saidi
422810SN/A *          Gabe Black
432810SN/A *          Giacomo Gabrielli
442810SN/A *          Thomas Grocutt
452810SN/A */
462810SN/A
472810SN/A#include "arch/arm/faults.hh"
488232Snate@binkert.org
499152Satgutier@umich.edu#include "arch/arm/insts/static_inst.hh"
509795Sandreas.hansson@arm.com#include "arch/arm/system.hh"
519795Sandreas.hansson@arm.com#include "arch/arm/utility.hh"
5210263Satgutier@umich.edu#include "base/compiler.hh"
535338Sstever@gmail.com#include "base/trace.hh"
549795Sandreas.hansson@arm.com#include "cpu/base.hh"
555338Sstever@gmail.com#include "cpu/thread_context.hh"
568786Sgblack@eecs.umich.edu#include "debug/Faults.hh"
572810SN/A#include "sim/full_system.hh"
582810SN/A
592810SN/Anamespace ArmISA
608856Sandreas.hansson@arm.com{
618856Sandreas.hansson@arm.com
628856Sandreas.hansson@arm.comuint8_t ArmFault::shortDescFaultSources[] = {
638922Swilliam.wang@arm.com    0x01,  // AlignmentFault
648914Sandreas.hansson@arm.com    0x04,  // InstructionCacheMaintenance
658856Sandreas.hansson@arm.com    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
668856Sandreas.hansson@arm.com    0x0c,  // SynchExtAbtOnTranslTableWalkL1
674475SN/A    0x0e,  // SynchExtAbtOnTranslTableWalkL2
6811053Sandreas.hansson@arm.com    0xff,  // SynchExtAbtOnTranslTableWalkL3 (INVALID)
695034SN/A    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
7010360Sandreas.hansson@arm.com    0x1c,  // SynchPtyErrOnTranslTableWalkL1
7111377Sandreas.hansson@arm.com    0x1e,  // SynchPtyErrOnTranslTableWalkL2
7211377Sandreas.hansson@arm.com    0xff,  // SynchPtyErrOnTranslTableWalkL3 (INVALID)
7311053Sandreas.hansson@arm.com    0xff,  // TranslationL0 (INVALID)
7410693SMarco.Balboni@ARM.com    0x05,  // TranslationL1
7510693SMarco.Balboni@ARM.com    0x07,  // TranslationL2
7610693SMarco.Balboni@ARM.com    0xff,  // TranslationL3 (INVALID)
779263Smrinmoy.ghosh@arm.com    0xff,  // AccessFlagL0 (INVALID)
785034SN/A    0x03,  // AccessFlagL1
7911331Sandreas.hansson@arm.com    0x06,  // AccessFlagL2
8010884Sandreas.hansson@arm.com    0xff,  // AccessFlagL3 (INVALID)
814626SN/A    0xff,  // DomainL0 (INVALID)
8210360Sandreas.hansson@arm.com    0x09,  // DomainL1
834626SN/A    0x0b,  // DomainL2
845034SN/A    0xff,  // DomainL3 (INVALID)
858883SAli.Saidi@ARM.com    0xff,  // PermissionL0 (INVALID)
868833Sdam.sunwoo@arm.com    0x0d,  // PermissionL1
874458SN/A    0x0f,  // PermissionL2
8811377Sandreas.hansson@arm.com    0xff,  // PermissionL3 (INVALID)
8911377Sandreas.hansson@arm.com    0x02,  // DebugEvent
9011377Sandreas.hansson@arm.com    0x08,  // SynchronousExternalAbort
9111377Sandreas.hansson@arm.com    0x10,  // TLBConflictAbort
9211377Sandreas.hansson@arm.com    0x19,  // SynchPtyErrOnMemoryAccess
9311377Sandreas.hansson@arm.com    0x16,  // AsynchronousExternalAbort
9411331Sandreas.hansson@arm.com    0x18,  // AsynchPtyErrOnMemoryAccess
9511331Sandreas.hansson@arm.com    0xff,  // AddressSizeL0 (INVALID)
962810SN/A    0xff,  // AddressSizeL1 (INVALID)
972810SN/A    0xff,  // AddressSizeL2 (INVALID)
983013SN/A    0xff,  // AddressSizeL3 (INVALID)
998856Sandreas.hansson@arm.com    0x40,  // PrefetchTLBMiss
1002810SN/A    0x80   // PrefetchUncacheable
1013013SN/A};
10210714Sandreas.hansson@arm.com
1032810SN/Astatic_assert(sizeof(ArmFault::shortDescFaultSources) ==
1049614Srene.dejong@arm.com              ArmFault::NumFaultSources,
1059614Srene.dejong@arm.com              "Invalid size of ArmFault::shortDescFaultSources[]");
1069614Srene.dejong@arm.com
10710345SCurtis.Dunham@arm.comuint8_t ArmFault::longDescFaultSources[] = {
10810714Sandreas.hansson@arm.com    0x21,  // AlignmentFault
10910345SCurtis.Dunham@arm.com    0xff,  // InstructionCacheMaintenance (INVALID)
1109614Srene.dejong@arm.com    0xff,  // SynchExtAbtOnTranslTableWalkL0 (INVALID)
1112810SN/A    0x15,  // SynchExtAbtOnTranslTableWalkL1
1122810SN/A    0x16,  // SynchExtAbtOnTranslTableWalkL2
1132810SN/A    0x17,  // SynchExtAbtOnTranslTableWalkL3
1148856Sandreas.hansson@arm.com    0xff,  // SynchPtyErrOnTranslTableWalkL0 (INVALID)
1152810SN/A    0x1d,  // SynchPtyErrOnTranslTableWalkL1
1163013SN/A    0x1e,  // SynchPtyErrOnTranslTableWalkL2
11710714Sandreas.hansson@arm.com    0x1f,  // SynchPtyErrOnTranslTableWalkL3
1183013SN/A    0xff,  // TranslationL0 (INVALID)
1198856Sandreas.hansson@arm.com    0x05,  // TranslationL1
12010714Sandreas.hansson@arm.com    0x06,  // TranslationL2
1218922Swilliam.wang@arm.com    0x07,  // TranslationL3
1222897SN/A    0xff,  // AccessFlagL0 (INVALID)
1232810SN/A    0x09,  // AccessFlagL1
1242810SN/A    0x0a,  // AccessFlagL2
12510344Sandreas.hansson@arm.com    0x0b,  // AccessFlagL3
12610344Sandreas.hansson@arm.com    0xff,  // DomainL0 (INVALID)
12710344Sandreas.hansson@arm.com    0x3d,  // DomainL1
12810714Sandreas.hansson@arm.com    0x3e,  // DomainL2
12910344Sandreas.hansson@arm.com    0xff,  // DomainL3 (RESERVED)
13010344Sandreas.hansson@arm.com    0xff,  // PermissionL0 (INVALID)
13110344Sandreas.hansson@arm.com    0x0d,  // PermissionL1
13210713Sandreas.hansson@arm.com    0x0e,  // PermissionL2
13310344Sandreas.hansson@arm.com    0x0f,  // PermissionL3
1342844SN/A    0x22,  // DebugEvent
1352810SN/A    0x10,  // SynchronousExternalAbort
1362858SN/A    0x30,  // TLBConflictAbort
1372858SN/A    0x18,  // SynchPtyErrOnMemoryAccess
1388856Sandreas.hansson@arm.com    0x11,  // AsynchronousExternalAbort
1398922Swilliam.wang@arm.com    0x19,  // AsynchPtyErrOnMemoryAccess
1408711Sandreas.hansson@arm.com    0xff,  // AddressSizeL0 (INVALID)
14111331Sandreas.hansson@arm.com    0xff,  // AddressSizeL1 (INVALID)
1422858SN/A    0xff,  // AddressSizeL2 (INVALID)
1432858SN/A    0xff,  // AddressSizeL3 (INVALID)
1449294Sandreas.hansson@arm.com    0x40,  // PrefetchTLBMiss
1459294Sandreas.hansson@arm.com    0x80   // PrefetchUncacheable
1468922Swilliam.wang@arm.com};
1478922Swilliam.wang@arm.com
1488922Swilliam.wang@arm.comstatic_assert(sizeof(ArmFault::longDescFaultSources) ==
1498922Swilliam.wang@arm.com              ArmFault::NumFaultSources,
1508922Swilliam.wang@arm.com              "Invalid size of ArmFault::longDescFaultSources[]");
1518922Swilliam.wang@arm.com
1528922Swilliam.wang@arm.comuint8_t ArmFault::aarch64FaultSources[] = {
1538922Swilliam.wang@arm.com    0x21,  // AlignmentFault
1549294Sandreas.hansson@arm.com    0xff,  // InstructionCacheMaintenance (INVALID)
1559294Sandreas.hansson@arm.com    0x14,  // SynchExtAbtOnTranslTableWalkL0
1568922Swilliam.wang@arm.com    0x15,  // SynchExtAbtOnTranslTableWalkL1
1578922Swilliam.wang@arm.com    0x16,  // SynchExtAbtOnTranslTableWalkL2
1588922Swilliam.wang@arm.com    0x17,  // SynchExtAbtOnTranslTableWalkL3
1598922Swilliam.wang@arm.com    0x1c,  // SynchPtyErrOnTranslTableWalkL0
1608922Swilliam.wang@arm.com    0x1d,  // SynchPtyErrOnTranslTableWalkL1
1618922Swilliam.wang@arm.com    0x1e,  // SynchPtyErrOnTranslTableWalkL2
1628922Swilliam.wang@arm.com    0x1f,  // SynchPtyErrOnTranslTableWalkL3
1634628SN/A    0x04,  // TranslationL0
16410821Sandreas.hansson@arm.com    0x05,  // TranslationL1
16510821Sandreas.hansson@arm.com    0x06,  // TranslationL2
16610821Sandreas.hansson@arm.com    0x07,  // TranslationL3
16710821Sandreas.hansson@arm.com    0x08,  // AccessFlagL0
16810821Sandreas.hansson@arm.com    0x09,  // AccessFlagL1
16910821Sandreas.hansson@arm.com    0x0a,  // AccessFlagL2
17010821Sandreas.hansson@arm.com    0x0b,  // AccessFlagL3
17110821Sandreas.hansson@arm.com    // @todo: Section & Page Domain Fault in AArch64?
17210821Sandreas.hansson@arm.com    0xff,  // DomainL0 (INVALID)
17310821Sandreas.hansson@arm.com    0xff,  // DomainL1 (INVALID)
17410821Sandreas.hansson@arm.com    0xff,  // DomainL2 (INVALID)
1752858SN/A    0xff,  // DomainL3 (INVALID)
1762810SN/A    0x0c,  // PermissionL0
1772810SN/A    0x0d,  // PermissionL1
1782810SN/A    0x0e,  // PermissionL2
1792810SN/A    0x0f,  // PermissionL3
1802810SN/A    0xff,  // DebugEvent (INVALID)
1814022SN/A    0x10,  // SynchronousExternalAbort
1824022SN/A    0x30,  // TLBConflictAbort
1834022SN/A    0x18,  // SynchPtyErrOnMemoryAccess
1842810SN/A    0xff,  // AsynchronousExternalAbort (INVALID)
1852810SN/A    0xff,  // AsynchPtyErrOnMemoryAccess (INVALID)
1868833Sdam.sunwoo@arm.com    0x00,  // AddressSizeL0
1872810SN/A    0x01,  // AddressSizeL1
1882810SN/A    0x02,  // AddressSizeL2
1892810SN/A    0x03,  // AddressSizeL3
1902810SN/A    0x40,  // PrefetchTLBMiss
1918833Sdam.sunwoo@arm.com    0x80   // PrefetchUncacheable
1928833Sdam.sunwoo@arm.com};
1938833Sdam.sunwoo@arm.com
1942810SN/Astatic_assert(sizeof(ArmFault::aarch64FaultSources) ==
1952810SN/A              ArmFault::NumFaultSources,
1964871SN/A              "Invalid size of ArmFault::aarch64FaultSources[]");
1974871SN/A
1984871SN/A// Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode,
1994871SN/A//         {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap,
20010885Sandreas.hansson@arm.com//         {A, F} disable, class, stat
20110885Sandreas.hansson@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals = {
2024871SN/A    // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED
2034871SN/A    // location in AArch64)
2044871SN/A    "Reset",                 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2054871SN/A    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2064871SN/A};
2072810SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals = {
2082810SN/A    "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
2092810SN/A    4, 2, 0, 0, true,  false, false, EC_UNKNOWN, FaultStat()
2108833Sdam.sunwoo@arm.com};
2112810SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals = {
2124871SN/A    "Supervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2138833Sdam.sunwoo@arm.com    4, 2, 4, 2, true,  false, false, EC_SVC_TO_HYP, FaultStat()
2148833Sdam.sunwoo@arm.com};
2158833Sdam.sunwoo@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals = {
2162810SN/A    "Secure Monitor Call",   0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2172810SN/A    4, 4, 4, 4, false, true,  true,  EC_SMC_TO_HYP, FaultStat()
2182810SN/A};
2192810SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals = {
2208833Sdam.sunwoo@arm.com    "Hypervisor Call",       0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2212810SN/A    4, 4, 4, 4, true,  false, false, EC_HVC, FaultStat()
2224871SN/A};
2238833Sdam.sunwoo@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals = {
2248833Sdam.sunwoo@arm.com    "Prefetch Abort",        0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2258833Sdam.sunwoo@arm.com    4, 4, 0, 0, true,  true,  false, EC_PREFETCH_ABORT_TO_HYP, FaultStat()
2262810SN/A};
2272810SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals = {
2284022SN/A    "Data Abort",            0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2294022SN/A    8, 8, 0, 0, true,  true,  false, EC_DATA_ABORT_TO_HYP, FaultStat()
2304022SN/A};
2312810SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals = {
2322810SN/A    "Virtual Data Abort",    0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
2338833Sdam.sunwoo@arm.com    8, 8, 0, 0, true,  true,  false, EC_INVALID, FaultStat()
2342810SN/A};
2352810SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals = {
2362810SN/A    // @todo: double check these values
2372810SN/A    "Hypervisor Trap",       0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
2388833Sdam.sunwoo@arm.com    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
2398833Sdam.sunwoo@arm.com};
2408833Sdam.sunwoo@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals = {
2412810SN/A    "IRQ",                   0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2422810SN/A    4, 4, 0, 0, false, true,  false, EC_UNKNOWN, FaultStat()
2432810SN/A};
2442810SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals = {
2452810SN/A    "Virtual IRQ",           0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
2468833Sdam.sunwoo@arm.com    4, 4, 0, 0, false, true,  false, EC_INVALID, FaultStat()
2472810SN/A};
2484871SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals = {
2498833Sdam.sunwoo@arm.com    "FIQ",                   0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2508833Sdam.sunwoo@arm.com    4, 4, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2518833Sdam.sunwoo@arm.com};
2522810SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals = {
2532810SN/A    "Virtual FIQ",           0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
2542810SN/A    4, 4, 0, 0, false, true,  true,  EC_INVALID, FaultStat()
2552810SN/A};
2568833Sdam.sunwoo@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals = {
2572810SN/A    // Some dummy values (SupervisorTrap is AArch64-only)
2584871SN/A    "Supervisor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2598833Sdam.sunwoo@arm.com    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
2608833Sdam.sunwoo@arm.com};
2618833Sdam.sunwoo@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals = {
2622810SN/A    // Some dummy values (SecureMonitorTrap is AArch64-only)
2632810SN/A    "Secure Monitor Trap",   0x014, 0x000, 0x200, 0x400, 0x600, MODE_MON,
2644022SN/A    0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat()
2654022SN/A};
2664022SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals = {
2672810SN/A    // Some dummy values (PCAlignmentFault is AArch64-only)
2682810SN/A    "PC Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2698833Sdam.sunwoo@arm.com    0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT, FaultStat()
2702810SN/A};
2712810SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals = {
2722810SN/A    // Some dummy values (SPAlignmentFault is AArch64-only)
2732810SN/A    "SP Alignment Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2748833Sdam.sunwoo@arm.com    0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT, FaultStat()
2758833Sdam.sunwoo@arm.com};
2768833Sdam.sunwoo@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals = {
2772810SN/A    // Some dummy values (SError is AArch64-only)
2782810SN/A    "SError",                0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC,
2792810SN/A    0, 0, 0, 0, false, true,  true,  EC_SERROR, FaultStat()
2802810SN/A};
2812810SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals = {
2828833Sdam.sunwoo@arm.com    // Some dummy values
2832810SN/A    "ArmSev Flush",          0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
2844871SN/A    0, 0, 0, 0, false, true,  true,  EC_UNKNOWN, FaultStat()
2858833Sdam.sunwoo@arm.com};
2868833Sdam.sunwoo@arm.comtemplate<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals = {
2878833Sdam.sunwoo@arm.com    // Some dummy values (SPAlignmentFault is AArch64-only)
2882810SN/A    "Illegal Inst Set State Fault",   0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
2892810SN/A    0, 0, 0, 0, true, false, false, EC_ILLEGAL_INST, FaultStat()
2902810SN/A};
2912810SN/A
2928833Sdam.sunwoo@arm.comAddr
2932810SN/AArmFault::getVector(ThreadContext *tc)
2944871SN/A{
2958833Sdam.sunwoo@arm.com    Addr base;
2968833Sdam.sunwoo@arm.com
2978833Sdam.sunwoo@arm.com    // ARM ARM issue C B1.8.1
2982810SN/A    bool haveSecurity = ArmSystem::haveSecurity(tc);
2992810SN/A
3004022SN/A    // panic if SCTLR.VE because I have no idea what to do with vectored
3014022SN/A    // interrupts
3024022SN/A    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
3032810SN/A    assert(!sctlr.ve);
3042810SN/A    // Check for invalid modes
3052810SN/A    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
3062810SN/A    assert(haveSecurity                      || cpsr.mode != MODE_MON);
3072810SN/A    assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
3082810SN/A
3098833Sdam.sunwoo@arm.com    switch (cpsr.mode)
3102810SN/A    {
3118833Sdam.sunwoo@arm.com      case MODE_MON:
3128833Sdam.sunwoo@arm.com        base = tc->readMiscReg(MISCREG_MVBAR);
3138833Sdam.sunwoo@arm.com        break;
3142810SN/A      case MODE_HYP:
3152810SN/A        base = tc->readMiscReg(MISCREG_HVBAR);
3162810SN/A        break;
3172810SN/A      default:
3182810SN/A        if (sctlr.v) {
3198833Sdam.sunwoo@arm.com            base = HighVecs;
3202810SN/A        } else {
3212810SN/A            base = haveSecurity ? tc->readMiscReg(MISCREG_VBAR) : 0;
3228833Sdam.sunwoo@arm.com        }
3238833Sdam.sunwoo@arm.com        break;
3248833Sdam.sunwoo@arm.com    }
3252810SN/A    return base + offset(tc);
3262810SN/A}
3272810SN/A
3282810SN/AAddr
3298833Sdam.sunwoo@arm.comArmFault::getVector64(ThreadContext *tc)
3302810SN/A{
3312810SN/A    Addr vbar;
3328833Sdam.sunwoo@arm.com    switch (toEL) {
3338833Sdam.sunwoo@arm.com      case EL3:
3348833Sdam.sunwoo@arm.com        assert(ArmSystem::haveSecurity(tc));
3352810SN/A        vbar = tc->readMiscReg(MISCREG_VBAR_EL3);
3362810SN/A        break;
3374022SN/A      case EL2:
3384022SN/A        assert(ArmSystem::haveVirtualization(tc));
3394022SN/A        vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
3402810SN/A        break;
3412810SN/A      case EL1:
3422810SN/A        vbar = tc->readMiscReg(MISCREG_VBAR_EL1);
3432810SN/A        break;
3442810SN/A      default:
3452810SN/A        panic("Invalid target exception level");
3468833Sdam.sunwoo@arm.com        break;
3472810SN/A    }
3488833Sdam.sunwoo@arm.com    return vbar + offset64();
3498833Sdam.sunwoo@arm.com}
3508833Sdam.sunwoo@arm.com
3512810SN/AMiscRegIndex
3522810SN/AArmFault::getSyndromeReg64() const
3532810SN/A{
3542810SN/A    switch (toEL) {
3552810SN/A      case EL1:
3568833Sdam.sunwoo@arm.com        return MISCREG_ESR_EL1;
3572810SN/A      case EL2:
3582810SN/A        return MISCREG_ESR_EL2;
3598833Sdam.sunwoo@arm.com      case EL3:
3608833Sdam.sunwoo@arm.com        return MISCREG_ESR_EL3;
3618833Sdam.sunwoo@arm.com      default:
3622810SN/A        panic("Invalid exception level");
3632810SN/A        break;
3642810SN/A    }
3652810SN/A}
3668833Sdam.sunwoo@arm.com
3672810SN/AMiscRegIndex
3682810SN/AArmFault::getFaultAddrReg64() const
3698833Sdam.sunwoo@arm.com{
3708833Sdam.sunwoo@arm.com    switch (toEL) {
3718833Sdam.sunwoo@arm.com      case EL1:
3722810SN/A        return MISCREG_FAR_EL1;
3732810SN/A      case EL2:
3744022SN/A        return MISCREG_FAR_EL2;
3754022SN/A      case EL3:
3764022SN/A        return MISCREG_FAR_EL3;
3772810SN/A      default:
3782810SN/A        panic("Invalid exception level");
3792810SN/A        break;
3802810SN/A    }
3812810SN/A}
3822810SN/A
3832810SN/Avoid
3842810SN/AArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
3858833Sdam.sunwoo@arm.com{
3868833Sdam.sunwoo@arm.com    uint32_t value;
3878833Sdam.sunwoo@arm.com    uint32_t exc_class = (uint32_t) ec(tc);
3888833Sdam.sunwoo@arm.com    uint32_t issVal = iss();
3892810SN/A    assert(!from64 || ArmSystem::highestELIs64(tc));
3902810SN/A
3912810SN/A    value = exc_class << 26;
3922810SN/A
3932810SN/A    // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24,
3948833Sdam.sunwoo@arm.com    // 0x25) for which the ISS information is not valid (ARMv7).
3952810SN/A    // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not
3962810SN/A    // valid it is treated as RES1.
3978833Sdam.sunwoo@arm.com    if (to64) {
3988833Sdam.sunwoo@arm.com        value |= 1 << 25;
3998833Sdam.sunwoo@arm.com    } else if ((bits(exc_class, 5, 3) != 4) ||
4002810SN/A               (bits(exc_class, 2) && bits(issVal, 24))) {
4012810SN/A        if (!machInst.thumb || machInst.bigThumb)
4022810SN/A            value |= 1 << 25;
4032810SN/A    }
4048833Sdam.sunwoo@arm.com    // Condition code valid for EC[5:4] nonzero
4052810SN/A    if (!from64 && ((bits(exc_class, 5, 4) == 0) &&
4062810SN/A                    (bits(exc_class, 3, 0) != 0))) {
4078833Sdam.sunwoo@arm.com        if (!machInst.thumb) {
4088833Sdam.sunwoo@arm.com            uint32_t      cond;
4098833Sdam.sunwoo@arm.com            ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode;
4102810SN/A            // If its on unconditional instruction report with a cond code of
4112810SN/A            // 0xE, ie the unconditional code
4122810SN/A            cond  = (condCode == COND_UC) ? COND_AL : condCode;
4132810SN/A            value |= cond << 20;
4142810SN/A            value |= 1    << 24;
4152810SN/A        }
4162810SN/A        value |= bits(issVal, 19, 0);
4172810SN/A    } else {
4182810SN/A        value |= issVal;
4192810SN/A    }
4202810SN/A    tc->setMiscReg(syndrome_reg, value);
4212810SN/A}
4222810SN/A
4232810SN/Avoid
4242810SN/AArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
4252810SN/A{
4262810SN/A    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
4272810SN/A
4282810SN/A    if (ArmSystem::highestELIs64(tc)) {  // ARMv8
4292810SN/A        // Determine source exception level and mode
4302810SN/A        fromMode = (OperatingMode) (uint8_t) cpsr.mode;
4312810SN/A        fromEL = opModeToEL(fromMode);
4322810SN/A        if (opModeIs64(fromMode))
4332810SN/A            from64 = true;
4342810SN/A
4352810SN/A        // Determine target exception level
4362810SN/A        if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc))
4372810SN/A            toEL = EL3;
4382810SN/A        else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc))
4392810SN/A            toEL = EL2;
4402810SN/A        else
4412810SN/A            toEL = opModeToEL(nextMode());
4422810SN/A        if (fromEL > toEL)
4432810SN/A            toEL = fromEL;
4442810SN/A
4452810SN/A        if (toEL == ArmSystem::highestEL(tc) || ELIs64(tc, toEL)) {
4462826SN/A            // Invoke exception handler in AArch64 state
44711436SRekai.GonzalezAlberquilla@arm.com            to64 = true;
44811436SRekai.GonzalezAlberquilla@arm.com            invoke64(tc, inst);
44911436SRekai.GonzalezAlberquilla@arm.com            return;
45011436SRekai.GonzalezAlberquilla@arm.com        }
45111436SRekai.GonzalezAlberquilla@arm.com    }
45211436SRekai.GonzalezAlberquilla@arm.com
4534626SN/A    // ARMv7 (ARM ARM issue C B1.9)
4548833Sdam.sunwoo@arm.com
4554626SN/A    bool have_security       = ArmSystem::haveSecurity(tc);
4564626SN/A    bool have_virtualization = ArmSystem::haveVirtualization(tc);
4578833Sdam.sunwoo@arm.com
4584626SN/A    FaultBase::invoke(tc);
4598833Sdam.sunwoo@arm.com    if (!FullSystem)
4608833Sdam.sunwoo@arm.com        return;
4618833Sdam.sunwoo@arm.com    countStat()++;
4624626SN/A
4634626SN/A    SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
4644626SN/A    SCR scr = tc->readMiscReg(MISCREG_SCR);
4654626SN/A    CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR);
4664626SN/A    saved_cpsr.nz = tc->readCCReg(CCREG_NZ);
4674626SN/A    saved_cpsr.c = tc->readCCReg(CCREG_C);
4684626SN/A    saved_cpsr.v = tc->readCCReg(CCREG_V);
4694626SN/A    saved_cpsr.ge = tc->readCCReg(CCREG_GE);
4708833Sdam.sunwoo@arm.com
4714626SN/A    Addr curPc M5_VAR_USED = tc->pcState().pc();
4724626SN/A    ITSTATE it = tc->pcState().itstate();
4734626SN/A    saved_cpsr.it2 = it.top6;
4744626SN/A    saved_cpsr.it1 = it.bottom2;
4758833Sdam.sunwoo@arm.com
4768833Sdam.sunwoo@arm.com    // if we have a valid instruction then use it to annotate this fault with
4778833Sdam.sunwoo@arm.com    // extra information. This is used to generate the correct fault syndrome
4784626SN/A    // information
4794626SN/A    if (inst) {
4804626SN/A        ArmStaticInst *armInst = reinterpret_cast<ArmStaticInst *>(inst.get());
4814626SN/A        armInst->annotateFault(this);
4824626SN/A    }
4838833Sdam.sunwoo@arm.com
4844626SN/A    if (have_security && routeToMonitor(tc))
4854871SN/A        cpsr.mode = MODE_MON;
4868833Sdam.sunwoo@arm.com    else if (have_virtualization && routeToHyp(tc))
4878833Sdam.sunwoo@arm.com        cpsr.mode = MODE_HYP;
4888833Sdam.sunwoo@arm.com    else
4894626SN/A        cpsr.mode = nextMode();
4904626SN/A
4914626SN/A    // Ensure Secure state if initially in Monitor mode
4924626SN/A    if (have_security && saved_cpsr.mode == MODE_MON) {
4938833Sdam.sunwoo@arm.com        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
4944626SN/A        if (scr.ns) {
4954871SN/A            scr.ns = 0;
4968833Sdam.sunwoo@arm.com            tc->setMiscRegNoEffect(MISCREG_SCR, scr);
4978833Sdam.sunwoo@arm.com        }
4988833Sdam.sunwoo@arm.com    }
4994626SN/A
5004626SN/A    // some bits are set differently if we have been routed to hyp mode
5014626SN/A    if (cpsr.mode == MODE_HYP) {
5024626SN/A        SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR);
5034626SN/A        cpsr.t = hsctlr.te;
5044626SN/A        cpsr.e = hsctlr.ee;
5054626SN/A        if (!scr.ea)  {cpsr.a = 1;}
5068833Sdam.sunwoo@arm.com        if (!scr.fiq) {cpsr.f = 1;}
5074626SN/A        if (!scr.irq) {cpsr.i = 1;}
5084626SN/A    } else if (cpsr.mode == MODE_MON) {
5094626SN/A        // Special case handling when entering monitor mode
5104626SN/A        cpsr.t = sctlr.te;
5118833Sdam.sunwoo@arm.com        cpsr.e = sctlr.ee;
5128833Sdam.sunwoo@arm.com        cpsr.a = 1;
5138833Sdam.sunwoo@arm.com        cpsr.f = 1;
5144626SN/A        cpsr.i = 1;
5154626SN/A    } else {
5164626SN/A        cpsr.t = sctlr.te;
5174626SN/A        cpsr.e = sctlr.ee;
5184626SN/A
5198833Sdam.sunwoo@arm.com        // The *Disable functions are virtual and different per fault
5204626SN/A        cpsr.a = cpsr.a | abortDisable(tc);
5214871SN/A        cpsr.f = cpsr.f | fiqDisable(tc);
5228833Sdam.sunwoo@arm.com        cpsr.i = 1;
5238833Sdam.sunwoo@arm.com    }
5248833Sdam.sunwoo@arm.com    cpsr.it1 = cpsr.it2 = 0;
5254626SN/A    cpsr.j = 0;
5264626SN/A    tc->setMiscReg(MISCREG_CPSR, cpsr);
5274626SN/A
5284626SN/A    // Make sure mailbox sets to one always
5298833Sdam.sunwoo@arm.com    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
5304626SN/A
5314871SN/A    // Clear the exclusive monitor
5328833Sdam.sunwoo@arm.com    tc->setMiscReg(MISCREG_LOCKFLAG, 0);
5338833Sdam.sunwoo@arm.com
5348833Sdam.sunwoo@arm.com    if (cpsr.mode == MODE_HYP) {
5354626SN/A        tc->setMiscReg(MISCREG_ELR_HYP, curPc +
5364626SN/A                (saved_cpsr.t ? thumbPcOffset(true)  : armPcOffset(true)));
5374626SN/A    } else {
5384626SN/A        tc->setIntReg(INTREG_LR, curPc +
5394626SN/A                (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false)));
5404626SN/A    }
5414626SN/A
5428833Sdam.sunwoo@arm.com    switch (cpsr.mode) {
5434626SN/A      case MODE_FIQ:
5444626SN/A        tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
5454626SN/A        break;
5464626SN/A      case MODE_IRQ:
5478833Sdam.sunwoo@arm.com        tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
5488833Sdam.sunwoo@arm.com        break;
5498833Sdam.sunwoo@arm.com      case MODE_SVC:
5504626SN/A        tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
5514626SN/A        break;
5524626SN/A      case MODE_MON:
5534626SN/A        assert(have_security);
5544626SN/A        tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr);
5558833Sdam.sunwoo@arm.com        break;
5564626SN/A      case MODE_ABORT:
5574871SN/A        tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
5588833Sdam.sunwoo@arm.com        break;
5598833Sdam.sunwoo@arm.com      case MODE_UNDEFINED:
5608833Sdam.sunwoo@arm.com        tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
5614626SN/A        if (ec(tc) != EC_UNKNOWN)
5624626SN/A            setSyndrome(tc, MISCREG_HSR);
5634626SN/A        break;
5644626SN/A      case MODE_HYP:
5658833Sdam.sunwoo@arm.com        assert(have_virtualization);
5664626SN/A        tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr);
5674871SN/A        setSyndrome(tc, MISCREG_HSR);
5684871SN/A        break;
5698833Sdam.sunwoo@arm.com      default:
5708833Sdam.sunwoo@arm.com        panic("unknown Mode\n");
5718833Sdam.sunwoo@arm.com    }
5724626SN/A
5734626SN/A    Addr newPc = getVector(tc);
5744626SN/A    DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n",
5754626SN/A            name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc);
5764626SN/A    PCState pc(newPc);
5774626SN/A    pc.thumb(cpsr.t);
5784626SN/A    pc.nextThumb(pc.thumb());
5798833Sdam.sunwoo@arm.com    pc.jazelle(cpsr.j);
5804626SN/A    pc.nextJazelle(pc.jazelle());
5814626SN/A    pc.aarch64(!cpsr.width);
5824626SN/A    pc.nextAArch64(!cpsr.width);
5834626SN/A    tc->pcState(pc);
5848833Sdam.sunwoo@arm.com}
5858833Sdam.sunwoo@arm.com
5868833Sdam.sunwoo@arm.comvoid
5874626SN/AArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
5884626SN/A{
5894626SN/A    // Determine actual misc. register indices for ELR_ELx and SPSR_ELx
5904626SN/A    MiscRegIndex elr_idx, spsr_idx;
5914626SN/A    switch (toEL) {
5928833Sdam.sunwoo@arm.com      case EL1:
5934626SN/A        elr_idx = MISCREG_ELR_EL1;
5944871SN/A        spsr_idx = MISCREG_SPSR_EL1;
5954871SN/A        break;
5968833Sdam.sunwoo@arm.com      case EL2:
5978833Sdam.sunwoo@arm.com        assert(ArmSystem::haveVirtualization(tc));
5988833Sdam.sunwoo@arm.com        elr_idx = MISCREG_ELR_EL2;
5994626SN/A        spsr_idx = MISCREG_SPSR_EL2;
6004626SN/A        break;
6014626SN/A      case EL3:
6024626SN/A        assert(ArmSystem::haveSecurity(tc));
6034626SN/A        elr_idx = MISCREG_ELR_EL3;
6044626SN/A        spsr_idx = MISCREG_SPSR_EL3;
6054626SN/A        break;
6068833Sdam.sunwoo@arm.com      default:
6074626SN/A        panic("Invalid target exception level");
6084626SN/A        break;
6094626SN/A    }
6104626SN/A
6118833Sdam.sunwoo@arm.com    // Save process state into SPSR_ELx
6128833Sdam.sunwoo@arm.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
6138833Sdam.sunwoo@arm.com    CPSR spsr = cpsr;
6144626SN/A    spsr.nz = tc->readCCReg(CCREG_NZ);
6154626SN/A    spsr.c = tc->readCCReg(CCREG_C);
6164626SN/A    spsr.v = tc->readCCReg(CCREG_V);
6174626SN/A    if (from64) {
6184626SN/A        // Force some bitfields to 0
6198833Sdam.sunwoo@arm.com        spsr.q = 0;
6204626SN/A        spsr.it1 = 0;
6214871SN/A        spsr.j = 0;
6224871SN/A        spsr.res0_23_22 = 0;
6234871SN/A        spsr.ge = 0;
6248833Sdam.sunwoo@arm.com        spsr.it2 = 0;
6258833Sdam.sunwoo@arm.com        spsr.t = 0;
6268833Sdam.sunwoo@arm.com    } else {
6274626SN/A        spsr.ge = tc->readCCReg(CCREG_GE);
6284626SN/A        ITSTATE it = tc->pcState().itstate();
6294626SN/A        spsr.it2 = it.top6;
6304626SN/A        spsr.it1 = it.bottom2;
6314626SN/A        // Force some bitfields to 0
6324626SN/A        spsr.res0_23_22 = 0;
6334626SN/A        spsr.ss = 0;
6344626SN/A    }
6354626SN/A    tc->setMiscReg(spsr_idx, spsr);
6364626SN/A
6374626SN/A    // Save preferred return address into ELR_ELx
6384626SN/A    Addr curr_pc = tc->pcState().pc();
6394626SN/A    Addr ret_addr = curr_pc;
6404626SN/A    if (from64)
6414626SN/A        ret_addr += armPcElrOffset();
6424626SN/A    else
6434626SN/A        ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset();
6444626SN/A    tc->setMiscReg(elr_idx, ret_addr);
6454626SN/A
6464626SN/A    // Update process state
6474626SN/A    OperatingMode64 mode = 0;
6484626SN/A    mode.spX = 1;
6494626SN/A    mode.el = toEL;
6504626SN/A    mode.width = 0;
6514626SN/A    cpsr.mode = mode;
6524626SN/A    cpsr.daif = 0xf;
6534626SN/A    cpsr.il = 0;
6544626SN/A    cpsr.ss = 0;
6554626SN/A    tc->setMiscReg(MISCREG_CPSR, cpsr);
6564626SN/A
6574626SN/A    // Set PC to start of exception handler
6584626SN/A    Addr new_pc = purifyTaggedAddr(getVector64(tc), tc, toEL);
6594626SN/A    DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x "
6604626SN/A            "elr:%#x newVec: %#x\n", name(), cpsr, curr_pc, ret_addr, new_pc);
6614626SN/A    PCState pc(new_pc);
6624626SN/A    pc.aarch64(!cpsr.width);
6634626SN/A    pc.nextAArch64(!cpsr.width);
6644626SN/A    tc->pcState(pc);
6654626SN/A
6664626SN/A    // If we have a valid instruction then use it to annotate this fault with
6674626SN/A    // extra information. This is used to generate the correct fault syndrome
6684626SN/A    // information
6694626SN/A    if (inst)
6704626SN/A        reinterpret_cast<ArmStaticInst *>(inst.get())->annotateFault(this);
6714626SN/A    // Save exception syndrome
6728833Sdam.sunwoo@arm.com    if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ))
6738833Sdam.sunwoo@arm.com        setSyndrome(tc, getSyndromeReg64());
6748833Sdam.sunwoo@arm.com}
6758833Sdam.sunwoo@arm.com
6764626SN/Avoid
6774626SN/AReset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
6784626SN/A{
6794626SN/A    if (FullSystem) {
6804626SN/A        tc->getCpuPtr()->clearInterrupts(tc->threadId());
6818833Sdam.sunwoo@arm.com        tc->clearArchRegs();
6824626SN/A    }
6834626SN/A    if (!ArmSystem::highestELIs64(tc)) {
6848833Sdam.sunwoo@arm.com        ArmFault::invoke(tc, inst);
6858833Sdam.sunwoo@arm.com        tc->setMiscReg(MISCREG_VMPIDR,
6868833Sdam.sunwoo@arm.com                       getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc));
6874626SN/A
6884626SN/A        // Unless we have SMC code to get us there, boot in HYP!
6894626SN/A        if (ArmSystem::haveVirtualization(tc) &&
6904626SN/A            !ArmSystem::haveSecurity(tc)) {
6918833Sdam.sunwoo@arm.com            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
6924626SN/A            cpsr.mode = MODE_HYP;
6934626SN/A            tc->setMiscReg(MISCREG_CPSR, cpsr);
6948833Sdam.sunwoo@arm.com        }
6958833Sdam.sunwoo@arm.com    } else {
6968833Sdam.sunwoo@arm.com        // Advance the PC to the IMPLEMENTATION DEFINED reset value
6974626SN/A        PCState pc = ArmSystem::resetAddr64(tc);
6984626SN/A        pc.aarch64(true);
6994626SN/A        pc.nextAArch64(true);
7004626SN/A        tc->pcState(pc);
7014626SN/A    }
7024626SN/A}
7034626SN/A
7044626SN/Avoid
7054626SN/AUndefinedInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
7064626SN/A{
7074626SN/A    if (FullSystem) {
7084626SN/A        ArmFault::invoke(tc, inst);
7094626SN/A        return;
7108833Sdam.sunwoo@arm.com    }
7118833Sdam.sunwoo@arm.com
7128833Sdam.sunwoo@arm.com    // If the mnemonic isn't defined this has to be an unknown instruction.
7138833Sdam.sunwoo@arm.com    assert(unknown || mnemonic != NULL);
7144626SN/A    if (disabled) {
7154626SN/A        panic("Attempted to execute disabled instruction "
7164626SN/A                "'%s' (inst 0x%08x)", mnemonic, machInst);
7174626SN/A    } else if (unknown) {
7184626SN/A        panic("Attempted to execute unknown instruction (inst 0x%08x)",
7198833Sdam.sunwoo@arm.com              machInst);
7204626SN/A    } else {
7214626SN/A        panic("Attempted to execute unimplemented instruction "
7228833Sdam.sunwoo@arm.com                "'%s' (inst 0x%08x)", mnemonic, machInst);
7238833Sdam.sunwoo@arm.com    }
7248833Sdam.sunwoo@arm.com}
7254626SN/A
7264626SN/Abool
7274626SN/AUndefinedInstruction::routeToHyp(ThreadContext *tc) const
7284626SN/A{
7298833Sdam.sunwoo@arm.com    bool toHyp;
7304626SN/A
7314626SN/A    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
7328833Sdam.sunwoo@arm.com    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
7338833Sdam.sunwoo@arm.com    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
7348833Sdam.sunwoo@arm.com
7354626SN/A    // if in Hyp mode then stay in Hyp mode
7364626SN/A    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
7374626SN/A    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
7384626SN/A    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
7394626SN/A    return toHyp;
7404626SN/A}
7414626SN/A
7424626SN/Auint32_t
7434626SN/AUndefinedInstruction::iss() const
7444626SN/A{
7454626SN/A    if (overrideEc == EC_INVALID)
7464626SN/A        return issRaw;
7474626SN/A
7488833Sdam.sunwoo@arm.com    uint32_t new_iss = 0;
7498833Sdam.sunwoo@arm.com    uint32_t op0, op1, op2, CRn, CRm, Rt, dir;
7508833Sdam.sunwoo@arm.com
7518833Sdam.sunwoo@arm.com    dir = bits(machInst, 21, 21);
7524626SN/A    op0 = bits(machInst, 20, 19);
7534626SN/A    op1 = bits(machInst, 18, 16);
7544626SN/A    CRn = bits(machInst, 15, 12);
7554626SN/A    CRm = bits(machInst, 11, 8);
7564626SN/A    op2 = bits(machInst, 7, 5);
7578833Sdam.sunwoo@arm.com    Rt = bits(machInst, 4, 0);
7584626SN/A
7594626SN/A    new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 |
7608833Sdam.sunwoo@arm.com            Rt << 5 | CRm << 1 | dir;
7618833Sdam.sunwoo@arm.com
7628833Sdam.sunwoo@arm.com    return new_iss;
7634626SN/A}
7644626SN/A
7658833Sdam.sunwoo@arm.comvoid
7664626SN/ASupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
7674626SN/A{
7688833Sdam.sunwoo@arm.com    if (FullSystem) {
7694626SN/A        ArmFault::invoke(tc, inst);
7708833Sdam.sunwoo@arm.com        return;
7718833Sdam.sunwoo@arm.com    }
7728833Sdam.sunwoo@arm.com
7734626SN/A    // As of now, there isn't a 32 bit thumb version of this instruction.
7744626SN/A    assert(!machInst.bigThumb);
7754626SN/A    uint32_t callNum;
7768833Sdam.sunwoo@arm.com    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
7774626SN/A    OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
7784626SN/A    if (opModeIs64(mode))
7798833Sdam.sunwoo@arm.com        callNum = tc->readIntReg(INTREG_X8);
7804626SN/A    else
7818833Sdam.sunwoo@arm.com        callNum = tc->readIntReg(INTREG_R7);
7828833Sdam.sunwoo@arm.com    Fault fault;
7838833Sdam.sunwoo@arm.com    tc->syscall(callNum, &fault);
7844626SN/A
7854626SN/A    // Advance the PC since that won't happen automatically.
7864626SN/A    PCState pc = tc->pcState();
7874626SN/A    assert(inst);
7884626SN/A    inst->advancePC(pc);
7894626SN/A    tc->pcState(pc);
7902810SN/A}
791
792bool
793SupervisorCall::routeToHyp(ThreadContext *tc) const
794{
795    bool toHyp;
796
797    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
798    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
799    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
800
801    // if in Hyp mode then stay in Hyp mode
802    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
803    // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
804    toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER);
805    return toHyp;
806}
807
808ExceptionClass
809SupervisorCall::ec(ThreadContext *tc) const
810{
811    return (overrideEc != EC_INVALID) ? overrideEc :
812        (from64 ? EC_SVC_64 : vals.ec);
813}
814
815uint32_t
816SupervisorCall::iss() const
817{
818    // Even if we have a 24 bit imm from an arm32 instruction then we only use
819    // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC).
820    return issRaw & 0xFFFF;
821}
822
823uint32_t
824SecureMonitorCall::iss() const
825{
826    if (from64)
827        return bits(machInst, 20, 5);
828    return 0;
829}
830
831ExceptionClass
832UndefinedInstruction::ec(ThreadContext *tc) const
833{
834    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
835}
836
837
838HypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) :
839        ArmFaultVals<HypervisorCall>(_machInst, _imm)
840{}
841
842ExceptionClass
843HypervisorCall::ec(ThreadContext *tc) const
844{
845    return from64 ? EC_HVC_64 : vals.ec;
846}
847
848ExceptionClass
849HypervisorTrap::ec(ThreadContext *tc) const
850{
851    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
852}
853
854template<class T>
855FaultOffset
856ArmFaultVals<T>::offset(ThreadContext *tc)
857{
858    bool isHypTrap = false;
859
860    // Normally we just use the exception vector from the table at the top if
861    // this file, however if this exception has caused a transition to hype
862    // mode, and its an exception type that would only do this if it has been
863    // trapped then we use the hyp trap vector instead of the normal vector
864    if (vals.hypTrappable) {
865        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
866        if (cpsr.mode == MODE_HYP) {
867            CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
868            isHypTrap = spsr.mode != MODE_HYP;
869        }
870    }
871    return isHypTrap ? 0x14 : vals.offset;
872}
873
874// void
875// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx)
876// {
877//     ESR esr = 0;
878//     esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32;
879//     esr.il = !machInst.thumb;
880//     if (machInst.aarch64)
881//         esr.imm16 = bits(machInst.instBits, 20, 5);
882//     else if (machInst.thumb)
883//         esr.imm16 = bits(machInst.instBits, 7, 0);
884//     else
885//         esr.imm16 = bits(machInst.instBits, 15, 0);
886//     tc->setMiscReg(esr_idx, esr);
887// }
888
889void
890SecureMonitorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst)
891{
892    if (FullSystem) {
893        ArmFault::invoke(tc, inst);
894        return;
895    }
896}
897
898ExceptionClass
899SecureMonitorCall::ec(ThreadContext *tc) const
900{
901    return (from64 ? EC_SMC_64 : vals.ec);
902}
903
904ExceptionClass
905SupervisorTrap::ec(ThreadContext *tc) const
906{
907    return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
908}
909
910ExceptionClass
911SecureMonitorTrap::ec(ThreadContext *tc) const
912{
913    return (overrideEc != EC_INVALID) ? overrideEc :
914        (from64 ? EC_SMC_64 : vals.ec);
915}
916
917template<class T>
918void
919AbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
920{
921    if (tranMethod == ArmFault::UnknownTran) {
922        tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran
923                                             : ArmFault::VmsaTran;
924
925        if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) {
926            // See ARM ARM B3-1416
927            bool override_LPAE = false;
928            TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S);
929            TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS);
930            if (ttbcr_s.eae) {
931                override_LPAE = true;
932            } else {
933                // Unimplemented code option, not seen in testing.  May need
934                // extension according to the manual exceprt above.
935                DPRINTF(Faults, "Warning: Incomplete translation method "
936                        "override detected.\n");
937            }
938            if (override_LPAE)
939                tranMethod = ArmFault::LpaeTran;
940        }
941    }
942
943    if (source == ArmFault::AsynchronousExternalAbort) {
944        tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
945    }
946    // Get effective fault source encoding
947    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
948    FSR  fsr  = getFsr(tc);
949
950    // source must be determined BEFORE invoking generic routines which will
951    // try to set hsr etc. and are based upon source!
952    ArmFaultVals<T>::invoke(tc, inst);
953
954    if (!this->to64) {  // AArch32
955        if (cpsr.mode == MODE_HYP) {
956            tc->setMiscReg(T::HFarIndex, faultAddr);
957        } else if (stage2) {
958            tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf);
959            tc->setMiscReg(T::HFarIndex,  OVAddr);
960        } else {
961            tc->setMiscReg(T::FsrIndex, fsr);
962            tc->setMiscReg(T::FarIndex, faultAddr);
963        }
964        DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\
965                "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod);
966    } else {  // AArch64
967        // Set the FAR register.  Nothing else to do if we are in AArch64 state
968        // because the syndrome register has already been set inside invoke64()
969        if (stage2) {
970            // stage 2 fault, set HPFAR_EL2 to the faulting IPA
971            // and FAR_EL2 to the Original VA
972            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr);
973            tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
974
975            DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
976                    OVAddr, faultAddr);
977        } else {
978            tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
979        }
980    }
981}
982
983template<class T>
984FSR
985AbortFault<T>::getFsr(ThreadContext *tc)
986{
987    FSR fsr = 0;
988
989    if (((CPSR) tc->readMiscRegNoEffect(MISCREG_CPSR)).width) {
990        // AArch32
991        assert(tranMethod != ArmFault::UnknownTran);
992        if (tranMethod == ArmFault::LpaeTran) {
993            srcEncoded = ArmFault::longDescFaultSources[source];
994            fsr.status = srcEncoded;
995            fsr.lpae   = 1;
996        } else {
997            srcEncoded = ArmFault::shortDescFaultSources[source];
998            fsr.fsLow  = bits(srcEncoded, 3, 0);
999            fsr.fsHigh = bits(srcEncoded, 4);
1000            fsr.domain = static_cast<uint8_t>(domain);
1001        }
1002        fsr.wnr = (write ? 1 : 0);
1003        fsr.ext = 0;
1004    } else {
1005        // AArch64
1006        srcEncoded = ArmFault::aarch64FaultSources[source];
1007    }
1008    if (srcEncoded == ArmFault::FaultSourceInvalid) {
1009        panic("Invalid fault source\n");
1010    }
1011    return fsr;
1012}
1013
1014template<class T>
1015bool
1016AbortFault<T>::abortDisable(ThreadContext *tc)
1017{
1018    if (ArmSystem::haveSecurity(tc)) {
1019        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1020        return (!scr.ns || scr.aw);
1021    }
1022    return true;
1023}
1024
1025template<class T>
1026void
1027AbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val)
1028{
1029    switch (id)
1030    {
1031      case ArmFault::S1PTW:
1032        s1ptw = val;
1033        break;
1034      case ArmFault::OVA:
1035        OVAddr = val;
1036        break;
1037
1038      // Just ignore unknown ID's
1039      default:
1040        break;
1041    }
1042}
1043
1044template<class T>
1045uint32_t
1046AbortFault<T>::iss() const
1047{
1048    uint32_t val;
1049
1050    val  = srcEncoded & 0x3F;
1051    val |= write << 6;
1052    val |= s1ptw << 7;
1053    return (val);
1054}
1055
1056template<class T>
1057bool
1058AbortFault<T>::isMMUFault() const
1059{
1060    // NOTE: Not relying on LL information being aligned to lowest bits here
1061    return
1062         (source == ArmFault::AlignmentFault)     ||
1063        ((source >= ArmFault::TranslationLL) &&
1064         (source <  ArmFault::TranslationLL + 4)) ||
1065        ((source >= ArmFault::AccessFlagLL) &&
1066         (source <  ArmFault::AccessFlagLL + 4))  ||
1067        ((source >= ArmFault::DomainLL) &&
1068         (source <  ArmFault::DomainLL + 4))      ||
1069        ((source >= ArmFault::PermissionLL) &&
1070         (source <  ArmFault::PermissionLL + 4));
1071}
1072
1073ExceptionClass
1074PrefetchAbort::ec(ThreadContext *tc) const
1075{
1076    if (to64) {
1077        // AArch64
1078        if (toEL == fromEL)
1079            return EC_PREFETCH_ABORT_CURR_EL;
1080        else
1081            return EC_PREFETCH_ABORT_LOWER_EL;
1082    } else {
1083        // AArch32
1084        // Abort faults have different EC codes depending on whether
1085        // the fault originated within HYP mode, or not. So override
1086        // the method and add the extra adjustment of the EC value.
1087
1088        ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec;
1089
1090        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
1091        if (spsr.mode == MODE_HYP) {
1092            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
1093        }
1094        return ec;
1095    }
1096}
1097
1098bool
1099PrefetchAbort::routeToMonitor(ThreadContext *tc) const
1100{
1101    SCR scr = 0;
1102    if (from64)
1103        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1104    else
1105        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1106
1107    return scr.ea && !isMMUFault();
1108}
1109
1110bool
1111PrefetchAbort::routeToHyp(ThreadContext *tc) const
1112{
1113    bool toHyp;
1114
1115    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1116    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1117    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1118    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
1119
1120    // if in Hyp mode then stay in Hyp mode
1121    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
1122    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
1123    toHyp |= (stage2 ||
1124                ( (source ==               DebugEvent) && hdcr.tde && (cpsr.mode !=  MODE_HYP)) ||
1125                ( (source == SynchronousExternalAbort) && hcr.tge  && (cpsr.mode == MODE_USER))
1126             ) && !inSecureState(tc);
1127    return toHyp;
1128}
1129
1130ExceptionClass
1131DataAbort::ec(ThreadContext *tc) const
1132{
1133    if (to64) {
1134        // AArch64
1135        if (source == ArmFault::AsynchronousExternalAbort) {
1136            panic("Asynchronous External Abort should be handled with "
1137                    "SystemErrors (SErrors)!");
1138        }
1139        if (toEL == fromEL)
1140            return EC_DATA_ABORT_CURR_EL;
1141        else
1142            return EC_DATA_ABORT_LOWER_EL;
1143    } else {
1144        // AArch32
1145        // Abort faults have different EC codes depending on whether
1146        // the fault originated within HYP mode, or not. So override
1147        // the method and add the extra adjustment of the EC value.
1148
1149        ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec;
1150
1151        CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
1152        if (spsr.mode == MODE_HYP) {
1153            ec = ((ExceptionClass) (((uint32_t) ec) + 1));
1154        }
1155        return ec;
1156    }
1157}
1158
1159bool
1160DataAbort::routeToMonitor(ThreadContext *tc) const
1161{
1162    SCR scr = 0;
1163    if (from64)
1164        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1165    else
1166        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1167
1168    return scr.ea && !isMMUFault();
1169}
1170
1171bool
1172DataAbort::routeToHyp(ThreadContext *tc) const
1173{
1174    bool toHyp;
1175
1176    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1177    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1178    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1179    HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
1180
1181    // if in Hyp mode then stay in Hyp mode
1182    toHyp  = scr.ns && (cpsr.mode == MODE_HYP);
1183    // otherwise, check whether to take to Hyp mode through Hyp Trap vector
1184    toHyp |= (stage2 ||
1185                ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) ||
1186                                               ((source == DebugEvent) && hdcr.tde) )
1187                ) ||
1188                ( (cpsr.mode == MODE_USER) && hcr.tge &&
1189                  ((source == AlignmentFault)            ||
1190                   (source == SynchronousExternalAbort))
1191                )
1192             ) && !inSecureState(tc);
1193    return toHyp;
1194}
1195
1196uint32_t
1197DataAbort::iss() const
1198{
1199    uint32_t val;
1200
1201    // Add on the data abort specific fields to the generic abort ISS value
1202    val  = AbortFault<DataAbort>::iss();
1203    // ISS is valid if not caused by a stage 1 page table walk, and when taken
1204    // to AArch64 only when directed to EL2
1205    if (!s1ptw && (!to64 || toEL == EL2)) {
1206        val |= isv << 24;
1207        if (isv) {
1208            val |= sas << 22;
1209            val |= sse << 21;
1210            val |= srt << 16;
1211            // AArch64 only. These assignments are safe on AArch32 as well
1212            // because these vars are initialized to false
1213            val |= sf << 15;
1214            val |= ar << 14;
1215        }
1216    }
1217    return (val);
1218}
1219
1220void
1221DataAbort::annotate(AnnotationIDs id, uint64_t val)
1222{
1223    AbortFault<DataAbort>::annotate(id, val);
1224    switch (id)
1225    {
1226      case SAS:
1227        isv = true;
1228        sas = val;
1229        break;
1230      case SSE:
1231        isv = true;
1232        sse = val;
1233        break;
1234      case SRT:
1235        isv = true;
1236        srt = val;
1237        break;
1238      case SF:
1239        isv = true;
1240        sf  = val;
1241        break;
1242      case AR:
1243        isv = true;
1244        ar  = val;
1245        break;
1246      // Just ignore unknown ID's
1247      default:
1248        break;
1249    }
1250}
1251
1252void
1253VirtualDataAbort::invoke(ThreadContext *tc, const StaticInstPtr &inst)
1254{
1255    AbortFault<VirtualDataAbort>::invoke(tc, inst);
1256    HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
1257    hcr.va = 0;
1258    tc->setMiscRegNoEffect(MISCREG_HCR, hcr);
1259}
1260
1261bool
1262Interrupt::routeToMonitor(ThreadContext *tc) const
1263{
1264    assert(ArmSystem::haveSecurity(tc));
1265    SCR scr = 0;
1266    if (from64)
1267        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1268    else
1269        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1270    return scr.irq;
1271}
1272
1273bool
1274Interrupt::routeToHyp(ThreadContext *tc) const
1275{
1276    bool toHyp;
1277
1278    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1279    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1280    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1281    // Determine whether IRQs are routed to Hyp mode.
1282    toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) ||
1283            (cpsr.mode == MODE_HYP);
1284    return toHyp;
1285}
1286
1287bool
1288Interrupt::abortDisable(ThreadContext *tc)
1289{
1290    if (ArmSystem::haveSecurity(tc)) {
1291        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1292        return (!scr.ns || scr.aw);
1293    }
1294    return true;
1295}
1296
1297VirtualInterrupt::VirtualInterrupt()
1298{}
1299
1300bool
1301FastInterrupt::routeToMonitor(ThreadContext *tc) const
1302{
1303    assert(ArmSystem::haveSecurity(tc));
1304    SCR scr = 0;
1305    if (from64)
1306        scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1307    else
1308        scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1309    return scr.fiq;
1310}
1311
1312bool
1313FastInterrupt::routeToHyp(ThreadContext *tc) const
1314{
1315    bool toHyp;
1316
1317    SCR  scr  = tc->readMiscRegNoEffect(MISCREG_SCR);
1318    HCR  hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1319    CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1320    // Determine whether IRQs are routed to Hyp mode.
1321    toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) ||
1322            (cpsr.mode == MODE_HYP);
1323    return toHyp;
1324}
1325
1326bool
1327FastInterrupt::abortDisable(ThreadContext *tc)
1328{
1329    if (ArmSystem::haveSecurity(tc)) {
1330        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1331        return (!scr.ns || scr.aw);
1332    }
1333    return true;
1334}
1335
1336bool
1337FastInterrupt::fiqDisable(ThreadContext *tc)
1338{
1339    if (ArmSystem::haveVirtualization(tc)) {
1340        return true;
1341    } else if (ArmSystem::haveSecurity(tc)) {
1342        SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1343        return (!scr.ns || scr.fw);
1344    }
1345    return true;
1346}
1347
1348VirtualFastInterrupt::VirtualFastInterrupt()
1349{}
1350
1351void
1352PCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
1353{
1354    ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
1355    assert(from64);
1356    // Set the FAR
1357    tc->setMiscReg(getFaultAddrReg64(), faultPC);
1358}
1359
1360SPAlignmentFault::SPAlignmentFault()
1361{}
1362
1363SystemError::SystemError()
1364{}
1365
1366void
1367SystemError::invoke(ThreadContext *tc, const StaticInstPtr &inst)
1368{
1369    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
1370    ArmFault::invoke(tc, inst);
1371}
1372
1373bool
1374SystemError::routeToMonitor(ThreadContext *tc) const
1375{
1376    assert(ArmSystem::haveSecurity(tc));
1377    assert(from64);
1378    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1379    return scr.ea;
1380}
1381
1382bool
1383SystemError::routeToHyp(ThreadContext *tc) const
1384{
1385    bool toHyp;
1386    assert(from64);
1387
1388    SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1389    HCR hcr  = tc->readMiscRegNoEffect(MISCREG_HCR);
1390
1391    toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) ||
1392            (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc));
1393    return toHyp;
1394}
1395
1396void
1397ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
1398    DPRINTF(Faults, "Invoking ArmSev Fault\n");
1399    if (!FullSystem)
1400        return;
1401
1402    // Set sev_mailbox to 1, clear the pending interrupt from remote
1403    // SEV execution and let pipeline continue as pcState is still
1404    // valid.
1405    tc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
1406    tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0);
1407}
1408
1409// Instantiate all the templates to make the linker happy
1410template class ArmFaultVals<Reset>;
1411template class ArmFaultVals<UndefinedInstruction>;
1412template class ArmFaultVals<SupervisorCall>;
1413template class ArmFaultVals<SecureMonitorCall>;
1414template class ArmFaultVals<HypervisorCall>;
1415template class ArmFaultVals<PrefetchAbort>;
1416template class ArmFaultVals<DataAbort>;
1417template class ArmFaultVals<VirtualDataAbort>;
1418template class ArmFaultVals<HypervisorTrap>;
1419template class ArmFaultVals<Interrupt>;
1420template class ArmFaultVals<VirtualInterrupt>;
1421template class ArmFaultVals<FastInterrupt>;
1422template class ArmFaultVals<VirtualFastInterrupt>;
1423template class ArmFaultVals<SupervisorTrap>;
1424template class ArmFaultVals<SecureMonitorTrap>;
1425template class ArmFaultVals<PCAlignmentFault>;
1426template class ArmFaultVals<SPAlignmentFault>;
1427template class ArmFaultVals<SystemError>;
1428template class ArmFaultVals<ArmSev>;
1429template class AbortFault<PrefetchAbort>;
1430template class AbortFault<DataAbort>;
1431template class AbortFault<VirtualDataAbort>;
1432
1433
1434IllegalInstSetStateFault::IllegalInstSetStateFault()
1435{}
1436
1437
1438} // namespace ArmISA
1439