faults.cc revision 10367
12221SN/A/* 22221SN/A * Copyright (c) 2010, 2012-2014 ARM Limited 32221SN/A * All rights reserved 42221SN/A * 52221SN/A * The license below extends only to copyright in the software and shall 62221SN/A * not be construed as granting a license to any other intellectual 72221SN/A * property including but not limited to intellectual property relating 82221SN/A * to a hardware implementation of the functionality of the software 92221SN/A * licensed hereunder. You may use the software subject to the license 102221SN/A * terms below provided that you ensure that this notice is replicated 112221SN/A * unmodified and in its entirety in all distributions of the software, 122221SN/A * modified or unmodified, in source code or in binary form. 132221SN/A * 142221SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 152221SN/A * Copyright (c) 2007-2008 The Florida State University 162221SN/A * All rights reserved. 172221SN/A * 182221SN/A * Redistribution and use in source and binary forms, with or without 192221SN/A * modification, are permitted provided that the following conditions are 202221SN/A * met: redistributions of source code must retain the above copyright 212221SN/A * notice, this list of conditions and the following disclaimer; 222221SN/A * redistributions in binary form must reproduce the above copyright 232221SN/A * notice, this list of conditions and the following disclaimer in the 242221SN/A * documentation and/or other materials provided with the distribution; 252221SN/A * neither the name of the copyright holders nor the names of its 262221SN/A * contributors may be used to endorse or promote products derived from 272665Ssaidi@eecs.umich.edu * this software without specific prior written permission. 282665Ssaidi@eecs.umich.edu * 292665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302221SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 312221SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 323415Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 333415Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 342223SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 353415Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 368778Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 373578Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 383415Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 393415Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 408750Sgblack@eecs.umich.edu * 413415Sgblack@eecs.umich.edu * Authors: Ali Saidi 422680Sktlim@umich.edu * Gabe Black 433415Sgblack@eecs.umich.edu * Giacomo Gabrielli 442800Ssaidi@eecs.umich.edu * Thomas Grocutt 458750Sgblack@eecs.umich.edu */ 462221SN/A 473415Sgblack@eecs.umich.edu#include "arch/arm/faults.hh" 483415Sgblack@eecs.umich.edu#include "arch/arm/system.hh" 492223SN/A#include "arch/arm/utility.hh" 502221SN/A#include "arch/arm/insts/static_inst.hh" 512221SN/A#include "base/compiler.hh" 523573Sgblack@eecs.umich.edu#include "base/trace.hh" 533576Sgblack@eecs.umich.edu#include "cpu/base.hh" 543576Sgblack@eecs.umich.edu#include "cpu/thread_context.hh" 552221SN/A#include "debug/Faults.hh" 563573Sgblack@eecs.umich.edu#include "sim/full_system.hh" 573576Sgblack@eecs.umich.edu 583576Sgblack@eecs.umich.edunamespace ArmISA 592221SN/A{ 603573Sgblack@eecs.umich.edu 613576Sgblack@eecs.umich.eduuint8_t ArmFault::shortDescFaultSources[] = { 623576Sgblack@eecs.umich.edu 0x01, // AlignmentFault 632221SN/A 0x04, // InstructionCacheMaintenance 643573Sgblack@eecs.umich.edu 0xff, // SynchExtAbtOnTranslTableWalkL0 (INVALID) 653576Sgblack@eecs.umich.edu 0x0c, // SynchExtAbtOnTranslTableWalkL1 663576Sgblack@eecs.umich.edu 0x0e, // SynchExtAbtOnTranslTableWalkL2 672221SN/A 0xff, // SynchExtAbtOnTranslTableWalkL3 (INVALID) 683573Sgblack@eecs.umich.edu 0xff, // SynchPtyErrOnTranslTableWalkL0 (INVALID) 693576Sgblack@eecs.umich.edu 0x1c, // SynchPtyErrOnTranslTableWalkL1 703576Sgblack@eecs.umich.edu 0x1e, // SynchPtyErrOnTranslTableWalkL2 712221SN/A 0xff, // SynchPtyErrOnTranslTableWalkL3 (INVALID) 723573Sgblack@eecs.umich.edu 0xff, // TranslationL0 (INVALID) 733576Sgblack@eecs.umich.edu 0x05, // TranslationL1 743576Sgblack@eecs.umich.edu 0x07, // TranslationL2 752221SN/A 0xff, // TranslationL3 (INVALID) 763573Sgblack@eecs.umich.edu 0xff, // AccessFlagL0 (INVALID) 773576Sgblack@eecs.umich.edu 0x03, // AccessFlagL1 783576Sgblack@eecs.umich.edu 0x06, // AccessFlagL2 793576Sgblack@eecs.umich.edu 0xff, // AccessFlagL3 (INVALID) 803576Sgblack@eecs.umich.edu 0xff, // DomainL0 (INVALID) 813576Sgblack@eecs.umich.edu 0x09, // DomainL1 823576Sgblack@eecs.umich.edu 0x0b, // DomainL2 833576Sgblack@eecs.umich.edu 0xff, // DomainL3 (INVALID) 842221SN/A 0xff, // PermissionL0 (INVALID) 853573Sgblack@eecs.umich.edu 0x0d, // PermissionL1 863576Sgblack@eecs.umich.edu 0x0f, // PermissionL2 873576Sgblack@eecs.umich.edu 0xff, // PermissionL3 (INVALID) 882221SN/A 0x02, // DebugEvent 893573Sgblack@eecs.umich.edu 0x08, // SynchronousExternalAbort 903576Sgblack@eecs.umich.edu 0x10, // TLBConflictAbort 913576Sgblack@eecs.umich.edu 0x19, // SynchPtyErrOnMemoryAccess 922221SN/A 0x16, // AsynchronousExternalAbort 933573Sgblack@eecs.umich.edu 0x18, // AsynchPtyErrOnMemoryAccess 943576Sgblack@eecs.umich.edu 0xff, // AddressSizeL0 (INVALID) 953576Sgblack@eecs.umich.edu 0xff, // AddressSizeL1 (INVALID) 963576Sgblack@eecs.umich.edu 0xff, // AddressSizeL2 (INVALID) 973576Sgblack@eecs.umich.edu 0xff, // AddressSizeL3 (INVALID) 983576Sgblack@eecs.umich.edu 0x40, // PrefetchTLBMiss 993576Sgblack@eecs.umich.edu 0x80 // PrefetchUncacheable 1003576Sgblack@eecs.umich.edu}; 1013576Sgblack@eecs.umich.edu 1023576Sgblack@eecs.umich.edustatic_assert(sizeof(ArmFault::shortDescFaultSources) == 1033576Sgblack@eecs.umich.edu ArmFault::NumFaultSources, 1043576Sgblack@eecs.umich.edu "Invalid size of ArmFault::shortDescFaultSources[]"); 1053576Sgblack@eecs.umich.edu 1062221SN/Auint8_t ArmFault::longDescFaultSources[] = { 1073573Sgblack@eecs.umich.edu 0x21, // AlignmentFault 1083576Sgblack@eecs.umich.edu 0xff, // InstructionCacheMaintenance (INVALID) 1093576Sgblack@eecs.umich.edu 0xff, // SynchExtAbtOnTranslTableWalkL0 (INVALID) 1102221SN/A 0x15, // SynchExtAbtOnTranslTableWalkL1 1113573Sgblack@eecs.umich.edu 0x16, // SynchExtAbtOnTranslTableWalkL2 1123576Sgblack@eecs.umich.edu 0x17, // SynchExtAbtOnTranslTableWalkL3 1133576Sgblack@eecs.umich.edu 0xff, // SynchPtyErrOnTranslTableWalkL0 (INVALID) 1142221SN/A 0x1d, // SynchPtyErrOnTranslTableWalkL1 1153573Sgblack@eecs.umich.edu 0x1e, // SynchPtyErrOnTranslTableWalkL2 1163576Sgblack@eecs.umich.edu 0x1f, // SynchPtyErrOnTranslTableWalkL3 1173576Sgblack@eecs.umich.edu 0xff, // TranslationL0 (INVALID) 1182221SN/A 0x05, // TranslationL1 1193573Sgblack@eecs.umich.edu 0x06, // TranslationL2 1203576Sgblack@eecs.umich.edu 0x07, // TranslationL3 1213576Sgblack@eecs.umich.edu 0xff, // AccessFlagL0 (INVALID) 1222221SN/A 0x09, // AccessFlagL1 1233573Sgblack@eecs.umich.edu 0x0a, // AccessFlagL2 1243576Sgblack@eecs.umich.edu 0x0b, // AccessFlagL3 1253576Sgblack@eecs.umich.edu 0xff, // DomainL0 (INVALID) 1262221SN/A 0x3d, // DomainL1 1273573Sgblack@eecs.umich.edu 0x3e, // DomainL2 1283576Sgblack@eecs.umich.edu 0xff, // DomainL3 (RESERVED) 1293576Sgblack@eecs.umich.edu 0xff, // PermissionL0 (INVALID) 1302223SN/A 0x0d, // PermissionL1 1313573Sgblack@eecs.umich.edu 0x0e, // PermissionL2 1323576Sgblack@eecs.umich.edu 0x0f, // PermissionL3 1333576Sgblack@eecs.umich.edu 0x22, // DebugEvent 1342223SN/A 0x10, // SynchronousExternalAbort 1353573Sgblack@eecs.umich.edu 0x30, // TLBConflictAbort 1363576Sgblack@eecs.umich.edu 0x18, // SynchPtyErrOnMemoryAccess 1373576Sgblack@eecs.umich.edu 0x11, // AsynchronousExternalAbort 1382223SN/A 0x19, // AsynchPtyErrOnMemoryAccess 1393573Sgblack@eecs.umich.edu 0xff, // AddressSizeL0 (INVALID) 1403576Sgblack@eecs.umich.edu 0xff, // AddressSizeL1 (INVALID) 1413576Sgblack@eecs.umich.edu 0xff, // AddressSizeL2 (INVALID) 1422223SN/A 0xff, // AddressSizeL3 (INVALID) 1433573Sgblack@eecs.umich.edu 0x40, // PrefetchTLBMiss 1443576Sgblack@eecs.umich.edu 0x80 // PrefetchUncacheable 1453576Sgblack@eecs.umich.edu}; 1463576Sgblack@eecs.umich.edu 1473576Sgblack@eecs.umich.edustatic_assert(sizeof(ArmFault::longDescFaultSources) == 1483576Sgblack@eecs.umich.edu ArmFault::NumFaultSources, 1493576Sgblack@eecs.umich.edu "Invalid size of ArmFault::longDescFaultSources[]"); 1503576Sgblack@eecs.umich.edu 1512223SN/Auint8_t ArmFault::aarch64FaultSources[] = { 1523573Sgblack@eecs.umich.edu 0x21, // AlignmentFault 1533576Sgblack@eecs.umich.edu 0xff, // InstructionCacheMaintenance (INVALID) 1543576Sgblack@eecs.umich.edu 0x14, // SynchExtAbtOnTranslTableWalkL0 1552223SN/A 0x15, // SynchExtAbtOnTranslTableWalkL1 1563573Sgblack@eecs.umich.edu 0x16, // SynchExtAbtOnTranslTableWalkL2 1573576Sgblack@eecs.umich.edu 0x17, // SynchExtAbtOnTranslTableWalkL3 1583576Sgblack@eecs.umich.edu 0x1c, // SynchPtyErrOnTranslTableWalkL0 1592223SN/A 0x1d, // SynchPtyErrOnTranslTableWalkL1 1603573Sgblack@eecs.umich.edu 0x1e, // SynchPtyErrOnTranslTableWalkL2 1613576Sgblack@eecs.umich.edu 0x1f, // SynchPtyErrOnTranslTableWalkL3 1623576Sgblack@eecs.umich.edu 0x04, // TranslationL0 1632223SN/A 0x05, // TranslationL1 1643573Sgblack@eecs.umich.edu 0x06, // TranslationL2 1653576Sgblack@eecs.umich.edu 0x07, // TranslationL3 1663576Sgblack@eecs.umich.edu 0x08, // AccessFlagL0 1672223SN/A 0x09, // AccessFlagL1 1683573Sgblack@eecs.umich.edu 0x0a, // AccessFlagL2 1693576Sgblack@eecs.umich.edu 0x0b, // AccessFlagL3 1703576Sgblack@eecs.umich.edu // @todo: Section & Page Domain Fault in AArch64? 1712223SN/A 0xff, // DomainL0 (INVALID) 1723573Sgblack@eecs.umich.edu 0xff, // DomainL1 (INVALID) 1733576Sgblack@eecs.umich.edu 0xff, // DomainL2 (INVALID) 1743576Sgblack@eecs.umich.edu 0xff, // DomainL3 (INVALID) 1752223SN/A 0x0c, // PermissionL0 1763573Sgblack@eecs.umich.edu 0x0d, // PermissionL1 1773576Sgblack@eecs.umich.edu 0x0e, // PermissionL2 1783576Sgblack@eecs.umich.edu 0x0f, // PermissionL3 1792223SN/A 0xff, // DebugEvent (INVALID) 1803573Sgblack@eecs.umich.edu 0x10, // SynchronousExternalAbort 1813576Sgblack@eecs.umich.edu 0x30, // TLBConflictAbort 1823576Sgblack@eecs.umich.edu 0x18, // SynchPtyErrOnMemoryAccess 1832223SN/A 0xff, // AsynchronousExternalAbort (INVALID) 1843573Sgblack@eecs.umich.edu 0xff, // AsynchPtyErrOnMemoryAccess (INVALID) 1853576Sgblack@eecs.umich.edu 0x00, // AddressSizeL0 1863576Sgblack@eecs.umich.edu 0x01, // AddressSizeL1 1872223SN/A 0x02, // AddressSizeL2 1883573Sgblack@eecs.umich.edu 0x03, // AddressSizeL3 1893576Sgblack@eecs.umich.edu 0x40, // PrefetchTLBMiss 1903576Sgblack@eecs.umich.edu 0x80 // PrefetchUncacheable 1912223SN/A}; 1923576Sgblack@eecs.umich.edu 1933576Sgblack@eecs.umich.edustatic_assert(sizeof(ArmFault::aarch64FaultSources) == 1943576Sgblack@eecs.umich.edu ArmFault::NumFaultSources, 1953576Sgblack@eecs.umich.edu "Invalid size of ArmFault::aarch64FaultSources[]"); 1962527SN/A 1973573Sgblack@eecs.umich.edu// Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode, 1983576Sgblack@eecs.umich.edu// {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap, 1993890Ssaidi@eecs.umich.edu// {A, F} disable, class, stat 2002223SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals = { 2013573Sgblack@eecs.umich.edu // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED 2023576Sgblack@eecs.umich.edu // location in AArch64) 2033576Sgblack@eecs.umich.edu "Reset", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC, 2042223SN/A 0, 0, 0, 0, false, true, true, EC_UNKNOWN, FaultStat() 2053573Sgblack@eecs.umich.edu}; 2063576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals = { 2073576Sgblack@eecs.umich.edu "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED, 2082223SN/A 4, 2, 0, 0, true, false, false, EC_UNKNOWN, FaultStat() 2093573Sgblack@eecs.umich.edu}; 2104103Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals = { 2114103Ssaidi@eecs.umich.edu "Supervisor Call", 0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2124103Ssaidi@eecs.umich.edu 4, 2, 4, 2, true, false, false, EC_SVC_TO_HYP, FaultStat() 2134103Ssaidi@eecs.umich.edu}; 2143576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals = { 2153576Sgblack@eecs.umich.edu "Secure Monitor Call", 0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON, 2162223SN/A 4, 4, 4, 4, false, true, true, EC_SMC_TO_HYP, FaultStat() 2173573Sgblack@eecs.umich.edu}; 2183576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals = { 2193576Sgblack@eecs.umich.edu "Hypervisor Call", 0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP, 2202223SN/A 4, 4, 4, 4, true, false, false, EC_HVC, FaultStat() 2213573Sgblack@eecs.umich.edu}; 2223576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals = { 2233576Sgblack@eecs.umich.edu "Prefetch Abort", 0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT, 2243576Sgblack@eecs.umich.edu 4, 4, 0, 0, true, true, false, EC_PREFETCH_ABORT_TO_HYP, FaultStat() 2253576Sgblack@eecs.umich.edu}; 2263576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals = { 2273576Sgblack@eecs.umich.edu "Data Abort", 0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT, 2283576Sgblack@eecs.umich.edu 8, 8, 0, 0, true, true, false, EC_DATA_ABORT_TO_HYP, FaultStat() 2293576Sgblack@eecs.umich.edu}; 2303576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals = { 2313576Sgblack@eecs.umich.edu "Virtual Data Abort", 0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT, 2323576Sgblack@eecs.umich.edu 8, 8, 0, 0, true, true, false, EC_INVALID, FaultStat() 2333576Sgblack@eecs.umich.edu}; 2343576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals = { 2353576Sgblack@eecs.umich.edu // @todo: double check these values 2363576Sgblack@eecs.umich.edu "Hypervisor Trap", 0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP, 2373576Sgblack@eecs.umich.edu 0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat() 2383576Sgblack@eecs.umich.edu}; 2393576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals = { 2403576Sgblack@eecs.umich.edu "IRQ", 0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ, 2413576Sgblack@eecs.umich.edu 4, 4, 0, 0, false, true, false, EC_UNKNOWN, FaultStat() 2423576Sgblack@eecs.umich.edu}; 2433576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals = { 2443576Sgblack@eecs.umich.edu "Virtual IRQ", 0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ, 2453576Sgblack@eecs.umich.edu 4, 4, 0, 0, false, true, false, EC_INVALID, FaultStat() 2463893Shsul@eecs.umich.edu}; 2473576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals = { 2483576Sgblack@eecs.umich.edu "FIQ", 0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ, 2493576Sgblack@eecs.umich.edu 4, 4, 0, 0, false, true, true, EC_UNKNOWN, FaultStat() 2503576Sgblack@eecs.umich.edu}; 2513576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals = { 2523576Sgblack@eecs.umich.edu "Virtual FIQ", 0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ, 2533576Sgblack@eecs.umich.edu 4, 4, 0, 0, false, true, true, EC_INVALID, FaultStat() 2543576Sgblack@eecs.umich.edu}; 2553576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals = { 2563576Sgblack@eecs.umich.edu // Some dummy values (SupervisorTrap is AArch64-only) 2573576Sgblack@eecs.umich.edu "Supervisor Trap", 0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2583576Sgblack@eecs.umich.edu 0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat() 2593576Sgblack@eecs.umich.edu}; 2603576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals = { 2613576Sgblack@eecs.umich.edu // Some dummy values (SecureMonitorTrap is AArch64-only) 2623576Sgblack@eecs.umich.edu "Secure Monitor Trap", 0x014, 0x000, 0x200, 0x400, 0x600, MODE_MON, 2633576Sgblack@eecs.umich.edu 0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat() 2643576Sgblack@eecs.umich.edu}; 2653576Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals = { 2663576Sgblack@eecs.umich.edu // Some dummy values (PCAlignmentFault is AArch64-only) 2673576Sgblack@eecs.umich.edu "PC Alignment Fault", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2682223SN/A 0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT, FaultStat() 2693415Sgblack@eecs.umich.edu}; 2703578Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals = { 2713578Sgblack@eecs.umich.edu // Some dummy values (SPAlignmentFault is AArch64-only) 2723415Sgblack@eecs.umich.edu "SP Alignment Fault", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2733415Sgblack@eecs.umich.edu 0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT, FaultStat() 2747741Sgblack@eecs.umich.edu}; 2757741Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals = { 2763415Sgblack@eecs.umich.edu // Some dummy values (SError is AArch64-only) 2773578Sgblack@eecs.umich.edu "SError", 0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC, 2783578Sgblack@eecs.umich.edu 0, 0, 0, 0, false, true, true, EC_SERROR, FaultStat() 2794172Ssaidi@eecs.umich.edu}; 2807741Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<FlushPipe>::vals = { 2813578Sgblack@eecs.umich.edu // Some dummy values 2827741Sgblack@eecs.umich.edu "Pipe Flush", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC, 2833578Sgblack@eecs.umich.edu 0, 0, 0, 0, false, true, true, EC_UNKNOWN, FaultStat() 2844172Ssaidi@eecs.umich.edu}; 2857741Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals = { 2867741Sgblack@eecs.umich.edu // Some dummy values 2874172Ssaidi@eecs.umich.edu "ArmSev Flush", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC, 2883746Sgblack@eecs.umich.edu 0, 0, 0, 0, false, true, true, EC_UNKNOWN, FaultStat() 2894172Ssaidi@eecs.umich.edu}; 2903578Sgblack@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals = { 2913578Sgblack@eecs.umich.edu // Some dummy values (SPAlignmentFault is AArch64-only) 2923578Sgblack@eecs.umich.edu "Illegal Inst Set State Fault", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2933578Sgblack@eecs.umich.edu 0, 0, 0, 0, true, false, false, EC_ILLEGAL_INST, FaultStat() 2943578Sgblack@eecs.umich.edu}; 2953578Sgblack@eecs.umich.edu 2963578Sgblack@eecs.umich.eduAddr 2977741Sgblack@eecs.umich.eduArmFault::getVector(ThreadContext *tc) 2987741Sgblack@eecs.umich.edu{ 2993578Sgblack@eecs.umich.edu Addr base; 3004172Ssaidi@eecs.umich.edu 3014172Ssaidi@eecs.umich.edu // ARM ARM issue C B1.8.1 3024172Ssaidi@eecs.umich.edu bool haveSecurity = ArmSystem::haveSecurity(tc); 3034172Ssaidi@eecs.umich.edu 3043761Sgblack@eecs.umich.edu // panic if SCTLR.VE because I have no idea what to do with vectored 3054172Ssaidi@eecs.umich.edu // interrupts 3064172Ssaidi@eecs.umich.edu SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); 3074172Ssaidi@eecs.umich.edu assert(!sctlr.ve); 3084172Ssaidi@eecs.umich.edu // Check for invalid modes 3097720Sgblack@eecs.umich.edu CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 3103578Sgblack@eecs.umich.edu assert(haveSecurity || cpsr.mode != MODE_MON); 3113578Sgblack@eecs.umich.edu assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP); 3123578Sgblack@eecs.umich.edu 3137720Sgblack@eecs.umich.edu switch (cpsr.mode) 3143928Ssaidi@eecs.umich.edu { 3157741Sgblack@eecs.umich.edu case MODE_MON: 3163578Sgblack@eecs.umich.edu base = tc->readMiscReg(MISCREG_MVBAR); 3177741Sgblack@eecs.umich.edu break; 3183578Sgblack@eecs.umich.edu case MODE_HYP: 3197741Sgblack@eecs.umich.edu base = tc->readMiscReg(MISCREG_HVBAR); 3203578Sgblack@eecs.umich.edu break; 3217741Sgblack@eecs.umich.edu default: 3223578Sgblack@eecs.umich.edu if (sctlr.v) { 3237741Sgblack@eecs.umich.edu base = HighVecs; 3243578Sgblack@eecs.umich.edu } else { 3253578Sgblack@eecs.umich.edu base = haveSecurity ? tc->readMiscReg(MISCREG_VBAR) : 0; 3267741Sgblack@eecs.umich.edu } 3274172Ssaidi@eecs.umich.edu break; 3283578Sgblack@eecs.umich.edu } 3297741Sgblack@eecs.umich.edu return base + offset(tc); 3307720Sgblack@eecs.umich.edu} 3317741Sgblack@eecs.umich.edu 3327720Sgblack@eecs.umich.eduAddr 3333578Sgblack@eecs.umich.eduArmFault::getVector64(ThreadContext *tc) 3347741Sgblack@eecs.umich.edu{ 3354172Ssaidi@eecs.umich.edu Addr vbar; 3363578Sgblack@eecs.umich.edu switch (toEL) { 3377741Sgblack@eecs.umich.edu case EL3: 3384172Ssaidi@eecs.umich.edu assert(ArmSystem::haveSecurity(tc)); 3393578Sgblack@eecs.umich.edu vbar = tc->readMiscReg(MISCREG_VBAR_EL3); 3407741Sgblack@eecs.umich.edu break; 3414172Ssaidi@eecs.umich.edu // @todo: uncomment this to enable Virtualization 3423578Sgblack@eecs.umich.edu // case EL2: 3433926Ssaidi@eecs.umich.edu // assert(ArmSystem::haveVirtualization(tc)); 3447741Sgblack@eecs.umich.edu // vbar = tc->readMiscReg(MISCREG_VBAR_EL2); 3454172Ssaidi@eecs.umich.edu // break; 3463578Sgblack@eecs.umich.edu case EL1: 3477741Sgblack@eecs.umich.edu vbar = tc->readMiscReg(MISCREG_VBAR_EL1); 3483578Sgblack@eecs.umich.edu break; 3497741Sgblack@eecs.umich.edu default: 3503578Sgblack@eecs.umich.edu panic("Invalid target exception level"); 3517741Sgblack@eecs.umich.edu break; 3523578Sgblack@eecs.umich.edu } 3537741Sgblack@eecs.umich.edu return vbar + offset64(); 3543578Sgblack@eecs.umich.edu} 3554172Ssaidi@eecs.umich.edu 3563578Sgblack@eecs.umich.eduMiscRegIndex 3573578Sgblack@eecs.umich.eduArmFault::getSyndromeReg64() const 3583893Shsul@eecs.umich.edu{ 3593415Sgblack@eecs.umich.edu switch (toEL) { 3603893Shsul@eecs.umich.edu case EL1: 3613415Sgblack@eecs.umich.edu return MISCREG_ESR_EL1; 3623893Shsul@eecs.umich.edu case EL2: 3633415Sgblack@eecs.umich.edu return MISCREG_ESR_EL2; 3643415Sgblack@eecs.umich.edu case EL3: 3653415Sgblack@eecs.umich.edu return MISCREG_ESR_EL3; 3663420Sgblack@eecs.umich.edu default: 3677741Sgblack@eecs.umich.edu panic("Invalid exception level"); 3683415Sgblack@eecs.umich.edu break; 3694172Ssaidi@eecs.umich.edu } 3703415Sgblack@eecs.umich.edu} 3713415Sgblack@eecs.umich.edu 3723415Sgblack@eecs.umich.eduMiscRegIndex 3737741Sgblack@eecs.umich.eduArmFault::getFaultAddrReg64() const 3747741Sgblack@eecs.umich.edu{ 3757741Sgblack@eecs.umich.edu switch (toEL) { 3767741Sgblack@eecs.umich.edu case EL1: 3777741Sgblack@eecs.umich.edu return MISCREG_FAR_EL1; 3787741Sgblack@eecs.umich.edu case EL2: 3797741Sgblack@eecs.umich.edu return MISCREG_FAR_EL2; 3807741Sgblack@eecs.umich.edu case EL3: 3817741Sgblack@eecs.umich.edu return MISCREG_FAR_EL3; 3827741Sgblack@eecs.umich.edu default: 3837741Sgblack@eecs.umich.edu panic("Invalid exception level"); 3847741Sgblack@eecs.umich.edu break; 3857741Sgblack@eecs.umich.edu } 3867741Sgblack@eecs.umich.edu} 3877741Sgblack@eecs.umich.edu 3887741Sgblack@eecs.umich.eduvoid 3897741Sgblack@eecs.umich.eduArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg) 3907741Sgblack@eecs.umich.edu{ 3917741Sgblack@eecs.umich.edu uint32_t value; 3927741Sgblack@eecs.umich.edu uint32_t exc_class = (uint32_t) ec(tc); 3937741Sgblack@eecs.umich.edu uint32_t issVal = iss(); 3947741Sgblack@eecs.umich.edu assert(!from64 || ArmSystem::highestELIs64(tc)); 3957741Sgblack@eecs.umich.edu 3967741Sgblack@eecs.umich.edu value = exc_class << 26; 3977741Sgblack@eecs.umich.edu 3987741Sgblack@eecs.umich.edu // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24, 3997741Sgblack@eecs.umich.edu // 0x25) for which the ISS information is not valid (ARMv7). 4007741Sgblack@eecs.umich.edu // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not 4017741Sgblack@eecs.umich.edu // valid it is treated as RES1. 4027741Sgblack@eecs.umich.edu if (to64) { 4037741Sgblack@eecs.umich.edu value |= 1 << 25; 4047741Sgblack@eecs.umich.edu } else if ((bits(exc_class, 5, 3) != 4) || 4057741Sgblack@eecs.umich.edu (bits(exc_class, 2) && bits(issVal, 24))) { 4067741Sgblack@eecs.umich.edu if (!machInst.thumb || machInst.bigThumb) 4077741Sgblack@eecs.umich.edu value |= 1 << 25; 4087741Sgblack@eecs.umich.edu } 4097741Sgblack@eecs.umich.edu // Condition code valid for EC[5:4] nonzero 4107741Sgblack@eecs.umich.edu if (!from64 && ((bits(exc_class, 5, 4) == 0) && 4117741Sgblack@eecs.umich.edu (bits(exc_class, 3, 0) != 0))) { 4127741Sgblack@eecs.umich.edu if (!machInst.thumb) { 4137741Sgblack@eecs.umich.edu uint32_t cond; 4147741Sgblack@eecs.umich.edu ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode; 4157741Sgblack@eecs.umich.edu // If its on unconditional instruction report with a cond code of 4167741Sgblack@eecs.umich.edu // 0xE, ie the unconditional code 4177741Sgblack@eecs.umich.edu cond = (condCode == COND_UC) ? COND_AL : condCode; 4187741Sgblack@eecs.umich.edu value |= cond << 20; 4197741Sgblack@eecs.umich.edu value |= 1 << 24; 4207741Sgblack@eecs.umich.edu } 4217741Sgblack@eecs.umich.edu value |= bits(issVal, 19, 0); 4227741Sgblack@eecs.umich.edu } else { 4237741Sgblack@eecs.umich.edu value |= issVal; 4247741Sgblack@eecs.umich.edu } 4257741Sgblack@eecs.umich.edu tc->setMiscReg(syndrome_reg, value); 4267741Sgblack@eecs.umich.edu} 4277741Sgblack@eecs.umich.edu 4287741Sgblack@eecs.umich.eduvoid 4297741Sgblack@eecs.umich.eduArmFault::invoke(ThreadContext *tc, StaticInstPtr inst) 4307741Sgblack@eecs.umich.edu{ 4317741Sgblack@eecs.umich.edu CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 4327741Sgblack@eecs.umich.edu 4337741Sgblack@eecs.umich.edu if (ArmSystem::highestELIs64(tc)) { // ARMv8 4347741Sgblack@eecs.umich.edu // Determine source exception level and mode 4357741Sgblack@eecs.umich.edu fromMode = (OperatingMode) (uint8_t) cpsr.mode; 4367741Sgblack@eecs.umich.edu fromEL = opModeToEL(fromMode); 4377741Sgblack@eecs.umich.edu if (opModeIs64(fromMode)) 4387741Sgblack@eecs.umich.edu from64 = true; 4397741Sgblack@eecs.umich.edu 4407741Sgblack@eecs.umich.edu // Determine target exception level 4417741Sgblack@eecs.umich.edu if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc)) 4427741Sgblack@eecs.umich.edu toEL = EL3; 4437741Sgblack@eecs.umich.edu else 4447741Sgblack@eecs.umich.edu toEL = opModeToEL(nextMode()); 4457741Sgblack@eecs.umich.edu if (fromEL > toEL) 4467741Sgblack@eecs.umich.edu toEL = fromEL; 4477741Sgblack@eecs.umich.edu 4487741Sgblack@eecs.umich.edu if (toEL == ArmSystem::highestEL(tc) || ELIs64(tc, toEL)) { 4497741Sgblack@eecs.umich.edu // Invoke exception handler in AArch64 state 4507741Sgblack@eecs.umich.edu to64 = true; 4517741Sgblack@eecs.umich.edu invoke64(tc, inst); 4527741Sgblack@eecs.umich.edu return; 4537741Sgblack@eecs.umich.edu } 4547741Sgblack@eecs.umich.edu } 4557741Sgblack@eecs.umich.edu 4567741Sgblack@eecs.umich.edu // ARMv7 (ARM ARM issue C B1.9) 4577741Sgblack@eecs.umich.edu 4587741Sgblack@eecs.umich.edu bool have_security = ArmSystem::haveSecurity(tc); 4597741Sgblack@eecs.umich.edu bool have_virtualization = ArmSystem::haveVirtualization(tc); 4607741Sgblack@eecs.umich.edu 4617741Sgblack@eecs.umich.edu FaultBase::invoke(tc); 4627741Sgblack@eecs.umich.edu if (!FullSystem) 4637741Sgblack@eecs.umich.edu return; 4647741Sgblack@eecs.umich.edu countStat()++; 4657741Sgblack@eecs.umich.edu 4667741Sgblack@eecs.umich.edu SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); 4677741Sgblack@eecs.umich.edu SCR scr = tc->readMiscReg(MISCREG_SCR); 4687741Sgblack@eecs.umich.edu CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR); 4697741Sgblack@eecs.umich.edu saved_cpsr.nz = tc->readCCReg(CCREG_NZ); 4707741Sgblack@eecs.umich.edu saved_cpsr.c = tc->readCCReg(CCREG_C); 4713578Sgblack@eecs.umich.edu saved_cpsr.v = tc->readCCReg(CCREG_V); 4723585Sgblack@eecs.umich.edu saved_cpsr.ge = tc->readCCReg(CCREG_GE); 4733603Ssaidi@eecs.umich.edu 4743595Sgblack@eecs.umich.edu Addr curPc M5_VAR_USED = tc->pcState().pc(); 4753578Sgblack@eecs.umich.edu ITSTATE it = tc->pcState().itstate(); 4763578Sgblack@eecs.umich.edu saved_cpsr.it2 = it.top6; 4773578Sgblack@eecs.umich.edu saved_cpsr.it1 = it.bottom2; 4787741Sgblack@eecs.umich.edu 4797741Sgblack@eecs.umich.edu // if we have a valid instruction then use it to annotate this fault with 4803578Sgblack@eecs.umich.edu // extra information. This is used to generate the correct fault syndrome 4814172Ssaidi@eecs.umich.edu // information 4823578Sgblack@eecs.umich.edu if (inst) { 4833578Sgblack@eecs.umich.edu ArmStaticInst *armInst = reinterpret_cast<ArmStaticInst *>(inst.get()); 4843578Sgblack@eecs.umich.edu armInst->annotateFault(this); 4853578Sgblack@eecs.umich.edu } 4867741Sgblack@eecs.umich.edu 4877741Sgblack@eecs.umich.edu if (have_security && routeToMonitor(tc)) 4883578Sgblack@eecs.umich.edu cpsr.mode = MODE_MON; 4894172Ssaidi@eecs.umich.edu else if (have_virtualization && routeToHyp(tc)) 4903578Sgblack@eecs.umich.edu cpsr.mode = MODE_HYP; 4913578Sgblack@eecs.umich.edu else 4923578Sgblack@eecs.umich.edu cpsr.mode = nextMode(); 4933578Sgblack@eecs.umich.edu 4943578Sgblack@eecs.umich.edu // Ensure Secure state if initially in Monitor mode 4953578Sgblack@eecs.umich.edu if (have_security && saved_cpsr.mode == MODE_MON) { 4967741Sgblack@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 4977741Sgblack@eecs.umich.edu if (scr.ns) { 4982221SN/A scr.ns = 0; 4992680Sktlim@umich.edu tc->setMiscRegNoEffect(MISCREG_SCR, scr); 5008750Sgblack@eecs.umich.edu } 5018750Sgblack@eecs.umich.edu } 5028750Sgblack@eecs.umich.edu 5032223SN/A // some bits are set differently if we have been routed to hyp mode 5042221SN/A if (cpsr.mode == MODE_HYP) { 5057741Sgblack@eecs.umich.edu SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR); 5067741Sgblack@eecs.umich.edu cpsr.t = hsctlr.te; 5074172Ssaidi@eecs.umich.edu cpsr.e = hsctlr.ee; 5084172Ssaidi@eecs.umich.edu if (!scr.ea) {cpsr.a = 1;} 5094172Ssaidi@eecs.umich.edu if (!scr.fiq) {cpsr.f = 1;} 5104172Ssaidi@eecs.umich.edu if (!scr.irq) {cpsr.i = 1;} 5113578Sgblack@eecs.umich.edu } else if (cpsr.mode == MODE_MON) { 5123578Sgblack@eecs.umich.edu // Special case handling when entering monitor mode 5133578Sgblack@eecs.umich.edu cpsr.t = sctlr.te; 5143578Sgblack@eecs.umich.edu cpsr.e = sctlr.ee; 5153893Shsul@eecs.umich.edu cpsr.a = 1; 5163746Sgblack@eecs.umich.edu cpsr.f = 1; 5173893Shsul@eecs.umich.edu cpsr.i = 1; 5183578Sgblack@eecs.umich.edu } else { 5193578Sgblack@eecs.umich.edu cpsr.t = sctlr.te; 5203746Sgblack@eecs.umich.edu cpsr.e = sctlr.ee; 5213578Sgblack@eecs.umich.edu 5223578Sgblack@eecs.umich.edu // The *Disable functions are virtual and different per fault 5233578Sgblack@eecs.umich.edu cpsr.a = cpsr.a | abortDisable(tc); 5243893Shsul@eecs.umich.edu cpsr.f = cpsr.f | fiqDisable(tc); 5253595Sgblack@eecs.umich.edu cpsr.i = 1; 5263893Shsul@eecs.umich.edu } 5277741Sgblack@eecs.umich.edu cpsr.it1 = cpsr.it2 = 0; 5287741Sgblack@eecs.umich.edu cpsr.j = 0; 5293578Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_CPSR, cpsr); 5303893Shsul@eecs.umich.edu 5313825Ssaidi@eecs.umich.edu // Make sure mailbox sets to one always 5327741Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_SEV_MAILBOX, 1); 5337741Sgblack@eecs.umich.edu 5347741Sgblack@eecs.umich.edu // Clear the exclusive monitor 5353893Shsul@eecs.umich.edu tc->setMiscReg(MISCREG_LOCKFLAG, 0); 5367741Sgblack@eecs.umich.edu 5373578Sgblack@eecs.umich.edu if (cpsr.mode == MODE_HYP) { 5383585Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_ELR_HYP, curPc + 5393893Shsul@eecs.umich.edu (saved_cpsr.t ? thumbPcOffset(true) : armPcOffset(true))); 5405570Snate@binkert.org } else { 5413578Sgblack@eecs.umich.edu tc->setIntReg(INTREG_LR, curPc + 5423585Sgblack@eecs.umich.edu (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false))); 5433826Ssaidi@eecs.umich.edu } 5443578Sgblack@eecs.umich.edu 5457741Sgblack@eecs.umich.edu switch (cpsr.mode) { 5463578Sgblack@eecs.umich.edu case MODE_FIQ: 5473578Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr); 5487720Sgblack@eecs.umich.edu break; 5497720Sgblack@eecs.umich.edu case MODE_IRQ: 5507720Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr); 5517720Sgblack@eecs.umich.edu break; 5527720Sgblack@eecs.umich.edu case MODE_SVC: 5537720Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr); 5547720Sgblack@eecs.umich.edu break; 5553420Sgblack@eecs.umich.edu case MODE_MON: 5562221SN/A assert(have_security); 5577741Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr); 5587741Sgblack@eecs.umich.edu break; 5593523Sgblack@eecs.umich.edu case MODE_ABORT: 5607741Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr); 5617741Sgblack@eecs.umich.edu break; 5627741Sgblack@eecs.umich.edu case MODE_UNDEFINED: 5633595Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr); 5644172Ssaidi@eecs.umich.edu if (ec(tc) != EC_UNKNOWN) 5654172Ssaidi@eecs.umich.edu setSyndrome(tc, MISCREG_HSR); 5664172Ssaidi@eecs.umich.edu break; 5673595Sgblack@eecs.umich.edu case MODE_HYP: 5687741Sgblack@eecs.umich.edu assert(have_virtualization); 5694172Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr); 5703595Sgblack@eecs.umich.edu setSyndrome(tc, MISCREG_HSR); 5717741Sgblack@eecs.umich.edu break; 5724172Ssaidi@eecs.umich.edu default: 5737741Sgblack@eecs.umich.edu panic("unknown Mode\n"); 5743628Sgblack@eecs.umich.edu } 5757741Sgblack@eecs.umich.edu 5763628Sgblack@eecs.umich.edu Addr newPc = getVector(tc); 5777741Sgblack@eecs.umich.edu DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n", 5783628Sgblack@eecs.umich.edu name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc); 5797741Sgblack@eecs.umich.edu PCState pc(newPc); 5803628Sgblack@eecs.umich.edu pc.thumb(cpsr.t); 5814172Ssaidi@eecs.umich.edu pc.nextThumb(pc.thumb()); 5823595Sgblack@eecs.umich.edu pc.jazelle(cpsr.j); 5837741Sgblack@eecs.umich.edu pc.nextJazelle(pc.jazelle()); 5844172Ssaidi@eecs.umich.edu pc.aarch64(!cpsr.width); 5853595Sgblack@eecs.umich.edu pc.nextAArch64(!cpsr.width); 5867741Sgblack@eecs.umich.edu tc->pcState(pc); 5877741Sgblack@eecs.umich.edu} 5883746Sgblack@eecs.umich.edu 5893746Sgblack@eecs.umich.eduvoid 5903595Sgblack@eecs.umich.eduArmFault::invoke64(ThreadContext *tc, StaticInstPtr inst) 5913595Sgblack@eecs.umich.edu{ 5927720Sgblack@eecs.umich.edu // Determine actual misc. register indices for ELR_ELx and SPSR_ELx 5937720Sgblack@eecs.umich.edu MiscRegIndex elr_idx, spsr_idx; 5947720Sgblack@eecs.umich.edu switch (toEL) { 5957720Sgblack@eecs.umich.edu case EL1: 5967720Sgblack@eecs.umich.edu elr_idx = MISCREG_ELR_EL1; 5977720Sgblack@eecs.umich.edu spsr_idx = MISCREG_SPSR_EL1; 5987720Sgblack@eecs.umich.edu break; 5997720Sgblack@eecs.umich.edu // @todo: uncomment this to enable Virtualization 6003595Sgblack@eecs.umich.edu // case EL2: 6017741Sgblack@eecs.umich.edu // assert(ArmSystem::haveVirtualization()); 6027741Sgblack@eecs.umich.edu // elr_idx = MISCREG_ELR_EL2; 6033523Sgblack@eecs.umich.edu // spsr_idx = MISCREG_SPSR_EL2; 6043595Sgblack@eecs.umich.edu // break; 6053595Sgblack@eecs.umich.edu case EL3: 6063595Sgblack@eecs.umich.edu assert(ArmSystem::haveSecurity(tc)); 6074172Ssaidi@eecs.umich.edu elr_idx = MISCREG_ELR_EL3; 6083595Sgblack@eecs.umich.edu spsr_idx = MISCREG_SPSR_EL3; 6093523Sgblack@eecs.umich.edu break; 6107741Sgblack@eecs.umich.edu default: 6113523Sgblack@eecs.umich.edu panic("Invalid target exception level"); 6123523Sgblack@eecs.umich.edu break; 6133523Sgblack@eecs.umich.edu } 6143523Sgblack@eecs.umich.edu 6153523Sgblack@eecs.umich.edu // Save process state into SPSR_ELx 6163523Sgblack@eecs.umich.edu CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 6173523Sgblack@eecs.umich.edu CPSR spsr = cpsr; 6183523Sgblack@eecs.umich.edu spsr.nz = tc->readCCReg(CCREG_NZ); 6193523Sgblack@eecs.umich.edu spsr.c = tc->readCCReg(CCREG_C); 6202221SN/A spsr.v = tc->readCCReg(CCREG_V); 6212221SN/A if (from64) { 6227741Sgblack@eecs.umich.edu // Force some bitfields to 0 6237741Sgblack@eecs.umich.edu spsr.q = 0; 6244997Sgblack@eecs.umich.edu spsr.it1 = 0; 6258767Sgblack@eecs.umich.edu spsr.j = 0; 6268767Sgblack@eecs.umich.edu spsr.res0_23_22 = 0; 6274997Sgblack@eecs.umich.edu spsr.ge = 0; 6288767Sgblack@eecs.umich.edu spsr.it2 = 0; 6298767Sgblack@eecs.umich.edu spsr.t = 0; 6308767Sgblack@eecs.umich.edu } else { 6318767Sgblack@eecs.umich.edu spsr.ge = tc->readCCReg(CCREG_GE); 6328767Sgblack@eecs.umich.edu ITSTATE it = tc->pcState().itstate(); 6338767Sgblack@eecs.umich.edu spsr.it2 = it.top6; 6348767Sgblack@eecs.umich.edu spsr.it1 = it.bottom2; 6358767Sgblack@eecs.umich.edu // Force some bitfields to 0 6368767Sgblack@eecs.umich.edu spsr.res0_23_22 = 0; 6378767Sgblack@eecs.umich.edu spsr.ss = 0; 6384997Sgblack@eecs.umich.edu } 6394997Sgblack@eecs.umich.edu tc->setMiscReg(spsr_idx, spsr); 6404997Sgblack@eecs.umich.edu 6417741Sgblack@eecs.umich.edu // Save preferred return address into ELR_ELx 6427741Sgblack@eecs.umich.edu Addr curr_pc = tc->pcState().pc(); 6434997Sgblack@eecs.umich.edu Addr ret_addr = curr_pc; 6448767Sgblack@eecs.umich.edu if (from64) 6458767Sgblack@eecs.umich.edu ret_addr += armPcElrOffset(); 6468767Sgblack@eecs.umich.edu else 6478767Sgblack@eecs.umich.edu ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset(); 6488767Sgblack@eecs.umich.edu tc->setMiscReg(elr_idx, ret_addr); 6498767Sgblack@eecs.umich.edu 6508767Sgblack@eecs.umich.edu // Update process state 6518767Sgblack@eecs.umich.edu OperatingMode64 mode = 0; 6528767Sgblack@eecs.umich.edu mode.spX = 1; 6538767Sgblack@eecs.umich.edu mode.el = toEL; 6548767Sgblack@eecs.umich.edu mode.width = 0; 6558767Sgblack@eecs.umich.edu cpsr.mode = mode; 6568767Sgblack@eecs.umich.edu cpsr.daif = 0xf; 6578767Sgblack@eecs.umich.edu cpsr.il = 0; 6588767Sgblack@eecs.umich.edu cpsr.ss = 0; 6598767Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_CPSR, cpsr); 6608767Sgblack@eecs.umich.edu 6614997Sgblack@eecs.umich.edu // Set PC to start of exception handler 6624997Sgblack@eecs.umich.edu Addr new_pc = purifyTaggedAddr(getVector64(tc), tc, toEL); 6634997Sgblack@eecs.umich.edu DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x " 6647741Sgblack@eecs.umich.edu "elr:%#x newVec: %#x\n", name(), cpsr, curr_pc, ret_addr, new_pc); 6657741Sgblack@eecs.umich.edu PCState pc(new_pc); 6663415Sgblack@eecs.umich.edu pc.aarch64(!cpsr.width); 6678778Sgblack@eecs.umich.edu pc.nextAArch64(!cpsr.width); 6688778Sgblack@eecs.umich.edu tc->pcState(pc); 6698778Sgblack@eecs.umich.edu 6708778Sgblack@eecs.umich.edu // If we have a valid instruction then use it to annotate this fault with 6713415Sgblack@eecs.umich.edu // extra information. This is used to generate the correct fault syndrome 6728778Sgblack@eecs.umich.edu // information 6733415Sgblack@eecs.umich.edu if (inst) 6748778Sgblack@eecs.umich.edu reinterpret_cast<ArmStaticInst *>(inst.get())->annotateFault(this); 6758778Sgblack@eecs.umich.edu // Save exception syndrome 6768778Sgblack@eecs.umich.edu if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ)) 6773415Sgblack@eecs.umich.edu setSyndrome(tc, getSyndromeReg64()); 6788778Sgblack@eecs.umich.edu} 6798778Sgblack@eecs.umich.edu 6808778Sgblack@eecs.umich.eduvoid 6813415Sgblack@eecs.umich.eduReset::invoke(ThreadContext *tc, StaticInstPtr inst) 6823415Sgblack@eecs.umich.edu{ 6837741Sgblack@eecs.umich.edu if (FullSystem) { 6847741Sgblack@eecs.umich.edu tc->getCpuPtr()->clearInterrupts(); 6853415Sgblack@eecs.umich.edu tc->clearArchRegs(); 6868778Sgblack@eecs.umich.edu } 6878778Sgblack@eecs.umich.edu if (!ArmSystem::highestELIs64(tc)) { 6888778Sgblack@eecs.umich.edu ArmFault::invoke(tc, inst); 6898778Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_VMPIDR, 6903415Sgblack@eecs.umich.edu getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc)); 6918778Sgblack@eecs.umich.edu 6923415Sgblack@eecs.umich.edu // Unless we have SMC code to get us there, boot in HYP! 6938778Sgblack@eecs.umich.edu if (ArmSystem::haveVirtualization(tc) && 6948778Sgblack@eecs.umich.edu !ArmSystem::haveSecurity(tc)) { 6958778Sgblack@eecs.umich.edu CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 6963415Sgblack@eecs.umich.edu cpsr.mode = MODE_HYP; 6978778Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_CPSR, cpsr); 6988778Sgblack@eecs.umich.edu } 6998778Sgblack@eecs.umich.edu } else { 7003415Sgblack@eecs.umich.edu // Advance the PC to the IMPLEMENTATION DEFINED reset value 7013415Sgblack@eecs.umich.edu PCState pc = ArmSystem::resetAddr64(tc); 7027741Sgblack@eecs.umich.edu pc.aarch64(true); 7037741Sgblack@eecs.umich.edu pc.nextAArch64(true); 7044111Sgblack@eecs.umich.edu tc->pcState(pc); 7058778Sgblack@eecs.umich.edu } 7068778Sgblack@eecs.umich.edu} 7078778Sgblack@eecs.umich.edu 7088778Sgblack@eecs.umich.eduvoid 7098778Sgblack@eecs.umich.eduUndefinedInstruction::invoke(ThreadContext *tc, StaticInstPtr inst) 7108778Sgblack@eecs.umich.edu{ 7114111Sgblack@eecs.umich.edu if (FullSystem) { 7128778Sgblack@eecs.umich.edu ArmFault::invoke(tc, inst); 7134111Sgblack@eecs.umich.edu return; 7148778Sgblack@eecs.umich.edu } 7158778Sgblack@eecs.umich.edu 7164111Sgblack@eecs.umich.edu // If the mnemonic isn't defined this has to be an unknown instruction. 7178778Sgblack@eecs.umich.edu assert(unknown || mnemonic != NULL); 7184111Sgblack@eecs.umich.edu if (disabled) { 7198778Sgblack@eecs.umich.edu panic("Attempted to execute disabled instruction " 7208778Sgblack@eecs.umich.edu "'%s' (inst 0x%08x)", mnemonic, machInst); 7218778Sgblack@eecs.umich.edu } else if (unknown) { 7228778Sgblack@eecs.umich.edu panic("Attempted to execute unknown instruction (inst 0x%08x)", 7238778Sgblack@eecs.umich.edu machInst); 7248778Sgblack@eecs.umich.edu } else { 7254111Sgblack@eecs.umich.edu panic("Attempted to execute unimplemented instruction " 7264111Sgblack@eecs.umich.edu "'%s' (inst 0x%08x)", mnemonic, machInst); 7272223SN/A } 7282221SN/A} 729 730bool 731UndefinedInstruction::routeToHyp(ThreadContext *tc) const 732{ 733 bool toHyp; 734 735 SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 736 HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 737 CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 738 739 // if in Hyp mode then stay in Hyp mode 740 toHyp = scr.ns && (cpsr.mode == MODE_HYP); 741 // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector 742 toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER); 743 return toHyp; 744} 745 746uint32_t 747UndefinedInstruction::iss() const 748{ 749 if (overrideEc == EC_INVALID) 750 return issRaw; 751 752 uint32_t new_iss = 0; 753 uint32_t op0, op1, op2, CRn, CRm, Rt, dir; 754 755 dir = bits(machInst, 21, 21); 756 op0 = bits(machInst, 20, 19); 757 op1 = bits(machInst, 18, 16); 758 CRn = bits(machInst, 15, 12); 759 CRm = bits(machInst, 11, 8); 760 op2 = bits(machInst, 7, 5); 761 Rt = bits(machInst, 4, 0); 762 763 new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 | 764 Rt << 5 | CRm << 1 | dir; 765 766 return new_iss; 767} 768 769void 770SupervisorCall::invoke(ThreadContext *tc, StaticInstPtr inst) 771{ 772 if (FullSystem) { 773 ArmFault::invoke(tc, inst); 774 return; 775 } 776 777 // As of now, there isn't a 32 bit thumb version of this instruction. 778 assert(!machInst.bigThumb); 779 uint32_t callNum; 780 CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 781 OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode; 782 if (opModeIs64(mode)) 783 callNum = tc->readIntReg(INTREG_X8); 784 else 785 callNum = tc->readIntReg(INTREG_R7); 786 tc->syscall(callNum); 787 788 // Advance the PC since that won't happen automatically. 789 PCState pc = tc->pcState(); 790 assert(inst); 791 inst->advancePC(pc); 792 tc->pcState(pc); 793} 794 795bool 796SupervisorCall::routeToHyp(ThreadContext *tc) const 797{ 798 bool toHyp; 799 800 SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 801 HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 802 CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 803 804 // if in Hyp mode then stay in Hyp mode 805 toHyp = scr.ns && (cpsr.mode == MODE_HYP); 806 // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector 807 toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER); 808 return toHyp; 809} 810 811ExceptionClass 812SupervisorCall::ec(ThreadContext *tc) const 813{ 814 return (overrideEc != EC_INVALID) ? overrideEc : 815 (from64 ? EC_SVC_64 : vals.ec); 816} 817 818uint32_t 819SupervisorCall::iss() const 820{ 821 // Even if we have a 24 bit imm from an arm32 instruction then we only use 822 // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC). 823 return issRaw & 0xFFFF; 824} 825 826uint32_t 827SecureMonitorCall::iss() const 828{ 829 if (from64) 830 return bits(machInst, 20, 5); 831 return 0; 832} 833 834ExceptionClass 835UndefinedInstruction::ec(ThreadContext *tc) const 836{ 837 return (overrideEc != EC_INVALID) ? overrideEc : vals.ec; 838} 839 840 841HypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) : 842 ArmFaultVals<HypervisorCall>(_machInst, _imm) 843{} 844 845ExceptionClass 846HypervisorTrap::ec(ThreadContext *tc) const 847{ 848 return (overrideEc != EC_INVALID) ? overrideEc : vals.ec; 849} 850 851template<class T> 852FaultOffset 853ArmFaultVals<T>::offset(ThreadContext *tc) 854{ 855 bool isHypTrap = false; 856 857 // Normally we just use the exception vector from the table at the top if 858 // this file, however if this exception has caused a transition to hype 859 // mode, and its an exception type that would only do this if it has been 860 // trapped then we use the hyp trap vector instead of the normal vector 861 if (vals.hypTrappable) { 862 CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 863 if (cpsr.mode == MODE_HYP) { 864 CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP); 865 isHypTrap = spsr.mode != MODE_HYP; 866 } 867 } 868 return isHypTrap ? 0x14 : vals.offset; 869} 870 871// void 872// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx) 873// { 874// ESR esr = 0; 875// esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32; 876// esr.il = !machInst.thumb; 877// if (machInst.aarch64) 878// esr.imm16 = bits(machInst.instBits, 20, 5); 879// else if (machInst.thumb) 880// esr.imm16 = bits(machInst.instBits, 7, 0); 881// else 882// esr.imm16 = bits(machInst.instBits, 15, 0); 883// tc->setMiscReg(esr_idx, esr); 884// } 885 886void 887SecureMonitorCall::invoke(ThreadContext *tc, StaticInstPtr inst) 888{ 889 if (FullSystem) { 890 ArmFault::invoke(tc, inst); 891 return; 892 } 893} 894 895ExceptionClass 896SecureMonitorCall::ec(ThreadContext *tc) const 897{ 898 return (from64 ? EC_SMC_64 : vals.ec); 899} 900 901ExceptionClass 902SupervisorTrap::ec(ThreadContext *tc) const 903{ 904 return (overrideEc != EC_INVALID) ? overrideEc : vals.ec; 905} 906 907ExceptionClass 908SecureMonitorTrap::ec(ThreadContext *tc) const 909{ 910 return (overrideEc != EC_INVALID) ? overrideEc : 911 (from64 ? EC_SMC_64 : vals.ec); 912} 913 914template<class T> 915void 916AbortFault<T>::invoke(ThreadContext *tc, StaticInstPtr inst) 917{ 918 if (tranMethod == ArmFault::UnknownTran) { 919 tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran 920 : ArmFault::VmsaTran; 921 922 if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) { 923 // See ARM ARM B3-1416 924 bool override_LPAE = false; 925 TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S); 926 TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS); 927 if (ttbcr_s.eae) { 928 override_LPAE = true; 929 } else { 930 // Unimplemented code option, not seen in testing. May need 931 // extension according to the manual exceprt above. 932 DPRINTF(Faults, "Warning: Incomplete translation method " 933 "override detected.\n"); 934 } 935 if (override_LPAE) 936 tranMethod = ArmFault::LpaeTran; 937 } 938 } 939 940 if (source == ArmFault::AsynchronousExternalAbort) { 941 tc->getCpuPtr()->clearInterrupt(INT_ABT, 0); 942 } 943 // Get effective fault source encoding 944 CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 945 FSR fsr = getFsr(tc); 946 947 // source must be determined BEFORE invoking generic routines which will 948 // try to set hsr etc. and are based upon source! 949 ArmFaultVals<T>::invoke(tc, inst); 950 951 if (cpsr.width) { // AArch32 952 if (cpsr.mode == MODE_HYP) { 953 tc->setMiscReg(T::HFarIndex, faultAddr); 954 } else if (stage2) { 955 tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf); 956 tc->setMiscReg(T::HFarIndex, OVAddr); 957 } else { 958 tc->setMiscReg(T::FsrIndex, fsr); 959 tc->setMiscReg(T::FarIndex, faultAddr); 960 } 961 DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\ 962 "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod); 963 } else { // AArch64 964 // Set the FAR register. Nothing else to do if we are in AArch64 state 965 // because the syndrome register has already been set inside invoke64() 966 tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr); 967 } 968} 969 970template<class T> 971FSR 972AbortFault<T>::getFsr(ThreadContext *tc) 973{ 974 FSR fsr = 0; 975 976 if (((CPSR) tc->readMiscRegNoEffect(MISCREG_CPSR)).width) { 977 // AArch32 978 assert(tranMethod != ArmFault::UnknownTran); 979 if (tranMethod == ArmFault::LpaeTran) { 980 srcEncoded = ArmFault::longDescFaultSources[source]; 981 fsr.status = srcEncoded; 982 fsr.lpae = 1; 983 } else { 984 srcEncoded = ArmFault::shortDescFaultSources[source]; 985 fsr.fsLow = bits(srcEncoded, 3, 0); 986 fsr.fsHigh = bits(srcEncoded, 4); 987 fsr.domain = static_cast<uint8_t>(domain); 988 } 989 fsr.wnr = (write ? 1 : 0); 990 fsr.ext = 0; 991 } else { 992 // AArch64 993 srcEncoded = ArmFault::aarch64FaultSources[source]; 994 } 995 if (srcEncoded == ArmFault::FaultSourceInvalid) { 996 panic("Invalid fault source\n"); 997 } 998 return fsr; 999} 1000 1001template<class T> 1002bool 1003AbortFault<T>::abortDisable(ThreadContext *tc) 1004{ 1005 if (ArmSystem::haveSecurity(tc)) { 1006 SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 1007 return (!scr.ns || scr.aw); 1008 } 1009 return true; 1010} 1011 1012template<class T> 1013void 1014AbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val) 1015{ 1016 switch (id) 1017 { 1018 case ArmFault::S1PTW: 1019 s1ptw = val; 1020 break; 1021 case ArmFault::OVA: 1022 OVAddr = val; 1023 break; 1024 1025 // Just ignore unknown ID's 1026 default: 1027 break; 1028 } 1029} 1030 1031template<class T> 1032uint32_t 1033AbortFault<T>::iss() const 1034{ 1035 uint32_t val; 1036 1037 val = srcEncoded & 0x3F; 1038 val |= write << 6; 1039 val |= s1ptw << 7; 1040 return (val); 1041} 1042 1043template<class T> 1044bool 1045AbortFault<T>::isMMUFault() const 1046{ 1047 // NOTE: Not relying on LL information being aligned to lowest bits here 1048 return 1049 (source == ArmFault::AlignmentFault) || 1050 ((source >= ArmFault::TranslationLL) && 1051 (source < ArmFault::TranslationLL + 4)) || 1052 ((source >= ArmFault::AccessFlagLL) && 1053 (source < ArmFault::AccessFlagLL + 4)) || 1054 ((source >= ArmFault::DomainLL) && 1055 (source < ArmFault::DomainLL + 4)) || 1056 ((source >= ArmFault::PermissionLL) && 1057 (source < ArmFault::PermissionLL + 4)); 1058} 1059 1060ExceptionClass 1061PrefetchAbort::ec(ThreadContext *tc) const 1062{ 1063 if (to64) { 1064 // AArch64 1065 if (toEL == fromEL) 1066 return EC_PREFETCH_ABORT_CURR_EL; 1067 else 1068 return EC_PREFETCH_ABORT_LOWER_EL; 1069 } else { 1070 // AArch32 1071 // Abort faults have different EC codes depending on whether 1072 // the fault originated within HYP mode, or not. So override 1073 // the method and add the extra adjustment of the EC value. 1074 1075 ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec; 1076 1077 CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP); 1078 if (spsr.mode == MODE_HYP) { 1079 ec = ((ExceptionClass) (((uint32_t) ec) + 1)); 1080 } 1081 return ec; 1082 } 1083} 1084 1085bool 1086PrefetchAbort::routeToMonitor(ThreadContext *tc) const 1087{ 1088 SCR scr = 0; 1089 if (from64) 1090 scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 1091 else 1092 scr = tc->readMiscRegNoEffect(MISCREG_SCR); 1093 1094 return scr.ea && !isMMUFault(); 1095} 1096 1097bool 1098PrefetchAbort::routeToHyp(ThreadContext *tc) const 1099{ 1100 bool toHyp; 1101 1102 SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 1103 HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 1104 CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 1105 HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR); 1106 1107 // if in Hyp mode then stay in Hyp mode 1108 toHyp = scr.ns && (cpsr.mode == MODE_HYP); 1109 // otherwise, check whether to take to Hyp mode through Hyp Trap vector 1110 toHyp |= (stage2 || 1111 ( (source == DebugEvent) && hdcr.tde && (cpsr.mode != MODE_HYP)) || 1112 ( (source == SynchronousExternalAbort) && hcr.tge && (cpsr.mode == MODE_USER)) 1113 ) && !inSecureState(scr, cpsr); 1114 return toHyp; 1115} 1116 1117ExceptionClass 1118DataAbort::ec(ThreadContext *tc) const 1119{ 1120 if (to64) { 1121 // AArch64 1122 if (source == ArmFault::AsynchronousExternalAbort) { 1123 panic("Asynchronous External Abort should be handled with " 1124 "SystemErrors (SErrors)!"); 1125 } 1126 if (toEL == fromEL) 1127 return EC_DATA_ABORT_CURR_EL; 1128 else 1129 return EC_DATA_ABORT_LOWER_EL; 1130 } else { 1131 // AArch32 1132 // Abort faults have different EC codes depending on whether 1133 // the fault originated within HYP mode, or not. So override 1134 // the method and add the extra adjustment of the EC value. 1135 1136 ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec; 1137 1138 CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP); 1139 if (spsr.mode == MODE_HYP) { 1140 ec = ((ExceptionClass) (((uint32_t) ec) + 1)); 1141 } 1142 return ec; 1143 } 1144} 1145 1146bool 1147DataAbort::routeToMonitor(ThreadContext *tc) const 1148{ 1149 SCR scr = 0; 1150 if (from64) 1151 scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 1152 else 1153 scr = tc->readMiscRegNoEffect(MISCREG_SCR); 1154 1155 return scr.ea && !isMMUFault(); 1156} 1157 1158bool 1159DataAbort::routeToHyp(ThreadContext *tc) const 1160{ 1161 bool toHyp; 1162 1163 SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 1164 HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 1165 CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 1166 HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR); 1167 1168 // if in Hyp mode then stay in Hyp mode 1169 toHyp = scr.ns && (cpsr.mode == MODE_HYP); 1170 // otherwise, check whether to take to Hyp mode through Hyp Trap vector 1171 toHyp |= (stage2 || 1172 ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) || 1173 ((source == DebugEvent) && hdcr.tde) ) 1174 ) || 1175 ( (cpsr.mode == MODE_USER) && hcr.tge && 1176 ((source == AlignmentFault) || 1177 (source == SynchronousExternalAbort)) 1178 ) 1179 ) && !inSecureState(scr, cpsr); 1180 return toHyp; 1181} 1182 1183uint32_t 1184DataAbort::iss() const 1185{ 1186 uint32_t val; 1187 1188 // Add on the data abort specific fields to the generic abort ISS value 1189 val = AbortFault<DataAbort>::iss(); 1190 // ISS is valid if not caused by a stage 1 page table walk, and when taken 1191 // to AArch64 only when directed to EL2 1192 if (!s1ptw && (!to64 || toEL == EL2)) { 1193 val |= isv << 24; 1194 if (isv) { 1195 val |= sas << 22; 1196 val |= sse << 21; 1197 val |= srt << 16; 1198 // AArch64 only. These assignments are safe on AArch32 as well 1199 // because these vars are initialized to false 1200 val |= sf << 15; 1201 val |= ar << 14; 1202 } 1203 } 1204 return (val); 1205} 1206 1207void 1208DataAbort::annotate(AnnotationIDs id, uint64_t val) 1209{ 1210 AbortFault<DataAbort>::annotate(id, val); 1211 switch (id) 1212 { 1213 case SAS: 1214 isv = true; 1215 sas = val; 1216 break; 1217 case SSE: 1218 isv = true; 1219 sse = val; 1220 break; 1221 case SRT: 1222 isv = true; 1223 srt = val; 1224 break; 1225 case SF: 1226 isv = true; 1227 sf = val; 1228 break; 1229 case AR: 1230 isv = true; 1231 ar = val; 1232 break; 1233 // Just ignore unknown ID's 1234 default: 1235 break; 1236 } 1237} 1238 1239void 1240VirtualDataAbort::invoke(ThreadContext *tc, StaticInstPtr inst) 1241{ 1242 AbortFault<VirtualDataAbort>::invoke(tc, inst); 1243 HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 1244 hcr.va = 0; 1245 tc->setMiscRegNoEffect(MISCREG_HCR, hcr); 1246} 1247 1248bool 1249Interrupt::routeToMonitor(ThreadContext *tc) const 1250{ 1251 assert(ArmSystem::haveSecurity(tc)); 1252 SCR scr = 0; 1253 if (from64) 1254 scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 1255 else 1256 scr = tc->readMiscRegNoEffect(MISCREG_SCR); 1257 return scr.irq; 1258} 1259 1260bool 1261Interrupt::routeToHyp(ThreadContext *tc) const 1262{ 1263 bool toHyp; 1264 1265 SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 1266 HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 1267 CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 1268 // Determine whether IRQs are routed to Hyp mode. 1269 toHyp = (!scr.irq && hcr.imo && !inSecureState(scr, cpsr)) || 1270 (cpsr.mode == MODE_HYP); 1271 return toHyp; 1272} 1273 1274bool 1275Interrupt::abortDisable(ThreadContext *tc) 1276{ 1277 if (ArmSystem::haveSecurity(tc)) { 1278 SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 1279 return (!scr.ns || scr.aw); 1280 } 1281 return true; 1282} 1283 1284VirtualInterrupt::VirtualInterrupt() 1285{} 1286 1287bool 1288FastInterrupt::routeToMonitor(ThreadContext *tc) const 1289{ 1290 assert(ArmSystem::haveSecurity(tc)); 1291 SCR scr = 0; 1292 if (from64) 1293 scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 1294 else 1295 scr = tc->readMiscRegNoEffect(MISCREG_SCR); 1296 return scr.fiq; 1297} 1298 1299bool 1300FastInterrupt::routeToHyp(ThreadContext *tc) const 1301{ 1302 bool toHyp; 1303 1304 SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 1305 HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 1306 CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 1307 // Determine whether IRQs are routed to Hyp mode. 1308 toHyp = (!scr.fiq && hcr.fmo && !inSecureState(scr, cpsr)) || 1309 (cpsr.mode == MODE_HYP); 1310 return toHyp; 1311} 1312 1313bool 1314FastInterrupt::abortDisable(ThreadContext *tc) 1315{ 1316 if (ArmSystem::haveSecurity(tc)) { 1317 SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 1318 return (!scr.ns || scr.aw); 1319 } 1320 return true; 1321} 1322 1323bool 1324FastInterrupt::fiqDisable(ThreadContext *tc) 1325{ 1326 if (ArmSystem::haveVirtualization(tc)) { 1327 return true; 1328 } else if (ArmSystem::haveSecurity(tc)) { 1329 SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 1330 return (!scr.ns || scr.fw); 1331 } 1332 return true; 1333} 1334 1335VirtualFastInterrupt::VirtualFastInterrupt() 1336{} 1337 1338void 1339PCAlignmentFault::invoke(ThreadContext *tc, StaticInstPtr inst) 1340{ 1341 ArmFaultVals<PCAlignmentFault>::invoke(tc, inst); 1342 assert(from64); 1343 // Set the FAR 1344 tc->setMiscReg(getFaultAddrReg64(), faultPC); 1345} 1346 1347SPAlignmentFault::SPAlignmentFault() 1348{} 1349 1350SystemError::SystemError() 1351{} 1352 1353void 1354SystemError::invoke(ThreadContext *tc, StaticInstPtr inst) 1355{ 1356 tc->getCpuPtr()->clearInterrupt(INT_ABT, 0); 1357 ArmFault::invoke(tc, inst); 1358} 1359 1360bool 1361SystemError::routeToMonitor(ThreadContext *tc) const 1362{ 1363 assert(ArmSystem::haveSecurity(tc)); 1364 assert(from64); 1365 SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 1366 return scr.ea; 1367} 1368 1369bool 1370SystemError::routeToHyp(ThreadContext *tc) const 1371{ 1372 bool toHyp; 1373 assert(from64); 1374 1375 SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 1376 HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 1377 CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 1378 1379 toHyp = (!scr.ea && hcr.amo && !inSecureState(scr, cpsr)) || 1380 (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(scr,cpsr)); 1381 return toHyp; 1382} 1383 1384void 1385FlushPipe::invoke(ThreadContext *tc, StaticInstPtr inst) { 1386 DPRINTF(Faults, "Invoking FlushPipe Fault\n"); 1387 1388 // Set the PC to the next instruction of the faulting instruction. 1389 // Net effect is simply squashing all instructions behind and 1390 // start refetching from the next instruction. 1391 PCState pc = tc->pcState(); 1392 assert(inst); 1393 inst->advancePC(pc); 1394 tc->pcState(pc); 1395} 1396 1397void 1398ArmSev::invoke(ThreadContext *tc, StaticInstPtr inst) { 1399 DPRINTF(Faults, "Invoking ArmSev Fault\n"); 1400 if (!FullSystem) 1401 return; 1402 1403 // Set sev_mailbox to 1, clear the pending interrupt from remote 1404 // SEV execution and let pipeline continue as pcState is still 1405 // valid. 1406 tc->setMiscReg(MISCREG_SEV_MAILBOX, 1); 1407 tc->getCpuPtr()->clearInterrupt(INT_SEV, 0); 1408} 1409 1410// Instantiate all the templates to make the linker happy 1411template class ArmFaultVals<Reset>; 1412template class ArmFaultVals<UndefinedInstruction>; 1413template class ArmFaultVals<SupervisorCall>; 1414template class ArmFaultVals<SecureMonitorCall>; 1415template class ArmFaultVals<HypervisorCall>; 1416template class ArmFaultVals<PrefetchAbort>; 1417template class ArmFaultVals<DataAbort>; 1418template class ArmFaultVals<VirtualDataAbort>; 1419template class ArmFaultVals<HypervisorTrap>; 1420template class ArmFaultVals<Interrupt>; 1421template class ArmFaultVals<VirtualInterrupt>; 1422template class ArmFaultVals<FastInterrupt>; 1423template class ArmFaultVals<VirtualFastInterrupt>; 1424template class ArmFaultVals<SupervisorTrap>; 1425template class ArmFaultVals<SecureMonitorTrap>; 1426template class ArmFaultVals<PCAlignmentFault>; 1427template class ArmFaultVals<SPAlignmentFault>; 1428template class ArmFaultVals<SystemError>; 1429template class ArmFaultVals<FlushPipe>; 1430template class ArmFaultVals<ArmSev>; 1431template class AbortFault<PrefetchAbort>; 1432template class AbortFault<DataAbort>; 1433template class AbortFault<VirtualDataAbort>; 1434 1435 1436IllegalInstSetStateFault::IllegalInstSetStateFault() 1437{} 1438 1439 1440} // namespace ArmISA 1441