faults.cc revision 12299
15952Ssaidi@eecs.umich.edu/* 25952Ssaidi@eecs.umich.edu * Copyright (c) 2010, 2012-2014, 2016-2017 ARM Limited 35952Ssaidi@eecs.umich.edu * All rights reserved 45952Ssaidi@eecs.umich.edu * 55952Ssaidi@eecs.umich.edu * The license below extends only to copyright in the software and shall 65952Ssaidi@eecs.umich.edu * not be construed as granting a license to any other intellectual 75952Ssaidi@eecs.umich.edu * property including but not limited to intellectual property relating 85952Ssaidi@eecs.umich.edu * to a hardware implementation of the functionality of the software 95952Ssaidi@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 105952Ssaidi@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 115952Ssaidi@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 125952Ssaidi@eecs.umich.edu * modified or unmodified, in source code or in binary form. 135952Ssaidi@eecs.umich.edu * 145952Ssaidi@eecs.umich.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan 155952Ssaidi@eecs.umich.edu * Copyright (c) 2007-2008 The Florida State University 165952Ssaidi@eecs.umich.edu * All rights reserved. 175952Ssaidi@eecs.umich.edu * 185952Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 195952Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are 205952Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright 215952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 225952Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 235952Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 245952Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution; 255952Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its 265952Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 275952Ssaidi@eecs.umich.edu * this software without specific prior written permission. 285952Ssaidi@eecs.umich.edu * 295952Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 305952Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3110377Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 325952Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 338229Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 348229Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 355952Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 365952Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 375952Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 386658Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 395952Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4010377Sandreas.hansson@arm.com * 4110377Sandreas.hansson@arm.com * Authors: Ali Saidi 425952Ssaidi@eecs.umich.edu * Gabe Black 435952Ssaidi@eecs.umich.edu * Giacomo Gabrielli 445952Ssaidi@eecs.umich.edu * Thomas Grocutt 455952Ssaidi@eecs.umich.edu */ 465952Ssaidi@eecs.umich.edu 475952Ssaidi@eecs.umich.edu#include "arch/arm/faults.hh" 485952Ssaidi@eecs.umich.edu 495952Ssaidi@eecs.umich.edu#include "arch/arm/insts/static_inst.hh" 505952Ssaidi@eecs.umich.edu#include "arch/arm/system.hh" 515952Ssaidi@eecs.umich.edu#include "arch/arm/utility.hh" 525952Ssaidi@eecs.umich.edu#include "base/compiler.hh" 535952Ssaidi@eecs.umich.edu#include "base/trace.hh" 545952Ssaidi@eecs.umich.edu#include "cpu/base.hh" 555952Ssaidi@eecs.umich.edu#include "cpu/thread_context.hh" 565952Ssaidi@eecs.umich.edu#include "debug/Faults.hh" 575952Ssaidi@eecs.umich.edu#include "sim/full_system.hh" 585952Ssaidi@eecs.umich.edu 595952Ssaidi@eecs.umich.edunamespace ArmISA 605952Ssaidi@eecs.umich.edu{ 615952Ssaidi@eecs.umich.edu 625952Ssaidi@eecs.umich.eduuint8_t ArmFault::shortDescFaultSources[] = { 635952Ssaidi@eecs.umich.edu 0x01, // AlignmentFault 645952Ssaidi@eecs.umich.edu 0x04, // InstructionCacheMaintenance 655952Ssaidi@eecs.umich.edu 0xff, // SynchExtAbtOnTranslTableWalkL0 (INVALID) 665952Ssaidi@eecs.umich.edu 0x0c, // SynchExtAbtOnTranslTableWalkL1 675952Ssaidi@eecs.umich.edu 0x0e, // SynchExtAbtOnTranslTableWalkL2 685952Ssaidi@eecs.umich.edu 0xff, // SynchExtAbtOnTranslTableWalkL3 (INVALID) 695952Ssaidi@eecs.umich.edu 0xff, // SynchPtyErrOnTranslTableWalkL0 (INVALID) 705952Ssaidi@eecs.umich.edu 0x1c, // SynchPtyErrOnTranslTableWalkL1 715952Ssaidi@eecs.umich.edu 0x1e, // SynchPtyErrOnTranslTableWalkL2 725952Ssaidi@eecs.umich.edu 0xff, // SynchPtyErrOnTranslTableWalkL3 (INVALID) 735952Ssaidi@eecs.umich.edu 0xff, // TranslationL0 (INVALID) 745952Ssaidi@eecs.umich.edu 0x05, // TranslationL1 755952Ssaidi@eecs.umich.edu 0x07, // TranslationL2 765952Ssaidi@eecs.umich.edu 0xff, // TranslationL3 (INVALID) 775952Ssaidi@eecs.umich.edu 0xff, // AccessFlagL0 (INVALID) 785952Ssaidi@eecs.umich.edu 0x03, // AccessFlagL1 795952Ssaidi@eecs.umich.edu 0x06, // AccessFlagL2 805952Ssaidi@eecs.umich.edu 0xff, // AccessFlagL3 (INVALID) 815952Ssaidi@eecs.umich.edu 0xff, // DomainL0 (INVALID) 825952Ssaidi@eecs.umich.edu 0x09, // DomainL1 835952Ssaidi@eecs.umich.edu 0x0b, // DomainL2 845952Ssaidi@eecs.umich.edu 0xff, // DomainL3 (INVALID) 855952Ssaidi@eecs.umich.edu 0xff, // PermissionL0 (INVALID) 865952Ssaidi@eecs.umich.edu 0x0d, // PermissionL1 875952Ssaidi@eecs.umich.edu 0x0f, // PermissionL2 885952Ssaidi@eecs.umich.edu 0xff, // PermissionL3 (INVALID) 895952Ssaidi@eecs.umich.edu 0x02, // DebugEvent 905952Ssaidi@eecs.umich.edu 0x08, // SynchronousExternalAbort 915952Ssaidi@eecs.umich.edu 0x10, // TLBConflictAbort 925952Ssaidi@eecs.umich.edu 0x19, // SynchPtyErrOnMemoryAccess 935952Ssaidi@eecs.umich.edu 0x16, // AsynchronousExternalAbort 945952Ssaidi@eecs.umich.edu 0x18, // AsynchPtyErrOnMemoryAccess 955952Ssaidi@eecs.umich.edu 0xff, // AddressSizeL0 (INVALID) 965952Ssaidi@eecs.umich.edu 0xff, // AddressSizeL1 (INVALID) 975952Ssaidi@eecs.umich.edu 0xff, // AddressSizeL2 (INVALID) 985952Ssaidi@eecs.umich.edu 0xff, // AddressSizeL3 (INVALID) 995952Ssaidi@eecs.umich.edu 0x40, // PrefetchTLBMiss 1005952Ssaidi@eecs.umich.edu 0x80 // PrefetchUncacheable 1015952Ssaidi@eecs.umich.edu}; 1025952Ssaidi@eecs.umich.edu 1035952Ssaidi@eecs.umich.edustatic_assert(sizeof(ArmFault::shortDescFaultSources) == 1045952Ssaidi@eecs.umich.edu ArmFault::NumFaultSources, 1055952Ssaidi@eecs.umich.edu "Invalid size of ArmFault::shortDescFaultSources[]"); 1065952Ssaidi@eecs.umich.edu 1075952Ssaidi@eecs.umich.eduuint8_t ArmFault::longDescFaultSources[] = { 1085952Ssaidi@eecs.umich.edu 0x21, // AlignmentFault 1095952Ssaidi@eecs.umich.edu 0xff, // InstructionCacheMaintenance (INVALID) 1105952Ssaidi@eecs.umich.edu 0xff, // SynchExtAbtOnTranslTableWalkL0 (INVALID) 1115952Ssaidi@eecs.umich.edu 0x15, // SynchExtAbtOnTranslTableWalkL1 1125952Ssaidi@eecs.umich.edu 0x16, // SynchExtAbtOnTranslTableWalkL2 1135952Ssaidi@eecs.umich.edu 0x17, // SynchExtAbtOnTranslTableWalkL3 1145952Ssaidi@eecs.umich.edu 0xff, // SynchPtyErrOnTranslTableWalkL0 (INVALID) 1155952Ssaidi@eecs.umich.edu 0x1d, // SynchPtyErrOnTranslTableWalkL1 1165952Ssaidi@eecs.umich.edu 0x1e, // SynchPtyErrOnTranslTableWalkL2 1175952Ssaidi@eecs.umich.edu 0x1f, // SynchPtyErrOnTranslTableWalkL3 1185952Ssaidi@eecs.umich.edu 0xff, // TranslationL0 (INVALID) 1195952Ssaidi@eecs.umich.edu 0x05, // TranslationL1 1205952Ssaidi@eecs.umich.edu 0x06, // TranslationL2 1215952Ssaidi@eecs.umich.edu 0x07, // TranslationL3 1225952Ssaidi@eecs.umich.edu 0xff, // AccessFlagL0 (INVALID) 1235952Ssaidi@eecs.umich.edu 0x09, // AccessFlagL1 1245952Ssaidi@eecs.umich.edu 0x0a, // AccessFlagL2 1255952Ssaidi@eecs.umich.edu 0x0b, // AccessFlagL3 1265952Ssaidi@eecs.umich.edu 0xff, // DomainL0 (INVALID) 1275952Ssaidi@eecs.umich.edu 0x3d, // DomainL1 1285952Ssaidi@eecs.umich.edu 0x3e, // DomainL2 1295952Ssaidi@eecs.umich.edu 0xff, // DomainL3 (RESERVED) 1305952Ssaidi@eecs.umich.edu 0xff, // PermissionL0 (INVALID) 1315952Ssaidi@eecs.umich.edu 0x0d, // PermissionL1 1325952Ssaidi@eecs.umich.edu 0x0e, // PermissionL2 1335952Ssaidi@eecs.umich.edu 0x0f, // PermissionL3 1345952Ssaidi@eecs.umich.edu 0x22, // DebugEvent 1355952Ssaidi@eecs.umich.edu 0x10, // SynchronousExternalAbort 1365952Ssaidi@eecs.umich.edu 0x30, // TLBConflictAbort 1375952Ssaidi@eecs.umich.edu 0x18, // SynchPtyErrOnMemoryAccess 1385952Ssaidi@eecs.umich.edu 0x11, // AsynchronousExternalAbort 1395952Ssaidi@eecs.umich.edu 0x19, // AsynchPtyErrOnMemoryAccess 1405952Ssaidi@eecs.umich.edu 0xff, // AddressSizeL0 (INVALID) 1415952Ssaidi@eecs.umich.edu 0xff, // AddressSizeL1 (INVALID) 1425952Ssaidi@eecs.umich.edu 0xff, // AddressSizeL2 (INVALID) 1435952Ssaidi@eecs.umich.edu 0xff, // AddressSizeL3 (INVALID) 1445952Ssaidi@eecs.umich.edu 0x40, // PrefetchTLBMiss 1455952Ssaidi@eecs.umich.edu 0x80 // PrefetchUncacheable 1465952Ssaidi@eecs.umich.edu}; 14710377Sandreas.hansson@arm.com 14810377Sandreas.hansson@arm.comstatic_assert(sizeof(ArmFault::longDescFaultSources) == 14910377Sandreas.hansson@arm.com ArmFault::NumFaultSources, 15010377Sandreas.hansson@arm.com "Invalid size of ArmFault::longDescFaultSources[]"); 15110377Sandreas.hansson@arm.com 15210377Sandreas.hansson@arm.comuint8_t ArmFault::aarch64FaultSources[] = { 15310377Sandreas.hansson@arm.com 0x21, // AlignmentFault 15410377Sandreas.hansson@arm.com 0xff, // InstructionCacheMaintenance (INVALID) 15510377Sandreas.hansson@arm.com 0x14, // SynchExtAbtOnTranslTableWalkL0 15610377Sandreas.hansson@arm.com 0x15, // SynchExtAbtOnTranslTableWalkL1 15710377Sandreas.hansson@arm.com 0x16, // SynchExtAbtOnTranslTableWalkL2 1585952Ssaidi@eecs.umich.edu 0x17, // SynchExtAbtOnTranslTableWalkL3 1595952Ssaidi@eecs.umich.edu 0x1c, // SynchPtyErrOnTranslTableWalkL0 1605952Ssaidi@eecs.umich.edu 0x1d, // SynchPtyErrOnTranslTableWalkL1 1615952Ssaidi@eecs.umich.edu 0x1e, // SynchPtyErrOnTranslTableWalkL2 1625952Ssaidi@eecs.umich.edu 0x1f, // SynchPtyErrOnTranslTableWalkL3 1635952Ssaidi@eecs.umich.edu 0x04, // TranslationL0 1645952Ssaidi@eecs.umich.edu 0x05, // TranslationL1 1655952Ssaidi@eecs.umich.edu 0x06, // TranslationL2 1665952Ssaidi@eecs.umich.edu 0x07, // TranslationL3 1675952Ssaidi@eecs.umich.edu 0x08, // AccessFlagL0 1685952Ssaidi@eecs.umich.edu 0x09, // AccessFlagL1 1695952Ssaidi@eecs.umich.edu 0x0a, // AccessFlagL2 1705952Ssaidi@eecs.umich.edu 0x0b, // AccessFlagL3 1715952Ssaidi@eecs.umich.edu // @todo: Section & Page Domain Fault in AArch64? 1725952Ssaidi@eecs.umich.edu 0xff, // DomainL0 (INVALID) 1735952Ssaidi@eecs.umich.edu 0xff, // DomainL1 (INVALID) 1745952Ssaidi@eecs.umich.edu 0xff, // DomainL2 (INVALID) 1755952Ssaidi@eecs.umich.edu 0xff, // DomainL3 (INVALID) 1765952Ssaidi@eecs.umich.edu 0x0c, // PermissionL0 1777823Ssteve.reinhardt@amd.com 0x0d, // PermissionL1 1785952Ssaidi@eecs.umich.edu 0x0e, // PermissionL2 1795952Ssaidi@eecs.umich.edu 0x0f, // PermissionL3 1805952Ssaidi@eecs.umich.edu 0xff, // DebugEvent (INVALID) 1815952Ssaidi@eecs.umich.edu 0x10, // SynchronousExternalAbort 1825952Ssaidi@eecs.umich.edu 0x30, // TLBConflictAbort 1835952Ssaidi@eecs.umich.edu 0x18, // SynchPtyErrOnMemoryAccess 1845952Ssaidi@eecs.umich.edu 0xff, // AsynchronousExternalAbort (INVALID) 1855952Ssaidi@eecs.umich.edu 0xff, // AsynchPtyErrOnMemoryAccess (INVALID) 1865952Ssaidi@eecs.umich.edu 0x00, // AddressSizeL0 1875952Ssaidi@eecs.umich.edu 0x01, // AddressSizeL1 1885952Ssaidi@eecs.umich.edu 0x02, // AddressSizeL2 1895952Ssaidi@eecs.umich.edu 0x03, // AddressSizeL3 1905952Ssaidi@eecs.umich.edu 0x40, // PrefetchTLBMiss 1915952Ssaidi@eecs.umich.edu 0x80 // PrefetchUncacheable 1925952Ssaidi@eecs.umich.edu}; 1935952Ssaidi@eecs.umich.edu 1945952Ssaidi@eecs.umich.edustatic_assert(sizeof(ArmFault::aarch64FaultSources) == 1955952Ssaidi@eecs.umich.edu ArmFault::NumFaultSources, 1965952Ssaidi@eecs.umich.edu "Invalid size of ArmFault::aarch64FaultSources[]"); 1975952Ssaidi@eecs.umich.edu 1985952Ssaidi@eecs.umich.edu// Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode, 1995952Ssaidi@eecs.umich.edu// {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap, 2005952Ssaidi@eecs.umich.edu// {A, F} disable, class, stat 2015952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals = { 2025952Ssaidi@eecs.umich.edu // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED 2035952Ssaidi@eecs.umich.edu // location in AArch64) 2045952Ssaidi@eecs.umich.edu "Reset", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC, 2055952Ssaidi@eecs.umich.edu 0, 0, 0, 0, false, true, true, EC_UNKNOWN, FaultStat() 2065952Ssaidi@eecs.umich.edu}; 2075952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals = { 2085952Ssaidi@eecs.umich.edu "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED, 2095952Ssaidi@eecs.umich.edu 4, 2, 0, 0, true, false, false, EC_UNKNOWN, FaultStat() 2105952Ssaidi@eecs.umich.edu}; 2115952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals = { 2125952Ssaidi@eecs.umich.edu "Supervisor Call", 0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2135952Ssaidi@eecs.umich.edu 4, 2, 4, 2, true, false, false, EC_SVC_TO_HYP, FaultStat() 2145952Ssaidi@eecs.umich.edu}; 2155952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals = { 2165952Ssaidi@eecs.umich.edu "Secure Monitor Call", 0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON, 2175952Ssaidi@eecs.umich.edu 4, 4, 4, 4, false, true, true, EC_SMC_TO_HYP, FaultStat() 2185952Ssaidi@eecs.umich.edu}; 2195952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals = { 2205952Ssaidi@eecs.umich.edu "Hypervisor Call", 0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP, 2215952Ssaidi@eecs.umich.edu 4, 4, 4, 4, true, false, false, EC_HVC, FaultStat() 2225952Ssaidi@eecs.umich.edu}; 2235952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals = { 2245952Ssaidi@eecs.umich.edu "Prefetch Abort", 0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT, 2255952Ssaidi@eecs.umich.edu 4, 4, 0, 0, true, true, false, EC_PREFETCH_ABORT_TO_HYP, FaultStat() 2265952Ssaidi@eecs.umich.edu}; 2275952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals = { 2285952Ssaidi@eecs.umich.edu "Data Abort", 0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT, 2295952Ssaidi@eecs.umich.edu 8, 8, 0, 0, true, true, false, EC_DATA_ABORT_TO_HYP, FaultStat() 2305952Ssaidi@eecs.umich.edu}; 2315952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals = { 2325952Ssaidi@eecs.umich.edu "Virtual Data Abort", 0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT, 2335952Ssaidi@eecs.umich.edu 8, 8, 0, 0, true, true, false, EC_INVALID, FaultStat() 2345952Ssaidi@eecs.umich.edu}; 2355952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals = { 2365952Ssaidi@eecs.umich.edu // @todo: double check these values 2375952Ssaidi@eecs.umich.edu "Hypervisor Trap", 0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP, 2385952Ssaidi@eecs.umich.edu 0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat() 2395952Ssaidi@eecs.umich.edu}; 2405952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals = { 2415952Ssaidi@eecs.umich.edu "IRQ", 0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ, 2425952Ssaidi@eecs.umich.edu 4, 4, 0, 0, false, true, false, EC_UNKNOWN, FaultStat() 2435952Ssaidi@eecs.umich.edu}; 2445952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals = { 2455952Ssaidi@eecs.umich.edu "Virtual IRQ", 0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ, 2465952Ssaidi@eecs.umich.edu 4, 4, 0, 0, false, true, false, EC_INVALID, FaultStat() 2475952Ssaidi@eecs.umich.edu}; 2485952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals = { 2495952Ssaidi@eecs.umich.edu "FIQ", 0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ, 2505952Ssaidi@eecs.umich.edu 4, 4, 0, 0, false, true, true, EC_UNKNOWN, FaultStat() 2515952Ssaidi@eecs.umich.edu}; 2525952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals = { 2535952Ssaidi@eecs.umich.edu "Virtual FIQ", 0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ, 2545952Ssaidi@eecs.umich.edu 4, 4, 0, 0, false, true, true, EC_INVALID, FaultStat() 2555952Ssaidi@eecs.umich.edu}; 2565952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals = { 2575952Ssaidi@eecs.umich.edu // Some dummy values (SupervisorTrap is AArch64-only) 2585952Ssaidi@eecs.umich.edu "Supervisor Trap", 0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2595952Ssaidi@eecs.umich.edu 0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat() 2605952Ssaidi@eecs.umich.edu}; 2615952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals = { 2625952Ssaidi@eecs.umich.edu // Some dummy values (SecureMonitorTrap is AArch64-only) 2635952Ssaidi@eecs.umich.edu "Secure Monitor Trap", 0x014, 0x000, 0x200, 0x400, 0x600, MODE_MON, 2645952Ssaidi@eecs.umich.edu 0, 0, 0, 0, false, false, false, EC_UNKNOWN, FaultStat() 2655952Ssaidi@eecs.umich.edu}; 2665952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals = { 2675952Ssaidi@eecs.umich.edu // Some dummy values (PCAlignmentFault is AArch64-only) 2685952Ssaidi@eecs.umich.edu "PC Alignment Fault", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2695952Ssaidi@eecs.umich.edu 0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT, FaultStat() 2705952Ssaidi@eecs.umich.edu}; 2715952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals = { 2725952Ssaidi@eecs.umich.edu // Some dummy values (SPAlignmentFault is AArch64-only) 2735952Ssaidi@eecs.umich.edu "SP Alignment Fault", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2745952Ssaidi@eecs.umich.edu 0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT, FaultStat() 2755952Ssaidi@eecs.umich.edu}; 2765952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals = { 2775952Ssaidi@eecs.umich.edu // Some dummy values (SError is AArch64-only) 2785952Ssaidi@eecs.umich.edu "SError", 0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC, 2795952Ssaidi@eecs.umich.edu 0, 0, 0, 0, false, true, true, EC_SERROR, FaultStat() 2805952Ssaidi@eecs.umich.edu}; 2815952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals = { 2825952Ssaidi@eecs.umich.edu // Some dummy values (SoftwareBreakpoint is AArch64-only) 2835952Ssaidi@eecs.umich.edu "Software Breakpoint", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2845952Ssaidi@eecs.umich.edu 0, 0, 0, 0, true, false, false, EC_SOFTWARE_BREAKPOINT, FaultStat() 2855952Ssaidi@eecs.umich.edu}; 2865952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals = { 2875952Ssaidi@eecs.umich.edu // Some dummy values 2885952Ssaidi@eecs.umich.edu "ArmSev Flush", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC, 2897823Ssteve.reinhardt@amd.com 0, 0, 0, 0, false, true, true, EC_UNKNOWN, FaultStat() 2905952Ssaidi@eecs.umich.edu}; 2915952Ssaidi@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals = { 2925952Ssaidi@eecs.umich.edu // Some dummy values (SPAlignmentFault is AArch64-only) 2935952Ssaidi@eecs.umich.edu "Illegal Inst Set State Fault", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2945952Ssaidi@eecs.umich.edu 0, 0, 0, 0, true, false, false, EC_ILLEGAL_INST, FaultStat() 2955952Ssaidi@eecs.umich.edu}; 2965952Ssaidi@eecs.umich.edu 2975952Ssaidi@eecs.umich.eduAddr 2985952Ssaidi@eecs.umich.eduArmFault::getVector(ThreadContext *tc) 2995952Ssaidi@eecs.umich.edu{ 3005952Ssaidi@eecs.umich.edu Addr base; 3015952Ssaidi@eecs.umich.edu 3025952Ssaidi@eecs.umich.edu // ARM ARM issue C B1.8.1 3035952Ssaidi@eecs.umich.edu bool haveSecurity = ArmSystem::haveSecurity(tc); 3045952Ssaidi@eecs.umich.edu 3055952Ssaidi@eecs.umich.edu // panic if SCTLR.VE because I have no idea what to do with vectored 3065952Ssaidi@eecs.umich.edu // interrupts 3075952Ssaidi@eecs.umich.edu SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); 3085952Ssaidi@eecs.umich.edu assert(!sctlr.ve); 3095952Ssaidi@eecs.umich.edu // Check for invalid modes 3105952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 3115952Ssaidi@eecs.umich.edu assert(haveSecurity || cpsr.mode != MODE_MON); 3125952Ssaidi@eecs.umich.edu assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP); 3135952Ssaidi@eecs.umich.edu 3145952Ssaidi@eecs.umich.edu switch (cpsr.mode) 3155952Ssaidi@eecs.umich.edu { 3165952Ssaidi@eecs.umich.edu case MODE_MON: 3175952Ssaidi@eecs.umich.edu base = tc->readMiscReg(MISCREG_MVBAR); 3185952Ssaidi@eecs.umich.edu break; 3195952Ssaidi@eecs.umich.edu case MODE_HYP: 3205952Ssaidi@eecs.umich.edu base = tc->readMiscReg(MISCREG_HVBAR); 3215952Ssaidi@eecs.umich.edu break; 3225952Ssaidi@eecs.umich.edu default: 3235952Ssaidi@eecs.umich.edu if (sctlr.v) { 3245952Ssaidi@eecs.umich.edu base = HighVecs; 3255952Ssaidi@eecs.umich.edu } else { 3265952Ssaidi@eecs.umich.edu base = haveSecurity ? tc->readMiscReg(MISCREG_VBAR) : 0; 3275952Ssaidi@eecs.umich.edu } 3285952Ssaidi@eecs.umich.edu break; 3295952Ssaidi@eecs.umich.edu } 3305952Ssaidi@eecs.umich.edu return base + offset(tc); 3315952Ssaidi@eecs.umich.edu} 3327823Ssteve.reinhardt@amd.com 3335952Ssaidi@eecs.umich.eduAddr 3345952Ssaidi@eecs.umich.eduArmFault::getVector64(ThreadContext *tc) 3355952Ssaidi@eecs.umich.edu{ 3365952Ssaidi@eecs.umich.edu Addr vbar; 3375952Ssaidi@eecs.umich.edu switch (toEL) { 3385952Ssaidi@eecs.umich.edu case EL3: 3395952Ssaidi@eecs.umich.edu assert(ArmSystem::haveSecurity(tc)); 3405952Ssaidi@eecs.umich.edu vbar = tc->readMiscReg(MISCREG_VBAR_EL3); 3415952Ssaidi@eecs.umich.edu break; 3425952Ssaidi@eecs.umich.edu case EL2: 3435952Ssaidi@eecs.umich.edu assert(ArmSystem::haveVirtualization(tc)); 3445952Ssaidi@eecs.umich.edu vbar = tc->readMiscReg(MISCREG_VBAR_EL2); 3455952Ssaidi@eecs.umich.edu break; 3465952Ssaidi@eecs.umich.edu case EL1: 3475952Ssaidi@eecs.umich.edu vbar = tc->readMiscReg(MISCREG_VBAR_EL1); 3485952Ssaidi@eecs.umich.edu break; 3495952Ssaidi@eecs.umich.edu default: 3505952Ssaidi@eecs.umich.edu panic("Invalid target exception level"); 3515952Ssaidi@eecs.umich.edu break; 3525952Ssaidi@eecs.umich.edu } 3535952Ssaidi@eecs.umich.edu return vbar + offset64(); 3545952Ssaidi@eecs.umich.edu} 3555952Ssaidi@eecs.umich.edu 3565952Ssaidi@eecs.umich.eduMiscRegIndex 3575952Ssaidi@eecs.umich.eduArmFault::getSyndromeReg64() const 3585952Ssaidi@eecs.umich.edu{ 3595952Ssaidi@eecs.umich.edu switch (toEL) { 3605952Ssaidi@eecs.umich.edu case EL1: 3615952Ssaidi@eecs.umich.edu return MISCREG_ESR_EL1; 3625952Ssaidi@eecs.umich.edu case EL2: 3635952Ssaidi@eecs.umich.edu return MISCREG_ESR_EL2; 3645952Ssaidi@eecs.umich.edu case EL3: 3655952Ssaidi@eecs.umich.edu return MISCREG_ESR_EL3; 3665952Ssaidi@eecs.umich.edu default: 3675952Ssaidi@eecs.umich.edu panic("Invalid exception level"); 3685952Ssaidi@eecs.umich.edu break; 3695952Ssaidi@eecs.umich.edu } 3705952Ssaidi@eecs.umich.edu} 3715952Ssaidi@eecs.umich.edu 3725952Ssaidi@eecs.umich.eduMiscRegIndex 3735952Ssaidi@eecs.umich.eduArmFault::getFaultAddrReg64() const 3745952Ssaidi@eecs.umich.edu{ 3755952Ssaidi@eecs.umich.edu switch (toEL) { 3765952Ssaidi@eecs.umich.edu case EL1: 3775952Ssaidi@eecs.umich.edu return MISCREG_FAR_EL1; 3785952Ssaidi@eecs.umich.edu case EL2: 3795952Ssaidi@eecs.umich.edu return MISCREG_FAR_EL2; 3805952Ssaidi@eecs.umich.edu case EL3: 3815952Ssaidi@eecs.umich.edu return MISCREG_FAR_EL3; 3825952Ssaidi@eecs.umich.edu default: 3835952Ssaidi@eecs.umich.edu panic("Invalid exception level"); 3845952Ssaidi@eecs.umich.edu break; 3855952Ssaidi@eecs.umich.edu } 3865952Ssaidi@eecs.umich.edu} 3875952Ssaidi@eecs.umich.edu 3885952Ssaidi@eecs.umich.eduvoid 3895952Ssaidi@eecs.umich.eduArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg) 3905952Ssaidi@eecs.umich.edu{ 3915952Ssaidi@eecs.umich.edu uint32_t value; 3925952Ssaidi@eecs.umich.edu uint32_t exc_class = (uint32_t) ec(tc); 3935952Ssaidi@eecs.umich.edu uint32_t issVal = iss(); 3945952Ssaidi@eecs.umich.edu assert(!from64 || ArmSystem::highestELIs64(tc)); 3955952Ssaidi@eecs.umich.edu 3965952Ssaidi@eecs.umich.edu value = exc_class << 26; 3975952Ssaidi@eecs.umich.edu 3985952Ssaidi@eecs.umich.edu // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24, 3995952Ssaidi@eecs.umich.edu // 0x25) for which the ISS information is not valid (ARMv7). 4005952Ssaidi@eecs.umich.edu // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not 4015952Ssaidi@eecs.umich.edu // valid it is treated as RES1. 4025952Ssaidi@eecs.umich.edu if (to64) { 4035952Ssaidi@eecs.umich.edu value |= 1 << 25; 4045952Ssaidi@eecs.umich.edu } else if ((bits(exc_class, 5, 3) != 4) || 4055952Ssaidi@eecs.umich.edu (bits(exc_class, 2) && bits(issVal, 24))) { 4065952Ssaidi@eecs.umich.edu if (!machInst.thumb || machInst.bigThumb) 4075952Ssaidi@eecs.umich.edu value |= 1 << 25; 4085952Ssaidi@eecs.umich.edu } 4095952Ssaidi@eecs.umich.edu // Condition code valid for EC[5:4] nonzero 4105952Ssaidi@eecs.umich.edu if (!from64 && ((bits(exc_class, 5, 4) == 0) && 4115952Ssaidi@eecs.umich.edu (bits(exc_class, 3, 0) != 0))) { 4125952Ssaidi@eecs.umich.edu if (!machInst.thumb) { 4135952Ssaidi@eecs.umich.edu uint32_t cond; 4145952Ssaidi@eecs.umich.edu ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode; 4155952Ssaidi@eecs.umich.edu // If its on unconditional instruction report with a cond code of 4165952Ssaidi@eecs.umich.edu // 0xE, ie the unconditional code 4175952Ssaidi@eecs.umich.edu cond = (condCode == COND_UC) ? COND_AL : condCode; 4185952Ssaidi@eecs.umich.edu value |= cond << 20; 4195952Ssaidi@eecs.umich.edu value |= 1 << 24; 4205952Ssaidi@eecs.umich.edu } 4215952Ssaidi@eecs.umich.edu value |= bits(issVal, 19, 0); 4225952Ssaidi@eecs.umich.edu } else { 4235952Ssaidi@eecs.umich.edu value |= issVal; 4245952Ssaidi@eecs.umich.edu } 4255952Ssaidi@eecs.umich.edu tc->setMiscReg(syndrome_reg, value); 4265952Ssaidi@eecs.umich.edu} 4275952Ssaidi@eecs.umich.edu 4285952Ssaidi@eecs.umich.eduvoid 4295952Ssaidi@eecs.umich.eduArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) 4305952Ssaidi@eecs.umich.edu{ 4315952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 4325952Ssaidi@eecs.umich.edu 4335952Ssaidi@eecs.umich.edu if (ArmSystem::highestELIs64(tc)) { // ARMv8 4345952Ssaidi@eecs.umich.edu // Determine source exception level and mode 4355952Ssaidi@eecs.umich.edu fromMode = (OperatingMode) (uint8_t) cpsr.mode; 4365952Ssaidi@eecs.umich.edu fromEL = opModeToEL(fromMode); 4375952Ssaidi@eecs.umich.edu if (opModeIs64(fromMode)) 4385952Ssaidi@eecs.umich.edu from64 = true; 4395952Ssaidi@eecs.umich.edu 4405952Ssaidi@eecs.umich.edu // Determine target exception level 4415952Ssaidi@eecs.umich.edu if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc)) 4425952Ssaidi@eecs.umich.edu toEL = EL3; 4435952Ssaidi@eecs.umich.edu else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc)) 4445952Ssaidi@eecs.umich.edu toEL = EL2; 4455952Ssaidi@eecs.umich.edu else 4465952Ssaidi@eecs.umich.edu toEL = opModeToEL(nextMode()); 4475952Ssaidi@eecs.umich.edu if (fromEL > toEL) 4485952Ssaidi@eecs.umich.edu toEL = fromEL; 4495952Ssaidi@eecs.umich.edu 4505952Ssaidi@eecs.umich.edu if (toEL == ArmSystem::highestEL(tc) || ELIs64(tc, toEL)) { 4515952Ssaidi@eecs.umich.edu // Invoke exception handler in AArch64 state 4525952Ssaidi@eecs.umich.edu to64 = true; 4535952Ssaidi@eecs.umich.edu invoke64(tc, inst); 4545952Ssaidi@eecs.umich.edu return; 4555952Ssaidi@eecs.umich.edu } 4565952Ssaidi@eecs.umich.edu } 4575952Ssaidi@eecs.umich.edu 4585952Ssaidi@eecs.umich.edu // ARMv7 (ARM ARM issue C B1.9) 4595952Ssaidi@eecs.umich.edu 4605952Ssaidi@eecs.umich.edu bool have_security = ArmSystem::haveSecurity(tc); 4615952Ssaidi@eecs.umich.edu bool have_virtualization = ArmSystem::haveVirtualization(tc); 4625952Ssaidi@eecs.umich.edu 4635952Ssaidi@eecs.umich.edu FaultBase::invoke(tc); 4645952Ssaidi@eecs.umich.edu if (!FullSystem) 4655952Ssaidi@eecs.umich.edu return; 4665952Ssaidi@eecs.umich.edu countStat()++; 4675952Ssaidi@eecs.umich.edu 4685952Ssaidi@eecs.umich.edu SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); 4695952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscReg(MISCREG_SCR); 4705952Ssaidi@eecs.umich.edu CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR); 4715952Ssaidi@eecs.umich.edu saved_cpsr.nz = tc->readCCReg(CCREG_NZ); 4725952Ssaidi@eecs.umich.edu saved_cpsr.c = tc->readCCReg(CCREG_C); 4735952Ssaidi@eecs.umich.edu saved_cpsr.v = tc->readCCReg(CCREG_V); 4745952Ssaidi@eecs.umich.edu saved_cpsr.ge = tc->readCCReg(CCREG_GE); 4755952Ssaidi@eecs.umich.edu 4765952Ssaidi@eecs.umich.edu Addr curPc M5_VAR_USED = tc->pcState().pc(); 4775952Ssaidi@eecs.umich.edu ITSTATE it = tc->pcState().itstate(); 4785952Ssaidi@eecs.umich.edu saved_cpsr.it2 = it.top6; 4795952Ssaidi@eecs.umich.edu saved_cpsr.it1 = it.bottom2; 4805952Ssaidi@eecs.umich.edu 4815952Ssaidi@eecs.umich.edu // if we have a valid instruction then use it to annotate this fault with 4825952Ssaidi@eecs.umich.edu // extra information. This is used to generate the correct fault syndrome 4835952Ssaidi@eecs.umich.edu // information 4845952Ssaidi@eecs.umich.edu if (inst) { 4855952Ssaidi@eecs.umich.edu ArmStaticInst *armInst = reinterpret_cast<ArmStaticInst *>(inst.get()); 4865952Ssaidi@eecs.umich.edu armInst->annotateFault(this); 4875952Ssaidi@eecs.umich.edu } 4885952Ssaidi@eecs.umich.edu 4895952Ssaidi@eecs.umich.edu if (have_security && routeToMonitor(tc)) 4905952Ssaidi@eecs.umich.edu cpsr.mode = MODE_MON; 4915952Ssaidi@eecs.umich.edu else if (have_virtualization && routeToHyp(tc)) 4925952Ssaidi@eecs.umich.edu cpsr.mode = MODE_HYP; 4935952Ssaidi@eecs.umich.edu else 4945952Ssaidi@eecs.umich.edu cpsr.mode = nextMode(); 4955952Ssaidi@eecs.umich.edu 4965952Ssaidi@eecs.umich.edu // Ensure Secure state if initially in Monitor mode 4975952Ssaidi@eecs.umich.edu if (have_security && saved_cpsr.mode == MODE_MON) { 4985952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 4995952Ssaidi@eecs.umich.edu if (scr.ns) { 5005952Ssaidi@eecs.umich.edu scr.ns = 0; 5015952Ssaidi@eecs.umich.edu tc->setMiscRegNoEffect(MISCREG_SCR, scr); 5025952Ssaidi@eecs.umich.edu } 5035952Ssaidi@eecs.umich.edu } 5045952Ssaidi@eecs.umich.edu 5055952Ssaidi@eecs.umich.edu // some bits are set differently if we have been routed to hyp mode 5065952Ssaidi@eecs.umich.edu if (cpsr.mode == MODE_HYP) { 5075952Ssaidi@eecs.umich.edu SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR); 5085952Ssaidi@eecs.umich.edu cpsr.t = hsctlr.te; 5095952Ssaidi@eecs.umich.edu cpsr.e = hsctlr.ee; 5105952Ssaidi@eecs.umich.edu if (!scr.ea) {cpsr.a = 1;} 5115952Ssaidi@eecs.umich.edu if (!scr.fiq) {cpsr.f = 1;} 5125952Ssaidi@eecs.umich.edu if (!scr.irq) {cpsr.i = 1;} 5135952Ssaidi@eecs.umich.edu } else if (cpsr.mode == MODE_MON) { 5145952Ssaidi@eecs.umich.edu // Special case handling when entering monitor mode 5155952Ssaidi@eecs.umich.edu cpsr.t = sctlr.te; 5165952Ssaidi@eecs.umich.edu cpsr.e = sctlr.ee; 5175952Ssaidi@eecs.umich.edu cpsr.a = 1; 5185952Ssaidi@eecs.umich.edu cpsr.f = 1; 5195952Ssaidi@eecs.umich.edu cpsr.i = 1; 5205952Ssaidi@eecs.umich.edu } else { 5215952Ssaidi@eecs.umich.edu cpsr.t = sctlr.te; 5225952Ssaidi@eecs.umich.edu cpsr.e = sctlr.ee; 5235952Ssaidi@eecs.umich.edu 5245952Ssaidi@eecs.umich.edu // The *Disable functions are virtual and different per fault 5255952Ssaidi@eecs.umich.edu cpsr.a = cpsr.a | abortDisable(tc); 5265952Ssaidi@eecs.umich.edu cpsr.f = cpsr.f | fiqDisable(tc); 5275952Ssaidi@eecs.umich.edu cpsr.i = 1; 5285952Ssaidi@eecs.umich.edu } 5295952Ssaidi@eecs.umich.edu cpsr.it1 = cpsr.it2 = 0; 5305952Ssaidi@eecs.umich.edu cpsr.j = 0; 5315952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_CPSR, cpsr); 5325952Ssaidi@eecs.umich.edu 5335952Ssaidi@eecs.umich.edu // Make sure mailbox sets to one always 5345952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_SEV_MAILBOX, 1); 5355952Ssaidi@eecs.umich.edu 5365952Ssaidi@eecs.umich.edu // Clear the exclusive monitor 5375952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_LOCKFLAG, 0); 5385952Ssaidi@eecs.umich.edu 5395952Ssaidi@eecs.umich.edu if (cpsr.mode == MODE_HYP) { 5405952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_ELR_HYP, curPc + 5415952Ssaidi@eecs.umich.edu (saved_cpsr.t ? thumbPcOffset(true) : armPcOffset(true))); 5425952Ssaidi@eecs.umich.edu } else { 5435952Ssaidi@eecs.umich.edu tc->setIntReg(INTREG_LR, curPc + 5445952Ssaidi@eecs.umich.edu (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false))); 5455952Ssaidi@eecs.umich.edu } 5465952Ssaidi@eecs.umich.edu 5475952Ssaidi@eecs.umich.edu switch (cpsr.mode) { 5485952Ssaidi@eecs.umich.edu case MODE_FIQ: 5495952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr); 5505952Ssaidi@eecs.umich.edu break; 5515952Ssaidi@eecs.umich.edu case MODE_IRQ: 5525952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr); 5535952Ssaidi@eecs.umich.edu break; 5545952Ssaidi@eecs.umich.edu case MODE_SVC: 5555952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr); 5565952Ssaidi@eecs.umich.edu break; 5575952Ssaidi@eecs.umich.edu case MODE_MON: 5585952Ssaidi@eecs.umich.edu assert(have_security); 5595952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr); 5605952Ssaidi@eecs.umich.edu break; 5615952Ssaidi@eecs.umich.edu case MODE_ABORT: 5625952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr); 5635952Ssaidi@eecs.umich.edu break; 5645952Ssaidi@eecs.umich.edu case MODE_UNDEFINED: 5655952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr); 5665952Ssaidi@eecs.umich.edu if (ec(tc) != EC_UNKNOWN) 5675952Ssaidi@eecs.umich.edu setSyndrome(tc, MISCREG_HSR); 5685952Ssaidi@eecs.umich.edu break; 5695952Ssaidi@eecs.umich.edu case MODE_HYP: 5705952Ssaidi@eecs.umich.edu assert(have_virtualization); 5715952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr); 5725952Ssaidi@eecs.umich.edu setSyndrome(tc, MISCREG_HSR); 5735952Ssaidi@eecs.umich.edu break; 5745952Ssaidi@eecs.umich.edu default: 5755952Ssaidi@eecs.umich.edu panic("unknown Mode\n"); 5765952Ssaidi@eecs.umich.edu } 5775952Ssaidi@eecs.umich.edu 5785952Ssaidi@eecs.umich.edu Addr newPc = getVector(tc); 5795952Ssaidi@eecs.umich.edu DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n", 5805952Ssaidi@eecs.umich.edu name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc); 5815952Ssaidi@eecs.umich.edu PCState pc(newPc); 5825952Ssaidi@eecs.umich.edu pc.thumb(cpsr.t); 5835952Ssaidi@eecs.umich.edu pc.nextThumb(pc.thumb()); 5845952Ssaidi@eecs.umich.edu pc.jazelle(cpsr.j); 5855952Ssaidi@eecs.umich.edu pc.nextJazelle(pc.jazelle()); 5865952Ssaidi@eecs.umich.edu pc.aarch64(!cpsr.width); 5875952Ssaidi@eecs.umich.edu pc.nextAArch64(!cpsr.width); 5885952Ssaidi@eecs.umich.edu tc->pcState(pc); 5895952Ssaidi@eecs.umich.edu} 5905952Ssaidi@eecs.umich.edu 5915952Ssaidi@eecs.umich.eduvoid 5925952Ssaidi@eecs.umich.eduArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst) 5935952Ssaidi@eecs.umich.edu{ 5945952Ssaidi@eecs.umich.edu // Determine actual misc. register indices for ELR_ELx and SPSR_ELx 5955952Ssaidi@eecs.umich.edu MiscRegIndex elr_idx, spsr_idx; 5965952Ssaidi@eecs.umich.edu switch (toEL) { 5975952Ssaidi@eecs.umich.edu case EL1: 5985952Ssaidi@eecs.umich.edu elr_idx = MISCREG_ELR_EL1; 5995952Ssaidi@eecs.umich.edu spsr_idx = MISCREG_SPSR_EL1; 6005952Ssaidi@eecs.umich.edu break; 6015952Ssaidi@eecs.umich.edu case EL2: 6025952Ssaidi@eecs.umich.edu assert(ArmSystem::haveVirtualization(tc)); 6035952Ssaidi@eecs.umich.edu elr_idx = MISCREG_ELR_EL2; 6045952Ssaidi@eecs.umich.edu spsr_idx = MISCREG_SPSR_EL2; 6055952Ssaidi@eecs.umich.edu break; 6065952Ssaidi@eecs.umich.edu case EL3: 6075952Ssaidi@eecs.umich.edu assert(ArmSystem::haveSecurity(tc)); 6085952Ssaidi@eecs.umich.edu elr_idx = MISCREG_ELR_EL3; 6095952Ssaidi@eecs.umich.edu spsr_idx = MISCREG_SPSR_EL3; 6105952Ssaidi@eecs.umich.edu break; 6115952Ssaidi@eecs.umich.edu default: 6125952Ssaidi@eecs.umich.edu panic("Invalid target exception level"); 6135952Ssaidi@eecs.umich.edu break; 6145952Ssaidi@eecs.umich.edu } 6155952Ssaidi@eecs.umich.edu 6165952Ssaidi@eecs.umich.edu // Save process state into SPSR_ELx 6175952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 6185952Ssaidi@eecs.umich.edu CPSR spsr = cpsr; 6195952Ssaidi@eecs.umich.edu spsr.nz = tc->readCCReg(CCREG_NZ); 6205952Ssaidi@eecs.umich.edu spsr.c = tc->readCCReg(CCREG_C); 6215952Ssaidi@eecs.umich.edu spsr.v = tc->readCCReg(CCREG_V); 6225952Ssaidi@eecs.umich.edu if (from64) { 6235952Ssaidi@eecs.umich.edu // Force some bitfields to 0 6245952Ssaidi@eecs.umich.edu spsr.q = 0; 6255952Ssaidi@eecs.umich.edu spsr.it1 = 0; 6265952Ssaidi@eecs.umich.edu spsr.j = 0; 6275952Ssaidi@eecs.umich.edu spsr.res0_23_22 = 0; 6285952Ssaidi@eecs.umich.edu spsr.ge = 0; 6295952Ssaidi@eecs.umich.edu spsr.it2 = 0; 6305952Ssaidi@eecs.umich.edu spsr.t = 0; 6315952Ssaidi@eecs.umich.edu } else { 6325952Ssaidi@eecs.umich.edu spsr.ge = tc->readCCReg(CCREG_GE); 6335952Ssaidi@eecs.umich.edu ITSTATE it = tc->pcState().itstate(); 6345952Ssaidi@eecs.umich.edu spsr.it2 = it.top6; 6355952Ssaidi@eecs.umich.edu spsr.it1 = it.bottom2; 6365952Ssaidi@eecs.umich.edu // Force some bitfields to 0 6375952Ssaidi@eecs.umich.edu spsr.res0_23_22 = 0; 6385952Ssaidi@eecs.umich.edu spsr.ss = 0; 6395952Ssaidi@eecs.umich.edu } 6405952Ssaidi@eecs.umich.edu tc->setMiscReg(spsr_idx, spsr); 6415952Ssaidi@eecs.umich.edu 6425952Ssaidi@eecs.umich.edu // Save preferred return address into ELR_ELx 6435952Ssaidi@eecs.umich.edu Addr curr_pc = tc->pcState().pc(); 6445952Ssaidi@eecs.umich.edu Addr ret_addr = curr_pc; 6455952Ssaidi@eecs.umich.edu if (from64) 6465952Ssaidi@eecs.umich.edu ret_addr += armPcElrOffset(); 6475952Ssaidi@eecs.umich.edu else 6485952Ssaidi@eecs.umich.edu ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset(); 6495952Ssaidi@eecs.umich.edu tc->setMiscReg(elr_idx, ret_addr); 6505952Ssaidi@eecs.umich.edu 6515952Ssaidi@eecs.umich.edu // Update process state 6525952Ssaidi@eecs.umich.edu OperatingMode64 mode = 0; 6535952Ssaidi@eecs.umich.edu mode.spX = 1; 6545952Ssaidi@eecs.umich.edu mode.el = toEL; 6555952Ssaidi@eecs.umich.edu mode.width = 0; 6565952Ssaidi@eecs.umich.edu cpsr.mode = mode; 6575952Ssaidi@eecs.umich.edu cpsr.daif = 0xf; 6585952Ssaidi@eecs.umich.edu cpsr.il = 0; 6595952Ssaidi@eecs.umich.edu cpsr.ss = 0; 6605952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_CPSR, cpsr); 6615952Ssaidi@eecs.umich.edu 6625952Ssaidi@eecs.umich.edu // Set PC to start of exception handler 6635952Ssaidi@eecs.umich.edu Addr new_pc = purifyTaggedAddr(getVector64(tc), tc, toEL); 6645952Ssaidi@eecs.umich.edu DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x " 6655952Ssaidi@eecs.umich.edu "elr:%#x newVec: %#x\n", name(), cpsr, curr_pc, ret_addr, new_pc); 6665952Ssaidi@eecs.umich.edu PCState pc(new_pc); 6675952Ssaidi@eecs.umich.edu pc.aarch64(!cpsr.width); 6685952Ssaidi@eecs.umich.edu pc.nextAArch64(!cpsr.width); 6695952Ssaidi@eecs.umich.edu tc->pcState(pc); 6705952Ssaidi@eecs.umich.edu 6715952Ssaidi@eecs.umich.edu // If we have a valid instruction then use it to annotate this fault with 6725952Ssaidi@eecs.umich.edu // extra information. This is used to generate the correct fault syndrome 6735952Ssaidi@eecs.umich.edu // information 6745952Ssaidi@eecs.umich.edu if (inst) 6755952Ssaidi@eecs.umich.edu reinterpret_cast<ArmStaticInst *>(inst.get())->annotateFault(this); 6765952Ssaidi@eecs.umich.edu // Save exception syndrome 6775952Ssaidi@eecs.umich.edu if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ)) 6785952Ssaidi@eecs.umich.edu setSyndrome(tc, getSyndromeReg64()); 6795952Ssaidi@eecs.umich.edu} 6805952Ssaidi@eecs.umich.edu 6815952Ssaidi@eecs.umich.eduvoid 6825952Ssaidi@eecs.umich.eduReset::invoke(ThreadContext *tc, const StaticInstPtr &inst) 6835952Ssaidi@eecs.umich.edu{ 6845952Ssaidi@eecs.umich.edu if (FullSystem) { 6855952Ssaidi@eecs.umich.edu tc->getCpuPtr()->clearInterrupts(tc->threadId()); 6865952Ssaidi@eecs.umich.edu tc->clearArchRegs(); 6875952Ssaidi@eecs.umich.edu } 6885952Ssaidi@eecs.umich.edu if (!ArmSystem::highestELIs64(tc)) { 6895952Ssaidi@eecs.umich.edu ArmFault::invoke(tc, inst); 6905952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_VMPIDR, 6915952Ssaidi@eecs.umich.edu getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc)); 6925952Ssaidi@eecs.umich.edu 6935952Ssaidi@eecs.umich.edu // Unless we have SMC code to get us there, boot in HYP! 6945952Ssaidi@eecs.umich.edu if (ArmSystem::haveVirtualization(tc) && 6955952Ssaidi@eecs.umich.edu !ArmSystem::haveSecurity(tc)) { 6965952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 6975952Ssaidi@eecs.umich.edu cpsr.mode = MODE_HYP; 6985952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_CPSR, cpsr); 6995952Ssaidi@eecs.umich.edu } 7005952Ssaidi@eecs.umich.edu } else { 7017823Ssteve.reinhardt@amd.com // Advance the PC to the IMPLEMENTATION DEFINED reset value 7025952Ssaidi@eecs.umich.edu PCState pc = ArmSystem::resetAddr64(tc); 7035952Ssaidi@eecs.umich.edu pc.aarch64(true); 7047823Ssteve.reinhardt@amd.com pc.nextAArch64(true); 7055952Ssaidi@eecs.umich.edu tc->pcState(pc); 7065952Ssaidi@eecs.umich.edu } 7075952Ssaidi@eecs.umich.edu} 7085952Ssaidi@eecs.umich.edu 7095952Ssaidi@eecs.umich.eduvoid 7105952Ssaidi@eecs.umich.eduUndefinedInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst) 7115952Ssaidi@eecs.umich.edu{ 7125952Ssaidi@eecs.umich.edu if (FullSystem) { 7135952Ssaidi@eecs.umich.edu ArmFault::invoke(tc, inst); 7145952Ssaidi@eecs.umich.edu return; 7155952Ssaidi@eecs.umich.edu } 7165952Ssaidi@eecs.umich.edu 7175952Ssaidi@eecs.umich.edu // If the mnemonic isn't defined this has to be an unknown instruction. 7185952Ssaidi@eecs.umich.edu assert(unknown || mnemonic != NULL); 7195952Ssaidi@eecs.umich.edu if (disabled) { 7205952Ssaidi@eecs.umich.edu panic("Attempted to execute disabled instruction " 7215952Ssaidi@eecs.umich.edu "'%s' (inst 0x%08x)", mnemonic, machInst); 7225952Ssaidi@eecs.umich.edu } else if (unknown) { 7235952Ssaidi@eecs.umich.edu panic("Attempted to execute unknown instruction (inst 0x%08x)", 7245952Ssaidi@eecs.umich.edu machInst); 7255952Ssaidi@eecs.umich.edu } else { 7265952Ssaidi@eecs.umich.edu panic("Attempted to execute unimplemented instruction " 7275952Ssaidi@eecs.umich.edu "'%s' (inst 0x%08x)", mnemonic, machInst); 7285952Ssaidi@eecs.umich.edu } 7295952Ssaidi@eecs.umich.edu} 7305952Ssaidi@eecs.umich.edu 7315952Ssaidi@eecs.umich.edubool 7325952Ssaidi@eecs.umich.eduUndefinedInstruction::routeToHyp(ThreadContext *tc) const 7335952Ssaidi@eecs.umich.edu{ 7345952Ssaidi@eecs.umich.edu bool toHyp; 7355952Ssaidi@eecs.umich.edu 7365952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 7375952Ssaidi@eecs.umich.edu HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 7385952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 7395952Ssaidi@eecs.umich.edu 7405952Ssaidi@eecs.umich.edu // if in Hyp mode then stay in Hyp mode 7415952Ssaidi@eecs.umich.edu toHyp = scr.ns && (cpsr.mode == MODE_HYP); 7425952Ssaidi@eecs.umich.edu // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector 7435952Ssaidi@eecs.umich.edu toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER); 7445952Ssaidi@eecs.umich.edu return toHyp; 7455952Ssaidi@eecs.umich.edu} 7465952Ssaidi@eecs.umich.edu 7475952Ssaidi@eecs.umich.eduuint32_t 7485952Ssaidi@eecs.umich.eduUndefinedInstruction::iss() const 7495952Ssaidi@eecs.umich.edu{ 7505952Ssaidi@eecs.umich.edu if (overrideEc == EC_INVALID) 7515952Ssaidi@eecs.umich.edu return issRaw; 7525952Ssaidi@eecs.umich.edu 7535952Ssaidi@eecs.umich.edu uint32_t new_iss = 0; 7545952Ssaidi@eecs.umich.edu uint32_t op0, op1, op2, CRn, CRm, Rt, dir; 7555952Ssaidi@eecs.umich.edu 7565952Ssaidi@eecs.umich.edu dir = bits(machInst, 21, 21); 7575952Ssaidi@eecs.umich.edu op0 = bits(machInst, 20, 19); 7585952Ssaidi@eecs.umich.edu op1 = bits(machInst, 18, 16); 7595952Ssaidi@eecs.umich.edu CRn = bits(machInst, 15, 12); 7605952Ssaidi@eecs.umich.edu CRm = bits(machInst, 11, 8); 7615952Ssaidi@eecs.umich.edu op2 = bits(machInst, 7, 5); 7625952Ssaidi@eecs.umich.edu Rt = bits(machInst, 4, 0); 7635952Ssaidi@eecs.umich.edu 7645952Ssaidi@eecs.umich.edu new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 | 7655952Ssaidi@eecs.umich.edu Rt << 5 | CRm << 1 | dir; 7665952Ssaidi@eecs.umich.edu 7675952Ssaidi@eecs.umich.edu return new_iss; 7685952Ssaidi@eecs.umich.edu} 7695952Ssaidi@eecs.umich.edu 7705952Ssaidi@eecs.umich.eduvoid 7715952Ssaidi@eecs.umich.eduSupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst) 7725952Ssaidi@eecs.umich.edu{ 7735952Ssaidi@eecs.umich.edu if (FullSystem) { 7745952Ssaidi@eecs.umich.edu ArmFault::invoke(tc, inst); 7755952Ssaidi@eecs.umich.edu return; 7765952Ssaidi@eecs.umich.edu } 7775952Ssaidi@eecs.umich.edu 7785952Ssaidi@eecs.umich.edu // As of now, there isn't a 32 bit thumb version of this instruction. 7795952Ssaidi@eecs.umich.edu assert(!machInst.bigThumb); 7805952Ssaidi@eecs.umich.edu uint32_t callNum; 7815952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 7825952Ssaidi@eecs.umich.edu OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode; 7835952Ssaidi@eecs.umich.edu if (opModeIs64(mode)) 7845952Ssaidi@eecs.umich.edu callNum = tc->readIntReg(INTREG_X8); 7855952Ssaidi@eecs.umich.edu else 7865952Ssaidi@eecs.umich.edu callNum = tc->readIntReg(INTREG_R7); 7875952Ssaidi@eecs.umich.edu Fault fault; 7885952Ssaidi@eecs.umich.edu tc->syscall(callNum, &fault); 7895952Ssaidi@eecs.umich.edu 7905952Ssaidi@eecs.umich.edu // Advance the PC since that won't happen automatically. 7915952Ssaidi@eecs.umich.edu PCState pc = tc->pcState(); 7925952Ssaidi@eecs.umich.edu assert(inst); 7935952Ssaidi@eecs.umich.edu inst->advancePC(pc); 7945952Ssaidi@eecs.umich.edu tc->pcState(pc); 7955952Ssaidi@eecs.umich.edu} 7965952Ssaidi@eecs.umich.edu 7975952Ssaidi@eecs.umich.edubool 7985952Ssaidi@eecs.umich.eduSupervisorCall::routeToHyp(ThreadContext *tc) const 7995952Ssaidi@eecs.umich.edu{ 8005952Ssaidi@eecs.umich.edu bool toHyp; 8015952Ssaidi@eecs.umich.edu 8025952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 8035952Ssaidi@eecs.umich.edu HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 8045952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 8055952Ssaidi@eecs.umich.edu 8065952Ssaidi@eecs.umich.edu // if in Hyp mode then stay in Hyp mode 8075952Ssaidi@eecs.umich.edu toHyp = scr.ns && (cpsr.mode == MODE_HYP); 8085952Ssaidi@eecs.umich.edu // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector 8095952Ssaidi@eecs.umich.edu toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER); 8105952Ssaidi@eecs.umich.edu return toHyp; 8115952Ssaidi@eecs.umich.edu} 8125952Ssaidi@eecs.umich.edu 8135952Ssaidi@eecs.umich.eduExceptionClass 8145952Ssaidi@eecs.umich.eduSupervisorCall::ec(ThreadContext *tc) const 8155952Ssaidi@eecs.umich.edu{ 8165952Ssaidi@eecs.umich.edu return (overrideEc != EC_INVALID) ? overrideEc : 8175952Ssaidi@eecs.umich.edu (from64 ? EC_SVC_64 : vals.ec); 8185952Ssaidi@eecs.umich.edu} 8195952Ssaidi@eecs.umich.edu 8205952Ssaidi@eecs.umich.eduuint32_t 8215952Ssaidi@eecs.umich.eduSupervisorCall::iss() const 8225952Ssaidi@eecs.umich.edu{ 8235952Ssaidi@eecs.umich.edu // Even if we have a 24 bit imm from an arm32 instruction then we only use 8245952Ssaidi@eecs.umich.edu // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC). 82510470Sandreas.hansson@arm.com return issRaw & 0xFFFF; 8267823Ssteve.reinhardt@amd.com} 8275952Ssaidi@eecs.umich.edu 8285952Ssaidi@eecs.umich.eduuint32_t 8295952Ssaidi@eecs.umich.eduSecureMonitorCall::iss() const 8305952Ssaidi@eecs.umich.edu{ 8315952Ssaidi@eecs.umich.edu if (from64) 8325952Ssaidi@eecs.umich.edu return bits(machInst, 20, 5); 8335952Ssaidi@eecs.umich.edu return 0; 8345952Ssaidi@eecs.umich.edu} 8355952Ssaidi@eecs.umich.edu 8365952Ssaidi@eecs.umich.eduExceptionClass 8375952Ssaidi@eecs.umich.eduUndefinedInstruction::ec(ThreadContext *tc) const 8385952Ssaidi@eecs.umich.edu{ 8395952Ssaidi@eecs.umich.edu return (overrideEc != EC_INVALID) ? overrideEc : vals.ec; 8405952Ssaidi@eecs.umich.edu} 8415952Ssaidi@eecs.umich.edu 8425952Ssaidi@eecs.umich.edu 8435952Ssaidi@eecs.umich.eduHypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) : 8445952Ssaidi@eecs.umich.edu ArmFaultVals<HypervisorCall>(_machInst, _imm) 8455952Ssaidi@eecs.umich.edu{} 8465952Ssaidi@eecs.umich.edu 8475952Ssaidi@eecs.umich.eduExceptionClass 8485952Ssaidi@eecs.umich.eduHypervisorCall::ec(ThreadContext *tc) const 8495952Ssaidi@eecs.umich.edu{ 8505952Ssaidi@eecs.umich.edu return from64 ? EC_HVC_64 : vals.ec; 8515952Ssaidi@eecs.umich.edu} 8525952Ssaidi@eecs.umich.edu 8535952Ssaidi@eecs.umich.eduExceptionClass 8545952Ssaidi@eecs.umich.eduHypervisorTrap::ec(ThreadContext *tc) const 8555952Ssaidi@eecs.umich.edu{ 8565952Ssaidi@eecs.umich.edu return (overrideEc != EC_INVALID) ? overrideEc : vals.ec; 8575952Ssaidi@eecs.umich.edu} 8585952Ssaidi@eecs.umich.edu 8595952Ssaidi@eecs.umich.edutemplate<class T> 8605952Ssaidi@eecs.umich.eduFaultOffset 8615952Ssaidi@eecs.umich.eduArmFaultVals<T>::offset(ThreadContext *tc) 8625952Ssaidi@eecs.umich.edu{ 8635952Ssaidi@eecs.umich.edu bool isHypTrap = false; 8645952Ssaidi@eecs.umich.edu 8655952Ssaidi@eecs.umich.edu // Normally we just use the exception vector from the table at the top if 8665952Ssaidi@eecs.umich.edu // this file, however if this exception has caused a transition to hype 8675952Ssaidi@eecs.umich.edu // mode, and its an exception type that would only do this if it has been 8685952Ssaidi@eecs.umich.edu // trapped then we use the hyp trap vector instead of the normal vector 8695952Ssaidi@eecs.umich.edu if (vals.hypTrappable) { 8705952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 8715952Ssaidi@eecs.umich.edu if (cpsr.mode == MODE_HYP) { 8725952Ssaidi@eecs.umich.edu CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP); 8735952Ssaidi@eecs.umich.edu isHypTrap = spsr.mode != MODE_HYP; 8745952Ssaidi@eecs.umich.edu } 8755952Ssaidi@eecs.umich.edu } 8765952Ssaidi@eecs.umich.edu return isHypTrap ? 0x14 : vals.offset; 8775952Ssaidi@eecs.umich.edu} 8785952Ssaidi@eecs.umich.edu 8795952Ssaidi@eecs.umich.edu// void 8805952Ssaidi@eecs.umich.edu// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx) 8815952Ssaidi@eecs.umich.edu// { 8825952Ssaidi@eecs.umich.edu// ESR esr = 0; 8835952Ssaidi@eecs.umich.edu// esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32; 8845952Ssaidi@eecs.umich.edu// esr.il = !machInst.thumb; 8855952Ssaidi@eecs.umich.edu// if (machInst.aarch64) 8865952Ssaidi@eecs.umich.edu// esr.imm16 = bits(machInst.instBits, 20, 5); 8875952Ssaidi@eecs.umich.edu// else if (machInst.thumb) 8885952Ssaidi@eecs.umich.edu// esr.imm16 = bits(machInst.instBits, 7, 0); 8895952Ssaidi@eecs.umich.edu// else 8905952Ssaidi@eecs.umich.edu// esr.imm16 = bits(machInst.instBits, 15, 0); 8915952Ssaidi@eecs.umich.edu// tc->setMiscReg(esr_idx, esr); 8925952Ssaidi@eecs.umich.edu// } 8935952Ssaidi@eecs.umich.edu 8945952Ssaidi@eecs.umich.eduvoid 8955952Ssaidi@eecs.umich.eduSecureMonitorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst) 8965952Ssaidi@eecs.umich.edu{ 8975952Ssaidi@eecs.umich.edu if (FullSystem) { 8985952Ssaidi@eecs.umich.edu ArmFault::invoke(tc, inst); 8995952Ssaidi@eecs.umich.edu return; 9005952Ssaidi@eecs.umich.edu } 9015952Ssaidi@eecs.umich.edu} 9025952Ssaidi@eecs.umich.edu 9035952Ssaidi@eecs.umich.eduExceptionClass 9045952Ssaidi@eecs.umich.eduSecureMonitorCall::ec(ThreadContext *tc) const 9055952Ssaidi@eecs.umich.edu{ 9065952Ssaidi@eecs.umich.edu return (from64 ? EC_SMC_64 : vals.ec); 9075952Ssaidi@eecs.umich.edu} 9085952Ssaidi@eecs.umich.edu 9095952Ssaidi@eecs.umich.eduExceptionClass 9105952Ssaidi@eecs.umich.eduSupervisorTrap::ec(ThreadContext *tc) const 9115952Ssaidi@eecs.umich.edu{ 9125952Ssaidi@eecs.umich.edu return (overrideEc != EC_INVALID) ? overrideEc : vals.ec; 9135952Ssaidi@eecs.umich.edu} 9145952Ssaidi@eecs.umich.edu 9155952Ssaidi@eecs.umich.eduExceptionClass 9165952Ssaidi@eecs.umich.eduSecureMonitorTrap::ec(ThreadContext *tc) const 9175952Ssaidi@eecs.umich.edu{ 9185952Ssaidi@eecs.umich.edu return (overrideEc != EC_INVALID) ? overrideEc : 9195952Ssaidi@eecs.umich.edu (from64 ? EC_SMC_64 : vals.ec); 9205952Ssaidi@eecs.umich.edu} 9215952Ssaidi@eecs.umich.edu 9225952Ssaidi@eecs.umich.edutemplate<class T> 9235952Ssaidi@eecs.umich.eduvoid 9245952Ssaidi@eecs.umich.eduAbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst) 9255952Ssaidi@eecs.umich.edu{ 9265952Ssaidi@eecs.umich.edu if (tranMethod == ArmFault::UnknownTran) { 9275952Ssaidi@eecs.umich.edu tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran 9285952Ssaidi@eecs.umich.edu : ArmFault::VmsaTran; 9295952Ssaidi@eecs.umich.edu 9305952Ssaidi@eecs.umich.edu if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) { 9315952Ssaidi@eecs.umich.edu // See ARM ARM B3-1416 9325952Ssaidi@eecs.umich.edu bool override_LPAE = false; 9335952Ssaidi@eecs.umich.edu TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S); 9345952Ssaidi@eecs.umich.edu TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS); 9355952Ssaidi@eecs.umich.edu if (ttbcr_s.eae) { 9365952Ssaidi@eecs.umich.edu override_LPAE = true; 9375952Ssaidi@eecs.umich.edu } else { 9385952Ssaidi@eecs.umich.edu // Unimplemented code option, not seen in testing. May need 9395952Ssaidi@eecs.umich.edu // extension according to the manual exceprt above. 9405952Ssaidi@eecs.umich.edu DPRINTF(Faults, "Warning: Incomplete translation method " 9415952Ssaidi@eecs.umich.edu "override detected.\n"); 9425952Ssaidi@eecs.umich.edu } 9435952Ssaidi@eecs.umich.edu if (override_LPAE) 9445952Ssaidi@eecs.umich.edu tranMethod = ArmFault::LpaeTran; 9455952Ssaidi@eecs.umich.edu } 9465952Ssaidi@eecs.umich.edu } 9475952Ssaidi@eecs.umich.edu 9485952Ssaidi@eecs.umich.edu if (source == ArmFault::AsynchronousExternalAbort) { 9495952Ssaidi@eecs.umich.edu tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0); 9505952Ssaidi@eecs.umich.edu } 9515952Ssaidi@eecs.umich.edu // Get effective fault source encoding 9525952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 9535952Ssaidi@eecs.umich.edu FSR fsr = getFsr(tc); 9545952Ssaidi@eecs.umich.edu 9555952Ssaidi@eecs.umich.edu // source must be determined BEFORE invoking generic routines which will 9565952Ssaidi@eecs.umich.edu // try to set hsr etc. and are based upon source! 9575952Ssaidi@eecs.umich.edu ArmFaultVals<T>::invoke(tc, inst); 9585952Ssaidi@eecs.umich.edu 9595952Ssaidi@eecs.umich.edu if (!this->to64) { // AArch32 9605952Ssaidi@eecs.umich.edu if (cpsr.mode == MODE_HYP) { 9615952Ssaidi@eecs.umich.edu tc->setMiscReg(T::HFarIndex, faultAddr); 9625952Ssaidi@eecs.umich.edu } else if (stage2) { 9635952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf); 9645952Ssaidi@eecs.umich.edu tc->setMiscReg(T::HFarIndex, OVAddr); 9655952Ssaidi@eecs.umich.edu } else { 9665952Ssaidi@eecs.umich.edu tc->setMiscReg(T::FsrIndex, fsr); 9675952Ssaidi@eecs.umich.edu tc->setMiscReg(T::FarIndex, faultAddr); 9685952Ssaidi@eecs.umich.edu } 9695952Ssaidi@eecs.umich.edu DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\ 9705952Ssaidi@eecs.umich.edu "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod); 9715952Ssaidi@eecs.umich.edu } else { // AArch64 9725952Ssaidi@eecs.umich.edu // Set the FAR register. Nothing else to do if we are in AArch64 state 9735952Ssaidi@eecs.umich.edu // because the syndrome register has already been set inside invoke64() 9745952Ssaidi@eecs.umich.edu if (stage2) { 9755952Ssaidi@eecs.umich.edu // stage 2 fault, set HPFAR_EL2 to the faulting IPA 9765952Ssaidi@eecs.umich.edu // and FAR_EL2 to the Original VA 9775952Ssaidi@eecs.umich.edu tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr); 9785952Ssaidi@eecs.umich.edu tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4); 9795952Ssaidi@eecs.umich.edu 9805952Ssaidi@eecs.umich.edu DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n", 9815952Ssaidi@eecs.umich.edu OVAddr, faultAddr); 9825952Ssaidi@eecs.umich.edu } else { 9835952Ssaidi@eecs.umich.edu tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr); 9845952Ssaidi@eecs.umich.edu } 9855952Ssaidi@eecs.umich.edu } 9865952Ssaidi@eecs.umich.edu} 9875952Ssaidi@eecs.umich.edu 9885952Ssaidi@eecs.umich.edutemplate<class T> 9895952Ssaidi@eecs.umich.eduFSR 9905952Ssaidi@eecs.umich.eduAbortFault<T>::getFsr(ThreadContext *tc) 9915952Ssaidi@eecs.umich.edu{ 9925952Ssaidi@eecs.umich.edu FSR fsr = 0; 9935952Ssaidi@eecs.umich.edu 9945952Ssaidi@eecs.umich.edu if (((CPSR) tc->readMiscRegNoEffect(MISCREG_CPSR)).width) { 9955952Ssaidi@eecs.umich.edu // AArch32 9965952Ssaidi@eecs.umich.edu assert(tranMethod != ArmFault::UnknownTran); 9975952Ssaidi@eecs.umich.edu if (tranMethod == ArmFault::LpaeTran) { 9985952Ssaidi@eecs.umich.edu srcEncoded = ArmFault::longDescFaultSources[source]; 9995952Ssaidi@eecs.umich.edu fsr.status = srcEncoded; 10005952Ssaidi@eecs.umich.edu fsr.lpae = 1; 10015952Ssaidi@eecs.umich.edu } else { 10025952Ssaidi@eecs.umich.edu srcEncoded = ArmFault::shortDescFaultSources[source]; 10035952Ssaidi@eecs.umich.edu fsr.fsLow = bits(srcEncoded, 3, 0); 10045952Ssaidi@eecs.umich.edu fsr.fsHigh = bits(srcEncoded, 4); 10055952Ssaidi@eecs.umich.edu fsr.domain = static_cast<uint8_t>(domain); 10065952Ssaidi@eecs.umich.edu } 10075952Ssaidi@eecs.umich.edu fsr.wnr = (write ? 1 : 0); 10085952Ssaidi@eecs.umich.edu fsr.ext = 0; 10095952Ssaidi@eecs.umich.edu } else { 10105952Ssaidi@eecs.umich.edu // AArch64 10115952Ssaidi@eecs.umich.edu srcEncoded = ArmFault::aarch64FaultSources[source]; 10125952Ssaidi@eecs.umich.edu } 10135952Ssaidi@eecs.umich.edu if (srcEncoded == ArmFault::FaultSourceInvalid) { 10145952Ssaidi@eecs.umich.edu panic("Invalid fault source\n"); 10155952Ssaidi@eecs.umich.edu } 10165952Ssaidi@eecs.umich.edu return fsr; 10175952Ssaidi@eecs.umich.edu} 10185952Ssaidi@eecs.umich.edu 10195952Ssaidi@eecs.umich.edutemplate<class T> 10205952Ssaidi@eecs.umich.edubool 10215952Ssaidi@eecs.umich.eduAbortFault<T>::abortDisable(ThreadContext *tc) 10225952Ssaidi@eecs.umich.edu{ 10235952Ssaidi@eecs.umich.edu if (ArmSystem::haveSecurity(tc)) { 10245952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 10255952Ssaidi@eecs.umich.edu return (!scr.ns || scr.aw); 10265952Ssaidi@eecs.umich.edu } 10275952Ssaidi@eecs.umich.edu return true; 10285952Ssaidi@eecs.umich.edu} 10295952Ssaidi@eecs.umich.edu 10305952Ssaidi@eecs.umich.edutemplate<class T> 10315952Ssaidi@eecs.umich.eduvoid 10325952Ssaidi@eecs.umich.eduAbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val) 10335952Ssaidi@eecs.umich.edu{ 10345952Ssaidi@eecs.umich.edu switch (id) 10355952Ssaidi@eecs.umich.edu { 10365952Ssaidi@eecs.umich.edu case ArmFault::S1PTW: 10375952Ssaidi@eecs.umich.edu s1ptw = val; 10385952Ssaidi@eecs.umich.edu break; 10395952Ssaidi@eecs.umich.edu case ArmFault::OVA: 10405952Ssaidi@eecs.umich.edu OVAddr = val; 10415952Ssaidi@eecs.umich.edu break; 10425952Ssaidi@eecs.umich.edu 10435952Ssaidi@eecs.umich.edu // Just ignore unknown ID's 10445952Ssaidi@eecs.umich.edu default: 10455952Ssaidi@eecs.umich.edu break; 10465952Ssaidi@eecs.umich.edu } 10475952Ssaidi@eecs.umich.edu} 10485952Ssaidi@eecs.umich.edu 10495952Ssaidi@eecs.umich.edutemplate<class T> 10505952Ssaidi@eecs.umich.eduuint32_t 10515952Ssaidi@eecs.umich.eduAbortFault<T>::iss() const 10525952Ssaidi@eecs.umich.edu{ 10535952Ssaidi@eecs.umich.edu uint32_t val; 10545952Ssaidi@eecs.umich.edu 10555952Ssaidi@eecs.umich.edu val = srcEncoded & 0x3F; 10565952Ssaidi@eecs.umich.edu val |= write << 6; 10575952Ssaidi@eecs.umich.edu val |= s1ptw << 7; 10585952Ssaidi@eecs.umich.edu return (val); 10595952Ssaidi@eecs.umich.edu} 10605952Ssaidi@eecs.umich.edu 10615952Ssaidi@eecs.umich.edutemplate<class T> 10625952Ssaidi@eecs.umich.edubool 10635952Ssaidi@eecs.umich.eduAbortFault<T>::isMMUFault() const 10645952Ssaidi@eecs.umich.edu{ 10655952Ssaidi@eecs.umich.edu // NOTE: Not relying on LL information being aligned to lowest bits here 106610905Sandreas.sandberg@arm.com return 10675952Ssaidi@eecs.umich.edu (source == ArmFault::AlignmentFault) || 10685952Ssaidi@eecs.umich.edu ((source >= ArmFault::TranslationLL) && 10695952Ssaidi@eecs.umich.edu (source < ArmFault::TranslationLL + 4)) || 10705952Ssaidi@eecs.umich.edu ((source >= ArmFault::AccessFlagLL) && 10715952Ssaidi@eecs.umich.edu (source < ArmFault::AccessFlagLL + 4)) || 10725952Ssaidi@eecs.umich.edu ((source >= ArmFault::DomainLL) && 10735952Ssaidi@eecs.umich.edu (source < ArmFault::DomainLL + 4)) || 10745952Ssaidi@eecs.umich.edu ((source >= ArmFault::PermissionLL) && 10755952Ssaidi@eecs.umich.edu (source < ArmFault::PermissionLL + 4)); 10765952Ssaidi@eecs.umich.edu} 10775952Ssaidi@eecs.umich.edu 10785952Ssaidi@eecs.umich.eduExceptionClass 10795952Ssaidi@eecs.umich.eduPrefetchAbort::ec(ThreadContext *tc) const 10805952Ssaidi@eecs.umich.edu{ 10815952Ssaidi@eecs.umich.edu if (to64) { 10825952Ssaidi@eecs.umich.edu // AArch64 10835952Ssaidi@eecs.umich.edu if (toEL == fromEL) 10845952Ssaidi@eecs.umich.edu return EC_PREFETCH_ABORT_CURR_EL; 10855952Ssaidi@eecs.umich.edu else 10865952Ssaidi@eecs.umich.edu return EC_PREFETCH_ABORT_LOWER_EL; 10875952Ssaidi@eecs.umich.edu } else { 10885952Ssaidi@eecs.umich.edu // AArch32 10895952Ssaidi@eecs.umich.edu // Abort faults have different EC codes depending on whether 10905952Ssaidi@eecs.umich.edu // the fault originated within HYP mode, or not. So override 10915952Ssaidi@eecs.umich.edu // the method and add the extra adjustment of the EC value. 10925952Ssaidi@eecs.umich.edu 10935952Ssaidi@eecs.umich.edu ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec; 10945952Ssaidi@eecs.umich.edu 10955952Ssaidi@eecs.umich.edu CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP); 10965952Ssaidi@eecs.umich.edu if (spsr.mode == MODE_HYP) { 10975952Ssaidi@eecs.umich.edu ec = ((ExceptionClass) (((uint32_t) ec) + 1)); 10985952Ssaidi@eecs.umich.edu } 10995952Ssaidi@eecs.umich.edu return ec; 11005952Ssaidi@eecs.umich.edu } 11015952Ssaidi@eecs.umich.edu} 11025952Ssaidi@eecs.umich.edu 11035952Ssaidi@eecs.umich.edubool 11045952Ssaidi@eecs.umich.eduPrefetchAbort::routeToMonitor(ThreadContext *tc) const 11055952Ssaidi@eecs.umich.edu{ 11065952Ssaidi@eecs.umich.edu SCR scr = 0; 11075952Ssaidi@eecs.umich.edu if (from64) 11085952Ssaidi@eecs.umich.edu scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 11095952Ssaidi@eecs.umich.edu else 11105952Ssaidi@eecs.umich.edu scr = tc->readMiscRegNoEffect(MISCREG_SCR); 11115952Ssaidi@eecs.umich.edu 11125952Ssaidi@eecs.umich.edu return scr.ea && !isMMUFault(); 11135952Ssaidi@eecs.umich.edu} 11145952Ssaidi@eecs.umich.edu 11155952Ssaidi@eecs.umich.edubool 11165952Ssaidi@eecs.umich.eduPrefetchAbort::routeToHyp(ThreadContext *tc) const 11175952Ssaidi@eecs.umich.edu{ 11185952Ssaidi@eecs.umich.edu bool toHyp; 11195952Ssaidi@eecs.umich.edu 11205952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 11215952Ssaidi@eecs.umich.edu HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 11225952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 11235952Ssaidi@eecs.umich.edu HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR); 11245952Ssaidi@eecs.umich.edu 11255952Ssaidi@eecs.umich.edu // if in Hyp mode then stay in Hyp mode 11265952Ssaidi@eecs.umich.edu toHyp = scr.ns && (cpsr.mode == MODE_HYP); 11275952Ssaidi@eecs.umich.edu // otherwise, check whether to take to Hyp mode through Hyp Trap vector 11285952Ssaidi@eecs.umich.edu toHyp |= (stage2 || 11295952Ssaidi@eecs.umich.edu ( (source == DebugEvent) && hdcr.tde && (cpsr.mode != MODE_HYP)) || 11305952Ssaidi@eecs.umich.edu ( (source == SynchronousExternalAbort) && hcr.tge && (cpsr.mode == MODE_USER)) 11315952Ssaidi@eecs.umich.edu ) && !inSecureState(tc); 11325952Ssaidi@eecs.umich.edu return toHyp; 11335952Ssaidi@eecs.umich.edu} 11345952Ssaidi@eecs.umich.edu 11355952Ssaidi@eecs.umich.eduExceptionClass 11365952Ssaidi@eecs.umich.eduDataAbort::ec(ThreadContext *tc) const 11375952Ssaidi@eecs.umich.edu{ 11385952Ssaidi@eecs.umich.edu if (to64) { 11395952Ssaidi@eecs.umich.edu // AArch64 11405952Ssaidi@eecs.umich.edu if (source == ArmFault::AsynchronousExternalAbort) { 11415952Ssaidi@eecs.umich.edu panic("Asynchronous External Abort should be handled with " 11425952Ssaidi@eecs.umich.edu "SystemErrors (SErrors)!"); 11435952Ssaidi@eecs.umich.edu } 11445952Ssaidi@eecs.umich.edu if (toEL == fromEL) 11455952Ssaidi@eecs.umich.edu return EC_DATA_ABORT_CURR_EL; 11465952Ssaidi@eecs.umich.edu else 11475952Ssaidi@eecs.umich.edu return EC_DATA_ABORT_LOWER_EL; 11485952Ssaidi@eecs.umich.edu } else { 11495952Ssaidi@eecs.umich.edu // AArch32 11505952Ssaidi@eecs.umich.edu // Abort faults have different EC codes depending on whether 11515952Ssaidi@eecs.umich.edu // the fault originated within HYP mode, or not. So override 11525952Ssaidi@eecs.umich.edu // the method and add the extra adjustment of the EC value. 11535952Ssaidi@eecs.umich.edu 11545952Ssaidi@eecs.umich.edu ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec; 11555952Ssaidi@eecs.umich.edu 11565952Ssaidi@eecs.umich.edu CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP); 11575952Ssaidi@eecs.umich.edu if (spsr.mode == MODE_HYP) { 11585952Ssaidi@eecs.umich.edu ec = ((ExceptionClass) (((uint32_t) ec) + 1)); 11595952Ssaidi@eecs.umich.edu } 11605952Ssaidi@eecs.umich.edu return ec; 11615952Ssaidi@eecs.umich.edu } 11625952Ssaidi@eecs.umich.edu} 11635952Ssaidi@eecs.umich.edu 11645952Ssaidi@eecs.umich.edubool 11655952Ssaidi@eecs.umich.eduDataAbort::routeToMonitor(ThreadContext *tc) const 11665952Ssaidi@eecs.umich.edu{ 11675952Ssaidi@eecs.umich.edu SCR scr = 0; 11685952Ssaidi@eecs.umich.edu if (from64) 11695952Ssaidi@eecs.umich.edu scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 11705952Ssaidi@eecs.umich.edu else 11715952Ssaidi@eecs.umich.edu scr = tc->readMiscRegNoEffect(MISCREG_SCR); 11725952Ssaidi@eecs.umich.edu 11735952Ssaidi@eecs.umich.edu return scr.ea && !isMMUFault(); 11745952Ssaidi@eecs.umich.edu} 11755952Ssaidi@eecs.umich.edu 11765952Ssaidi@eecs.umich.edubool 11775952Ssaidi@eecs.umich.eduDataAbort::routeToHyp(ThreadContext *tc) const 11785952Ssaidi@eecs.umich.edu{ 11795952Ssaidi@eecs.umich.edu bool toHyp; 11805952Ssaidi@eecs.umich.edu 11815952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 11825952Ssaidi@eecs.umich.edu HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 11835952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 11845952Ssaidi@eecs.umich.edu HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR); 11855952Ssaidi@eecs.umich.edu 11865952Ssaidi@eecs.umich.edu // if in Hyp mode then stay in Hyp mode 11875952Ssaidi@eecs.umich.edu toHyp = scr.ns && (cpsr.mode == MODE_HYP); 11885952Ssaidi@eecs.umich.edu // otherwise, check whether to take to Hyp mode through Hyp Trap vector 11895952Ssaidi@eecs.umich.edu toHyp |= (stage2 || 11905952Ssaidi@eecs.umich.edu ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) || 11915952Ssaidi@eecs.umich.edu ((source == DebugEvent) && hdcr.tde) ) 11925952Ssaidi@eecs.umich.edu ) || 11935952Ssaidi@eecs.umich.edu ( (cpsr.mode == MODE_USER) && hcr.tge && 11945952Ssaidi@eecs.umich.edu ((source == AlignmentFault) || 11955952Ssaidi@eecs.umich.edu (source == SynchronousExternalAbort)) 11965952Ssaidi@eecs.umich.edu ) 11975952Ssaidi@eecs.umich.edu ) && !inSecureState(tc); 11985952Ssaidi@eecs.umich.edu return toHyp; 11995952Ssaidi@eecs.umich.edu} 12005952Ssaidi@eecs.umich.edu 12015952Ssaidi@eecs.umich.eduuint32_t 12025952Ssaidi@eecs.umich.eduDataAbort::iss() const 12035952Ssaidi@eecs.umich.edu{ 12045952Ssaidi@eecs.umich.edu uint32_t val; 12055952Ssaidi@eecs.umich.edu 12065952Ssaidi@eecs.umich.edu // Add on the data abort specific fields to the generic abort ISS value 12075952Ssaidi@eecs.umich.edu val = AbortFault<DataAbort>::iss(); 12085952Ssaidi@eecs.umich.edu // ISS is valid if not caused by a stage 1 page table walk, and when taken 12095952Ssaidi@eecs.umich.edu // to AArch64 only when directed to EL2 12105952Ssaidi@eecs.umich.edu if (!s1ptw && (!to64 || toEL == EL2)) { 12115952Ssaidi@eecs.umich.edu val |= isv << 24; 121210905Sandreas.sandberg@arm.com if (isv) { 121310905Sandreas.sandberg@arm.com val |= sas << 22; 12145952Ssaidi@eecs.umich.edu val |= sse << 21; 12155952Ssaidi@eecs.umich.edu val |= srt << 16; 12165952Ssaidi@eecs.umich.edu // AArch64 only. These assignments are safe on AArch32 as well 12175952Ssaidi@eecs.umich.edu // because these vars are initialized to false 12185952Ssaidi@eecs.umich.edu val |= sf << 15; 12195952Ssaidi@eecs.umich.edu val |= ar << 14; 122010905Sandreas.sandberg@arm.com } 12215952Ssaidi@eecs.umich.edu } 12225952Ssaidi@eecs.umich.edu return (val); 12235952Ssaidi@eecs.umich.edu} 122410905Sandreas.sandberg@arm.com 122510905Sandreas.sandberg@arm.comvoid 12265952Ssaidi@eecs.umich.eduDataAbort::annotate(AnnotationIDs id, uint64_t val) 12275952Ssaidi@eecs.umich.edu{ 12285952Ssaidi@eecs.umich.edu AbortFault<DataAbort>::annotate(id, val); 122910905Sandreas.sandberg@arm.com switch (id) 123010905Sandreas.sandberg@arm.com { 12315952Ssaidi@eecs.umich.edu case SAS: 12325952Ssaidi@eecs.umich.edu isv = true; 12335952Ssaidi@eecs.umich.edu sas = val; 12345952Ssaidi@eecs.umich.edu break; 12355952Ssaidi@eecs.umich.edu case SSE: 12365952Ssaidi@eecs.umich.edu isv = true; 123710905Sandreas.sandberg@arm.com sse = val; 123810905Sandreas.sandberg@arm.com break; 12395952Ssaidi@eecs.umich.edu case SRT: 12405952Ssaidi@eecs.umich.edu isv = true; 12415952Ssaidi@eecs.umich.edu srt = val; 12425952Ssaidi@eecs.umich.edu break; 12435952Ssaidi@eecs.umich.edu case SF: 12445952Ssaidi@eecs.umich.edu isv = true; 12455952Ssaidi@eecs.umich.edu sf = val; 124610905Sandreas.sandberg@arm.com break; 124710905Sandreas.sandberg@arm.com case AR: 12485952Ssaidi@eecs.umich.edu isv = true; 12495952Ssaidi@eecs.umich.edu ar = val; 12505952Ssaidi@eecs.umich.edu break; 12515952Ssaidi@eecs.umich.edu // Just ignore unknown ID's 12525952Ssaidi@eecs.umich.edu default: 12535952Ssaidi@eecs.umich.edu break; 12545952Ssaidi@eecs.umich.edu } 12555952Ssaidi@eecs.umich.edu} 12565952Ssaidi@eecs.umich.edu 125710905Sandreas.sandberg@arm.comvoid 125810905Sandreas.sandberg@arm.comVirtualDataAbort::invoke(ThreadContext *tc, const StaticInstPtr &inst) 125910905Sandreas.sandberg@arm.com{ 12605952Ssaidi@eecs.umich.edu AbortFault<VirtualDataAbort>::invoke(tc, inst); 12615952Ssaidi@eecs.umich.edu HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 12625952Ssaidi@eecs.umich.edu hcr.va = 0; 12635952Ssaidi@eecs.umich.edu tc->setMiscRegNoEffect(MISCREG_HCR, hcr); 12645952Ssaidi@eecs.umich.edu} 12655952Ssaidi@eecs.umich.edu 12665952Ssaidi@eecs.umich.edubool 12675952Ssaidi@eecs.umich.eduInterrupt::routeToMonitor(ThreadContext *tc) const 126810905Sandreas.sandberg@arm.com{ 12695952Ssaidi@eecs.umich.edu assert(ArmSystem::haveSecurity(tc)); 127010905Sandreas.sandberg@arm.com SCR scr = 0; 127110905Sandreas.sandberg@arm.com if (from64) 127210905Sandreas.sandberg@arm.com scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 12735952Ssaidi@eecs.umich.edu else 12745952Ssaidi@eecs.umich.edu scr = tc->readMiscRegNoEffect(MISCREG_SCR); 12755952Ssaidi@eecs.umich.edu return scr.irq; 12765952Ssaidi@eecs.umich.edu} 12775952Ssaidi@eecs.umich.edu 12785952Ssaidi@eecs.umich.edubool 12795952Ssaidi@eecs.umich.eduInterrupt::routeToHyp(ThreadContext *tc) const 12805952Ssaidi@eecs.umich.edu{ 12815952Ssaidi@eecs.umich.edu bool toHyp; 12825952Ssaidi@eecs.umich.edu 12835952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 12845952Ssaidi@eecs.umich.edu HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 12855952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 12865952Ssaidi@eecs.umich.edu // Determine whether IRQs are routed to Hyp mode. 12875952Ssaidi@eecs.umich.edu toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) || 128810905Sandreas.sandberg@arm.com (cpsr.mode == MODE_HYP); 12895952Ssaidi@eecs.umich.edu return toHyp; 12905952Ssaidi@eecs.umich.edu} 129110905Sandreas.sandberg@arm.com 129210905Sandreas.sandberg@arm.combool 129310377Sandreas.hansson@arm.comInterrupt::abortDisable(ThreadContext *tc) 12945952Ssaidi@eecs.umich.edu{ 12955952Ssaidi@eecs.umich.edu if (ArmSystem::haveSecurity(tc)) { 12965952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 12975952Ssaidi@eecs.umich.edu return (!scr.ns || scr.aw); 129810905Sandreas.sandberg@arm.com } 12995952Ssaidi@eecs.umich.edu return true; 13005952Ssaidi@eecs.umich.edu} 13015952Ssaidi@eecs.umich.edu 13025952Ssaidi@eecs.umich.eduVirtualInterrupt::VirtualInterrupt() 130310905Sandreas.sandberg@arm.com{} 130410905Sandreas.sandberg@arm.com 130510905Sandreas.sandberg@arm.combool 13065952Ssaidi@eecs.umich.eduFastInterrupt::routeToMonitor(ThreadContext *tc) const 13075952Ssaidi@eecs.umich.edu{ 130810905Sandreas.sandberg@arm.com assert(ArmSystem::haveSecurity(tc)); 13095952Ssaidi@eecs.umich.edu SCR scr = 0; 13105952Ssaidi@eecs.umich.edu if (from64) 13115952Ssaidi@eecs.umich.edu scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 13125952Ssaidi@eecs.umich.edu else 13135952Ssaidi@eecs.umich.edu scr = tc->readMiscRegNoEffect(MISCREG_SCR); 13145952Ssaidi@eecs.umich.edu return scr.fiq; 13155952Ssaidi@eecs.umich.edu} 131610905Sandreas.sandberg@arm.com 13175952Ssaidi@eecs.umich.edubool 131810905Sandreas.sandberg@arm.comFastInterrupt::routeToHyp(ThreadContext *tc) const 131910905Sandreas.sandberg@arm.com{ 13205952Ssaidi@eecs.umich.edu bool toHyp; 13215952Ssaidi@eecs.umich.edu 13225952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 13235952Ssaidi@eecs.umich.edu HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 13245952Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 132510905Sandreas.sandberg@arm.com // Determine whether IRQs are routed to Hyp mode. 13265952Ssaidi@eecs.umich.edu toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) || 13275952Ssaidi@eecs.umich.edu (cpsr.mode == MODE_HYP); 13285952Ssaidi@eecs.umich.edu return toHyp; 13295952Ssaidi@eecs.umich.edu} 133010905Sandreas.sandberg@arm.com 133110905Sandreas.sandberg@arm.combool 133210905Sandreas.sandberg@arm.comFastInterrupt::abortDisable(ThreadContext *tc) 13335952Ssaidi@eecs.umich.edu{ 13345952Ssaidi@eecs.umich.edu if (ArmSystem::haveSecurity(tc)) { 13355952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 13365952Ssaidi@eecs.umich.edu return (!scr.ns || scr.aw); 13375952Ssaidi@eecs.umich.edu } 13385952Ssaidi@eecs.umich.edu return true; 13395952Ssaidi@eecs.umich.edu} 134010905Sandreas.sandberg@arm.com 13415952Ssaidi@eecs.umich.edubool 134210905Sandreas.sandberg@arm.comFastInterrupt::fiqDisable(ThreadContext *tc) 134310905Sandreas.sandberg@arm.com{ 13445952Ssaidi@eecs.umich.edu if (ArmSystem::haveVirtualization(tc)) { 13455952Ssaidi@eecs.umich.edu return true; 13465952Ssaidi@eecs.umich.edu } else if (ArmSystem::haveSecurity(tc)) { 13475952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 13485952Ssaidi@eecs.umich.edu return (!scr.ns || scr.fw); 13495952Ssaidi@eecs.umich.edu } 13505952Ssaidi@eecs.umich.edu return true; 135110905Sandreas.sandberg@arm.com} 135210905Sandreas.sandberg@arm.com 135310905Sandreas.sandberg@arm.comVirtualFastInterrupt::VirtualFastInterrupt() 13545952Ssaidi@eecs.umich.edu{} 13555952Ssaidi@eecs.umich.edu 13565952Ssaidi@eecs.umich.eduvoid 13575952Ssaidi@eecs.umich.eduPCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) 13585952Ssaidi@eecs.umich.edu{ 135910905Sandreas.sandberg@arm.com ArmFaultVals<PCAlignmentFault>::invoke(tc, inst); 136010905Sandreas.sandberg@arm.com assert(from64); 136110905Sandreas.sandberg@arm.com // Set the FAR 13625952Ssaidi@eecs.umich.edu tc->setMiscReg(getFaultAddrReg64(), faultPC); 13635952Ssaidi@eecs.umich.edu} 13645952Ssaidi@eecs.umich.edu 13655952Ssaidi@eecs.umich.eduSPAlignmentFault::SPAlignmentFault() 13665952Ssaidi@eecs.umich.edu{} 13675952Ssaidi@eecs.umich.edu 13685952Ssaidi@eecs.umich.eduSystemError::SystemError() 13695952Ssaidi@eecs.umich.edu{} 13705952Ssaidi@eecs.umich.edu 137110470Sandreas.hansson@arm.comvoid 137210905Sandreas.sandberg@arm.comSystemError::invoke(ThreadContext *tc, const StaticInstPtr &inst) 13735952Ssaidi@eecs.umich.edu{ 13745952Ssaidi@eecs.umich.edu tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0); 13755952Ssaidi@eecs.umich.edu ArmFault::invoke(tc, inst); 13765952Ssaidi@eecs.umich.edu} 13775952Ssaidi@eecs.umich.edu 13785952Ssaidi@eecs.umich.edubool 13795952Ssaidi@eecs.umich.eduSystemError::routeToMonitor(ThreadContext *tc) const 138010905Sandreas.sandberg@arm.com{ 13815952Ssaidi@eecs.umich.edu assert(ArmSystem::haveSecurity(tc)); 13825952Ssaidi@eecs.umich.edu assert(from64); 13835952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 13845952Ssaidi@eecs.umich.edu return scr.ea; 13855952Ssaidi@eecs.umich.edu} 13865952Ssaidi@eecs.umich.edu 13875952Ssaidi@eecs.umich.edubool 13885952Ssaidi@eecs.umich.eduSystemError::routeToHyp(ThreadContext *tc) const 13895952Ssaidi@eecs.umich.edu{ 13905952Ssaidi@eecs.umich.edu bool toHyp; 13915952Ssaidi@eecs.umich.edu assert(from64); 139210905Sandreas.sandberg@arm.com 13935952Ssaidi@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 13945952Ssaidi@eecs.umich.edu HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 13955952Ssaidi@eecs.umich.edu 13965952Ssaidi@eecs.umich.edu toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) || 13975952Ssaidi@eecs.umich.edu (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc)); 13985952Ssaidi@eecs.umich.edu return toHyp; 13995952Ssaidi@eecs.umich.edu} 14005952Ssaidi@eecs.umich.edu 14015952Ssaidi@eecs.umich.edu 14025952Ssaidi@eecs.umich.eduSoftwareBreakpoint::SoftwareBreakpoint(ExtMachInst _mach_inst, uint32_t _iss) 14035952Ssaidi@eecs.umich.edu : ArmFaultVals<SoftwareBreakpoint>(_mach_inst, _iss) 14045952Ssaidi@eecs.umich.edu{} 14055952Ssaidi@eecs.umich.edu 14065952Ssaidi@eecs.umich.edubool 14075952Ssaidi@eecs.umich.eduSoftwareBreakpoint::routeToHyp(ThreadContext *tc) const 14085952Ssaidi@eecs.umich.edu{ 14095952Ssaidi@eecs.umich.edu assert(from64); 14105952Ssaidi@eecs.umich.edu 1411 const bool have_el2 = ArmSystem::haveVirtualization(tc); 1412 1413 const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2); 1414 const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2); 1415 1416 return have_el2 && !inSecureState(tc) && fromEL <= EL1 && 1417 (hcr.tge || mdcr.tde); 1418} 1419 1420void 1421ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) { 1422 DPRINTF(Faults, "Invoking ArmSev Fault\n"); 1423 if (!FullSystem) 1424 return; 1425 1426 // Set sev_mailbox to 1, clear the pending interrupt from remote 1427 // SEV execution and let pipeline continue as pcState is still 1428 // valid. 1429 tc->setMiscReg(MISCREG_SEV_MAILBOX, 1); 1430 tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0); 1431} 1432 1433// Instantiate all the templates to make the linker happy 1434template class ArmFaultVals<Reset>; 1435template class ArmFaultVals<UndefinedInstruction>; 1436template class ArmFaultVals<SupervisorCall>; 1437template class ArmFaultVals<SecureMonitorCall>; 1438template class ArmFaultVals<HypervisorCall>; 1439template class ArmFaultVals<PrefetchAbort>; 1440template class ArmFaultVals<DataAbort>; 1441template class ArmFaultVals<VirtualDataAbort>; 1442template class ArmFaultVals<HypervisorTrap>; 1443template class ArmFaultVals<Interrupt>; 1444template class ArmFaultVals<VirtualInterrupt>; 1445template class ArmFaultVals<FastInterrupt>; 1446template class ArmFaultVals<VirtualFastInterrupt>; 1447template class ArmFaultVals<SupervisorTrap>; 1448template class ArmFaultVals<SecureMonitorTrap>; 1449template class ArmFaultVals<PCAlignmentFault>; 1450template class ArmFaultVals<SPAlignmentFault>; 1451template class ArmFaultVals<SystemError>; 1452template class ArmFaultVals<SoftwareBreakpoint>; 1453template class ArmFaultVals<ArmSev>; 1454template class AbortFault<PrefetchAbort>; 1455template class AbortFault<DataAbort>; 1456template class AbortFault<VirtualDataAbort>; 1457 1458 1459IllegalInstSetStateFault::IllegalInstSetStateFault() 1460{} 1461 1462 1463} // namespace ArmISA 1464