faults.cc revision 12568
1360SN/A/* 210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2010, 2012-2014, 2016-2018 ARM Limited 310796Sbrandon.potter@amd.com * All rights reserved 410027SChris.Adeniyi-Jones@arm.com * 510027SChris.Adeniyi-Jones@arm.com * The license below extends only to copyright in the software and shall 610027SChris.Adeniyi-Jones@arm.com * not be construed as granting a license to any other intellectual 710027SChris.Adeniyi-Jones@arm.com * property including but not limited to intellectual property relating 810027SChris.Adeniyi-Jones@arm.com * to a hardware implementation of the functionality of the software 910027SChris.Adeniyi-Jones@arm.com * licensed hereunder. You may use the software subject to the license 1010027SChris.Adeniyi-Jones@arm.com * terms below provided that you ensure that this notice is replicated 1110027SChris.Adeniyi-Jones@arm.com * unmodified and in its entirety in all distributions of the software, 1210027SChris.Adeniyi-Jones@arm.com * modified or unmodified, in source code or in binary form. 1310027SChris.Adeniyi-Jones@arm.com * 1410027SChris.Adeniyi-Jones@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 151458SN/A * Copyright (c) 2007-2008 The Florida State University 16360SN/A * All rights reserved. 17360SN/A * 18360SN/A * Redistribution and use in source and binary forms, with or without 19360SN/A * modification, are permitted provided that the following conditions are 20360SN/A * met: redistributions of source code must retain the above copyright 21360SN/A * notice, this list of conditions and the following disclaimer; 22360SN/A * redistributions in binary form must reproduce the above copyright 23360SN/A * notice, this list of conditions and the following disclaimer in the 24360SN/A * documentation and/or other materials provided with the distribution; 25360SN/A * neither the name of the copyright holders nor the names of its 26360SN/A * contributors may be used to endorse or promote products derived from 27360SN/A * this software without specific prior written permission. 28360SN/A * 29360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402665Ssaidi@eecs.umich.edu * 412665Ssaidi@eecs.umich.edu * Authors: Ali Saidi 422665Ssaidi@eecs.umich.edu * Gabe Black 43360SN/A * Giacomo Gabrielli 44360SN/A * Thomas Grocutt 451354SN/A */ 461354SN/A 47360SN/A#include "arch/arm/faults.hh" 4812018Sandreas.sandberg@arm.com 4912018Sandreas.sandberg@arm.com#include "arch/arm/insts/static_inst.hh" 5012018Sandreas.sandberg@arm.com#include "arch/arm/system.hh" 5112018Sandreas.sandberg@arm.com#include "arch/arm/utility.hh" 5212018Sandreas.sandberg@arm.com#include "base/compiler.hh" 5312018Sandreas.sandberg@arm.com#include "base/trace.hh" 5412018Sandreas.sandberg@arm.com#include "cpu/base.hh" 552064SN/A#include "cpu/thread_context.hh" 5612018Sandreas.sandberg@arm.com#include "debug/Faults.hh" 5712018Sandreas.sandberg@arm.com#include "sim/full_system.hh" 5812018Sandreas.sandberg@arm.com 5912018Sandreas.sandberg@arm.comnamespace ArmISA 6012018Sandreas.sandberg@arm.com{ 6112018Sandreas.sandberg@arm.com 6211799Sbrandon.potter@amd.comuint8_t ArmFault::shortDescFaultSources[] = { 6312018Sandreas.sandberg@arm.com 0x01, // AlignmentFault 6412018Sandreas.sandberg@arm.com 0x04, // InstructionCacheMaintenance 6512018Sandreas.sandberg@arm.com 0xff, // SynchExtAbtOnTranslTableWalkL0 (INVALID) 6612018Sandreas.sandberg@arm.com 0x0c, // SynchExtAbtOnTranslTableWalkL1 6712018Sandreas.sandberg@arm.com 0x0e, // SynchExtAbtOnTranslTableWalkL2 6812018Sandreas.sandberg@arm.com 0xff, // SynchExtAbtOnTranslTableWalkL3 (INVALID) 6911799Sbrandon.potter@amd.com 0xff, // SynchPtyErrOnTranslTableWalkL0 (INVALID) 70360SN/A 0x1c, // SynchPtyErrOnTranslTableWalkL1 71360SN/A 0x1e, // SynchPtyErrOnTranslTableWalkL2 72360SN/A 0xff, // SynchPtyErrOnTranslTableWalkL3 (INVALID) 73360SN/A 0xff, // TranslationL0 (INVALID) 74360SN/A 0x05, // TranslationL1 75360SN/A 0x07, // TranslationL2 761809SN/A 0xff, // TranslationL3 (INVALID) 7711800Sbrandon.potter@amd.com 0xff, // AccessFlagL0 (INVALID) 7811392Sbrandon.potter@amd.com 0x03, // AccessFlagL1 791809SN/A 0x06, // AccessFlagL2 8011392Sbrandon.potter@amd.com 0xff, // AccessFlagL3 (INVALID) 8113570Sbrandon.potter@amd.com 0xff, // DomainL0 (INVALID) 8211383Sbrandon.potter@amd.com 0x09, // DomainL1 8313568Sbrandon.potter@amd.com 0x0b, // DomainL2 843113Sgblack@eecs.umich.edu 0xff, // DomainL3 (INVALID) 8511799Sbrandon.potter@amd.com 0xff, // PermissionL0 (INVALID) 8611759Sbrandon.potter@amd.com 0x0d, // PermissionL1 8711812Sbaz21@cam.ac.uk 0x0f, // PermissionL2 8811812Sbaz21@cam.ac.uk 0xff, // PermissionL3 (INVALID) 8911799Sbrandon.potter@amd.com 0x02, // DebugEvent 908229Snate@binkert.org 0x08, // SynchronousExternalAbort 9113570Sbrandon.potter@amd.com 0x10, // TLBConflictAbort 928229Snate@binkert.org 0x19, // SynchPtyErrOnMemoryAccess 9311594Santhony.gutierrez@amd.com 0x16, // AsynchronousExternalAbort 947075Snate@binkert.org 0x18, // AsynchPtyErrOnMemoryAccess 958229Snate@binkert.org 0xff, // AddressSizeL0 (INVALID) 9611856Sbrandon.potter@amd.com 0xff, // AddressSizeL1 (INVALID) 977075Snate@binkert.org 0xff, // AddressSizeL2 (INVALID) 98360SN/A 0xff, // AddressSizeL3 (INVALID) 9912461Sgabeblack@google.com 0x40, // PrefetchTLBMiss 10011886Sbrandon.potter@amd.com 0x80 // PrefetchUncacheable 10111800Sbrandon.potter@amd.com}; 10211392Sbrandon.potter@amd.com 10312334Sgabeblack@google.comstatic_assert(sizeof(ArmFault::shortDescFaultSources) == 1041354SN/A ArmFault::NumFaultSources, 1056216Snate@binkert.org "Invalid size of ArmFault::shortDescFaultSources[]"); 1066658Snate@binkert.org 1072474SN/Auint8_t ArmFault::longDescFaultSources[] = { 1082680Sktlim@umich.edu 0x21, // AlignmentFault 1098229Snate@binkert.org 0xff, // InstructionCacheMaintenance (INVALID) 11011886Sbrandon.potter@amd.com 0xff, // SynchExtAbtOnTranslTableWalkL0 (INVALID) 11110496Ssteve.reinhardt@amd.com 0x15, // SynchExtAbtOnTranslTableWalkL1 11211911SBrandon.Potter@amd.com 0x16, // SynchExtAbtOnTranslTableWalkL2 1138229Snate@binkert.org 0x17, // SynchExtAbtOnTranslTableWalkL3 11411794Sbrandon.potter@amd.com 0xff, // SynchPtyErrOnTranslTableWalkL0 (INVALID) 11511886Sbrandon.potter@amd.com 0x1d, // SynchPtyErrOnTranslTableWalkL1 11610497Ssteve.reinhardt@amd.com 0x1e, // SynchPtyErrOnTranslTableWalkL2 11711794Sbrandon.potter@amd.com 0x1f, // SynchPtyErrOnTranslTableWalkL3 118360SN/A 0xff, // TranslationL0 (INVALID) 11913629SAndrea.Mondelli@ucf.edu 0x05, // TranslationL1 12013629SAndrea.Mondelli@ucf.edu 0x06, // TranslationL2 12113629SAndrea.Mondelli@ucf.edu 0x07, // TranslationL3 12213629SAndrea.Mondelli@ucf.edu 0xff, // AccessFlagL0 (INVALID) 123360SN/A 0x09, // AccessFlagL1 124360SN/A 0x0a, // AccessFlagL2 125360SN/A 0x0b, // AccessFlagL3 126360SN/A 0xff, // DomainL0 (INVALID) 127360SN/A 0x3d, // DomainL1 128360SN/A 0x3e, // DomainL2 129360SN/A 0xff, // DomainL3 (RESERVED) 130360SN/A 0xff, // PermissionL0 (INVALID) 131360SN/A 0x0d, // PermissionL1 132378SN/A 0x0e, // PermissionL2 1331706SN/A 0x0f, // PermissionL3 13411851Sbrandon.potter@amd.com 0x22, // DebugEvent 135378SN/A 0x10, // SynchronousExternalAbort 136378SN/A 0x30, // TLBConflictAbort 137378SN/A 0x18, // SynchPtyErrOnMemoryAccess 138378SN/A 0x11, // AsynchronousExternalAbort 139378SN/A 0x19, // AsynchPtyErrOnMemoryAccess 1401706SN/A 0xff, // AddressSizeL0 (INVALID) 14111851Sbrandon.potter@amd.com 0xff, // AddressSizeL1 (INVALID) 142360SN/A 0xff, // AddressSizeL2 (INVALID) 14311760Sbrandon.potter@amd.com 0xff, // AddressSizeL3 (INVALID) 14411760Sbrandon.potter@amd.com 0x40, // PrefetchTLBMiss 14511851Sbrandon.potter@amd.com 0x80 // PrefetchUncacheable 14611760Sbrandon.potter@amd.com}; 1476109Ssanchezd@stanford.edu 1481706SN/Astatic_assert(sizeof(ArmFault::longDescFaultSources) == 14911851Sbrandon.potter@amd.com ArmFault::NumFaultSources, 150378SN/A "Invalid size of ArmFault::longDescFaultSources[]"); 1516109Ssanchezd@stanford.edu 1526109Ssanchezd@stanford.eduuint8_t ArmFault::aarch64FaultSources[] = { 15311851Sbrandon.potter@amd.com 0x21, // AlignmentFault 1546109Ssanchezd@stanford.edu 0xff, // InstructionCacheMaintenance (INVALID) 15511886Sbrandon.potter@amd.com 0x14, // SynchExtAbtOnTranslTableWalkL0 15611886Sbrandon.potter@amd.com 0x15, // SynchExtAbtOnTranslTableWalkL1 15711886Sbrandon.potter@amd.com 0x16, // SynchExtAbtOnTranslTableWalkL2 15811886Sbrandon.potter@amd.com 0x17, // SynchExtAbtOnTranslTableWalkL3 159378SN/A 0x1c, // SynchPtyErrOnTranslTableWalkL0 1601706SN/A 0x1d, // SynchPtyErrOnTranslTableWalkL1 16111851Sbrandon.potter@amd.com 0x1e, // SynchPtyErrOnTranslTableWalkL2 162378SN/A 0x1f, // SynchPtyErrOnTranslTableWalkL3 1635748SSteve.Reinhardt@amd.com 0x04, // TranslationL0 1645748SSteve.Reinhardt@amd.com 0x05, // TranslationL1 16511851Sbrandon.potter@amd.com 0x06, // TranslationL2 166378SN/A 0x07, // TranslationL3 167378SN/A 0x08, // AccessFlagL0 1681706SN/A 0x09, // AccessFlagL1 16911851Sbrandon.potter@amd.com 0x0a, // AccessFlagL2 170378SN/A 0x0b, // AccessFlagL3 171378SN/A // @todo: Section & Page Domain Fault in AArch64? 1721706SN/A 0xff, // DomainL0 (INVALID) 17311851Sbrandon.potter@amd.com 0xff, // DomainL1 (INVALID) 174378SN/A 0xff, // DomainL2 (INVALID) 1754118Sgblack@eecs.umich.edu 0xff, // DomainL3 (INVALID) 1764118Sgblack@eecs.umich.edu 0x0c, // PermissionL0 17711851Sbrandon.potter@amd.com 0x0d, // PermissionL1 1784118Sgblack@eecs.umich.edu 0x0e, // PermissionL2 179378SN/A 0x0f, // PermissionL3 1801706SN/A 0xff, // DebugEvent (INVALID) 18111851Sbrandon.potter@amd.com 0x10, // SynchronousExternalAbort 182378SN/A 0x30, // TLBConflictAbort 18313568Sbrandon.potter@amd.com 0x18, // SynchPtyErrOnMemoryAccess 18413568Sbrandon.potter@amd.com 0xff, // AsynchronousExternalAbort (INVALID) 18513568Sbrandon.potter@amd.com 0xff, // AsynchPtyErrOnMemoryAccess (INVALID) 18613568Sbrandon.potter@amd.com 0x00, // AddressSizeL0 187378SN/A 0x01, // AddressSizeL1 1881706SN/A 0x02, // AddressSizeL2 18911851Sbrandon.potter@amd.com 0x03, // AddressSizeL3 190360SN/A 0x40, // PrefetchTLBMiss 1915513SMichael.Adler@intel.com 0x80 // PrefetchUncacheable 1925513SMichael.Adler@intel.com}; 19311851Sbrandon.potter@amd.com 1945513SMichael.Adler@intel.comstatic_assert(sizeof(ArmFault::aarch64FaultSources) == 19510203SAli.Saidi@ARM.com ArmFault::NumFaultSources, 19610203SAli.Saidi@ARM.com "Invalid size of ArmFault::aarch64FaultSources[]"); 19711851Sbrandon.potter@amd.com 19810203SAli.Saidi@ARM.com// Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode, 1995513SMichael.Adler@intel.com// {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap, 20011851Sbrandon.potter@amd.com// {A, F} disable, class, stat 2015513SMichael.Adler@intel.comtemplate<> ArmFault::FaultVals ArmFaultVals<Reset>::vals( 202511SN/A // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED 20310633Smichaelupton@gmail.com // location in AArch64) 20411851Sbrandon.potter@amd.com "Reset", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC, 20510633Smichaelupton@gmail.com 0, 0, 0, 0, false, true, true, EC_UNKNOWN 2061706SN/A); 20711851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<UndefinedInstruction>::vals( 208511SN/A "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED, 20912795Smattdsinclair@gmail.com 4, 2, 0, 0, true, false, false, EC_UNKNOWN 21012795Smattdsinclair@gmail.com); 21112795Smattdsinclair@gmail.comtemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorCall>::vals( 21212795Smattdsinclair@gmail.com "Supervisor Call", 0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 21312796Smattdsinclair@gmail.com 4, 2, 4, 2, true, false, false, EC_SVC_TO_HYP 21412796Smattdsinclair@gmail.com); 21512796Smattdsinclair@gmail.comtemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorCall>::vals( 21612796Smattdsinclair@gmail.com "Secure Monitor Call", 0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON, 2175513SMichael.Adler@intel.com 4, 4, 4, 4, false, true, true, EC_SMC_TO_HYP 2185513SMichael.Adler@intel.com); 21911851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorCall>::vals( 2205513SMichael.Adler@intel.com "Hypervisor Call", 0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP, 22113031Sbrandon.potter@amd.com 4, 4, 4, 4, true, false, false, EC_HVC 22213031Sbrandon.potter@amd.com); 22313031Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<PrefetchAbort>::vals( 22413031Sbrandon.potter@amd.com "Prefetch Abort", 0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT, 22513031Sbrandon.potter@amd.com 4, 4, 0, 0, true, true, false, EC_PREFETCH_ABORT_TO_HYP 22613031Sbrandon.potter@amd.com); 22713031Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<DataAbort>::vals( 22813031Sbrandon.potter@amd.com "Data Abort", 0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT, 22913031Sbrandon.potter@amd.com 8, 8, 0, 0, true, true, false, EC_DATA_ABORT_TO_HYP 23013031Sbrandon.potter@amd.com); 23113031Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<VirtualDataAbort>::vals( 23213031Sbrandon.potter@amd.com "Virtual Data Abort", 0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT, 233511SN/A 8, 8, 0, 0, true, true, false, EC_INVALID 2341706SN/A); 23511851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<HypervisorTrap>::vals( 2361706SN/A // @todo: double check these values 2371706SN/A "Hypervisor Trap", 0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP, 2381706SN/A 0, 0, 0, 0, false, false, false, EC_UNKNOWN 2391706SN/A); 24011851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<SecureMonitorTrap>::vals( 2411706SN/A "Secure Monitor Trap", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_MON, 2421706SN/A 4, 2, 0, 0, false, false, false, EC_UNKNOWN 2431706SN/A); 2441706SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals( 24511851Sbrandon.potter@amd.com "IRQ", 0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ, 2461706SN/A 4, 4, 0, 0, false, true, false, EC_UNKNOWN 247511SN/A); 2486703Svince@csl.cornell.edutemplate<> ArmFault::FaultVals ArmFaultVals<VirtualInterrupt>::vals( 2496703Svince@csl.cornell.edu "Virtual IRQ", 0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ, 25011851Sbrandon.potter@amd.com 4, 4, 0, 0, false, true, false, EC_INVALID 2516703Svince@csl.cornell.edu); 2526685Stjones1@inf.ed.ac.uktemplate<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals( 2536685Stjones1@inf.ed.ac.uk "FIQ", 0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ, 25411851Sbrandon.potter@amd.com 4, 4, 0, 0, false, true, true, EC_UNKNOWN 2556685Stjones1@inf.ed.ac.uk); 2566685Stjones1@inf.ed.ac.uktemplate<> ArmFault::FaultVals ArmFaultVals<VirtualFastInterrupt>::vals( 2575513SMichael.Adler@intel.com "Virtual FIQ", 0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ, 2585513SMichael.Adler@intel.com 4, 4, 0, 0, false, true, true, EC_INVALID 25911851Sbrandon.potter@amd.com); 2605513SMichael.Adler@intel.comtemplate<> ArmFault::FaultVals ArmFaultVals<SupervisorTrap>::vals( 26111885Sbrandon.potter@amd.com // Some dummy values (SupervisorTrap is AArch64-only) 26211885Sbrandon.potter@amd.com "Supervisor Trap", 0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 26311885Sbrandon.potter@amd.com 0, 0, 0, 0, false, false, false, EC_UNKNOWN 2645513SMichael.Adler@intel.com); 2651999SN/Atemplate<> ArmFault::FaultVals ArmFaultVals<PCAlignmentFault>::vals( 2661999SN/A // Some dummy values (PCAlignmentFault is AArch64-only) 26711851Sbrandon.potter@amd.com "PC Alignment Fault", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2681999SN/A 0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT 26911885Sbrandon.potter@amd.com); 27011885Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<SPAlignmentFault>::vals( 27111885Sbrandon.potter@amd.com // Some dummy values (SPAlignmentFault is AArch64-only) 2721999SN/A "SP Alignment Fault", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2731999SN/A 0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT 2741999SN/A); 27511851Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals( 2761999SN/A // Some dummy values (SError is AArch64-only) 2773079Sstever@eecs.umich.edu "SError", 0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC, 2783079Sstever@eecs.umich.edu 0, 0, 0, 0, false, true, true, EC_SERROR 27911851Sbrandon.potter@amd.com); 2803079Sstever@eecs.umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals( 28111908SBrandon.Potter@amd.com // Some dummy values (SoftwareBreakpoint is AArch64-only) 28211908SBrandon.Potter@amd.com "Software Breakpoint", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 28311908SBrandon.Potter@amd.com 0, 0, 0, 0, true, false, false, EC_SOFTWARE_BREAKPOINT 28411908SBrandon.Potter@amd.com); 28511875Sbrandon.potter@amd.comtemplate<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals( 2862093SN/A // Some dummy values 28711851Sbrandon.potter@amd.com "ArmSev Flush", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC, 2882093SN/A 0, 0, 0, 0, false, true, true, EC_UNKNOWN 2892687Sksewell@umich.edu); 2902687Sksewell@umich.edutemplate<> ArmFault::FaultVals ArmFaultVals<IllegalInstSetStateFault>::vals( 29111851Sbrandon.potter@amd.com // Some dummy values (SPAlignmentFault is AArch64-only) 2922687Sksewell@umich.edu "Illegal Inst Set State Fault", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC, 2932238SN/A 0, 0, 0, 0, true, false, false, EC_ILLEGAL_INST 2942238SN/A); 29511851Sbrandon.potter@amd.com 2962238SN/AAddr 29711908SBrandon.Potter@amd.comArmFault::getVector(ThreadContext *tc) 29811908SBrandon.Potter@amd.com{ 29911908SBrandon.Potter@amd.com Addr base; 30011908SBrandon.Potter@amd.com 30111908SBrandon.Potter@amd.com // ARM ARM issue C B1.8.1 30211908SBrandon.Potter@amd.com bool haveSecurity = ArmSystem::haveSecurity(tc); 30311908SBrandon.Potter@amd.com 30411908SBrandon.Potter@amd.com // panic if SCTLR.VE because I have no idea what to do with vectored 3052238SN/A // interrupts 3062238SN/A SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); 30711851Sbrandon.potter@amd.com assert(!sctlr.ve); 3082238SN/A // Check for invalid modes 30913571Sbrandon.potter@amd.com CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 31013571Sbrandon.potter@amd.com assert(haveSecurity || cpsr.mode != MODE_MON); 31113571Sbrandon.potter@amd.com assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP); 31213571Sbrandon.potter@amd.com 31313568Sbrandon.potter@amd.com switch (cpsr.mode) 31413568Sbrandon.potter@amd.com { 31513568Sbrandon.potter@amd.com case MODE_MON: 31613568Sbrandon.potter@amd.com base = tc->readMiscReg(MISCREG_MVBAR); 31713568Sbrandon.potter@amd.com break; 31813568Sbrandon.potter@amd.com case MODE_HYP: 31913568Sbrandon.potter@amd.com base = tc->readMiscReg(MISCREG_HVBAR); 32013568Sbrandon.potter@amd.com break; 32113568Sbrandon.potter@amd.com default: 32213568Sbrandon.potter@amd.com if (sctlr.v) { 32313568Sbrandon.potter@amd.com base = HighVecs; 32413568Sbrandon.potter@amd.com } else { 32513448Sciro.santilli@arm.com base = haveSecurity ? tc->readMiscReg(MISCREG_VBAR) : 0; 32613031Sbrandon.potter@amd.com } 32713031Sbrandon.potter@amd.com break; 32813031Sbrandon.potter@amd.com } 32913448Sciro.santilli@arm.com return base + offset(tc); 33013031Sbrandon.potter@amd.com} 33113539Sjavier.setoain@arm.com 33213539Sjavier.setoain@arm.comAddr 33313539Sjavier.setoain@arm.comArmFault::getVector64(ThreadContext *tc) 33413539Sjavier.setoain@arm.com{ 33513539Sjavier.setoain@arm.com Addr vbar; 33613539Sjavier.setoain@arm.com switch (toEL) { 33713569Sbrandon.potter@amd.com case EL3: 33813569Sbrandon.potter@amd.com assert(ArmSystem::haveSecurity(tc)); 33913569Sbrandon.potter@amd.com vbar = tc->readMiscReg(MISCREG_VBAR_EL3); 34013569Sbrandon.potter@amd.com break; 34113569Sbrandon.potter@amd.com case EL2: 34213569Sbrandon.potter@amd.com assert(ArmSystem::haveVirtualization(tc)); 34313569Sbrandon.potter@amd.com vbar = tc->readMiscReg(MISCREG_VBAR_EL2); 34413569Sbrandon.potter@amd.com break; 34513569Sbrandon.potter@amd.com case EL1: 34613569Sbrandon.potter@amd.com vbar = tc->readMiscReg(MISCREG_VBAR_EL1); 34713569Sbrandon.potter@amd.com break; 34813569Sbrandon.potter@amd.com default: 34913569Sbrandon.potter@amd.com panic("Invalid target exception level"); 35013569Sbrandon.potter@amd.com break; 35113569Sbrandon.potter@amd.com } 35213569Sbrandon.potter@amd.com return vbar + offset64(tc); 35313031Sbrandon.potter@amd.com} 3542238SN/A 35511851Sbrandon.potter@amd.comMiscRegIndex 3562238SN/AArmFault::getSyndromeReg64() const 3572238SN/A{ 3582238SN/A switch (toEL) { 35911851Sbrandon.potter@amd.com case EL1: 3602238SN/A return MISCREG_ESR_EL1; 3612238SN/A case EL2: 3622238SN/A return MISCREG_ESR_EL2; 36311851Sbrandon.potter@amd.com case EL3: 3642238SN/A return MISCREG_ESR_EL3; 3652238SN/A default: 3662238SN/A panic("Invalid exception level"); 36711851Sbrandon.potter@amd.com break; 3682238SN/A } 3692238SN/A} 3702238SN/A 37111851Sbrandon.potter@amd.comMiscRegIndex 3722238SN/AArmFault::getFaultAddrReg64() const 3739455Smitch.hayenga+gem5@gmail.com{ 3749455Smitch.hayenga+gem5@gmail.com switch (toEL) { 37511851Sbrandon.potter@amd.com case EL1: 37610203SAli.Saidi@ARM.com return MISCREG_FAR_EL1; 37711851Sbrandon.potter@amd.com case EL2: 37811851Sbrandon.potter@amd.com return MISCREG_FAR_EL2; 3799455Smitch.hayenga+gem5@gmail.com case EL3: 38013571Sbrandon.potter@amd.com return MISCREG_FAR_EL3; 38113571Sbrandon.potter@amd.com default: 38213571Sbrandon.potter@amd.com panic("Invalid exception level"); 38313571Sbrandon.potter@amd.com break; 38413571Sbrandon.potter@amd.com } 38513571Sbrandon.potter@amd.com} 38613571Sbrandon.potter@amd.com 38713571Sbrandon.potter@amd.comvoid 38813571Sbrandon.potter@amd.comArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg) 38913571Sbrandon.potter@amd.com{ 39013571Sbrandon.potter@amd.com uint32_t value; 39113571Sbrandon.potter@amd.com uint32_t exc_class = (uint32_t) ec(tc); 3929112Smarc.orr@gmail.com uint32_t issVal = iss(); 39311906SBrandon.Potter@amd.com 39411906SBrandon.Potter@amd.com assert(!from64 || ArmSystem::highestELIs64(tc)); 3959112Smarc.orr@gmail.com 3969112Smarc.orr@gmail.com value = exc_class << 26; 39711851Sbrandon.potter@amd.com 3989112Smarc.orr@gmail.com // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24, 3999112Smarc.orr@gmail.com // 0x25) for which the ISS information is not valid (ARMv7). 40011911SBrandon.Potter@amd.com // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not 4019112Smarc.orr@gmail.com // valid it is treated as RES1. 40211911SBrandon.Potter@amd.com if (to64) { 40311911SBrandon.Potter@amd.com value |= 1 << 25; 40411911SBrandon.Potter@amd.com } else if ((bits(exc_class, 5, 3) != 4) || 40511911SBrandon.Potter@amd.com (bits(exc_class, 2) && bits(issVal, 24))) { 40613642Sqtt2@cornell.edu if (!machInst.thumb || machInst.bigThumb) 40713642Sqtt2@cornell.edu value |= 1 << 25; 40813642Sqtt2@cornell.edu } 4099112Smarc.orr@gmail.com // Condition code valid for EC[5:4] nonzero 41011911SBrandon.Potter@amd.com if (!from64 && ((bits(exc_class, 5, 4) == 0) && 41111911SBrandon.Potter@amd.com (bits(exc_class, 3, 0) != 0))) { 41211911SBrandon.Potter@amd.com if (!machInst.thumb) { 41311911SBrandon.Potter@amd.com uint32_t cond; 4149238Slluc.alvarez@bsc.es ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode; 41513642Sqtt2@cornell.edu // If its on unconditional instruction report with a cond code of 4169112Smarc.orr@gmail.com // 0xE, ie the unconditional code 41711911SBrandon.Potter@amd.com cond = (condCode == COND_UC) ? COND_AL : condCode; 4189112Smarc.orr@gmail.com value |= cond << 20; 41913642Sqtt2@cornell.edu value |= 1 << 24; 42011911SBrandon.Potter@amd.com } 42111911SBrandon.Potter@amd.com value |= bits(issVal, 19, 0); 42211911SBrandon.Potter@amd.com } else { 42311911SBrandon.Potter@amd.com value |= issVal; 4249112Smarc.orr@gmail.com } 42511911SBrandon.Potter@amd.com tc->setMiscReg(syndrome_reg, value); 42611911SBrandon.Potter@amd.com} 42711911SBrandon.Potter@amd.com 42811911SBrandon.Potter@amd.comvoid 42911911SBrandon.Potter@amd.comArmFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) 43011911SBrandon.Potter@amd.com{ 4319112Smarc.orr@gmail.com CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 4329112Smarc.orr@gmail.com 43313642Sqtt2@cornell.edu if (ArmSystem::highestELIs64(tc)) { // ARMv8 43413642Sqtt2@cornell.edu // Determine source exception level and mode 43513642Sqtt2@cornell.edu fromMode = (OperatingMode) (uint8_t) cpsr.mode; 43613642Sqtt2@cornell.edu fromEL = opModeToEL(fromMode); 43713642Sqtt2@cornell.edu if (opModeIs64(fromMode)) 43811911SBrandon.Potter@amd.com from64 = true; 4399112Smarc.orr@gmail.com 44011911SBrandon.Potter@amd.com // Determine target exception level 44111911SBrandon.Potter@amd.com if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc)) { 44213642Sqtt2@cornell.edu toEL = EL3; 44313642Sqtt2@cornell.edu } else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc)) { 4449112Smarc.orr@gmail.com toEL = EL2; 4459112Smarc.orr@gmail.com hypRouted = true; 44611911SBrandon.Potter@amd.com } else { 44711911SBrandon.Potter@amd.com toEL = opModeToEL(nextMode()); 4489112Smarc.orr@gmail.com } 4499112Smarc.orr@gmail.com 4502238SN/A if (fromEL > toEL) 4512238SN/A toEL = fromEL; 4522238SN/A 4532238SN/A if (toEL == ArmSystem::highestEL(tc) || ELIs64(tc, toEL)) { 45411851Sbrandon.potter@amd.com // Invoke exception handler in AArch64 state 4552238SN/A to64 = true; 4562238SN/A invoke64(tc, inst); 4572238SN/A return; 45811851Sbrandon.potter@amd.com } 4592238SN/A } 4602238SN/A 4612238SN/A // ARMv7 (ARM ARM issue C B1.9) 46211851Sbrandon.potter@amd.com 4632238SN/A bool have_security = ArmSystem::haveSecurity(tc); 4642238SN/A bool have_virtualization = ArmSystem::haveVirtualization(tc); 4652238SN/A 46611851Sbrandon.potter@amd.com FaultBase::invoke(tc); 4672238SN/A if (!FullSystem) 4682238SN/A return; 4691354SN/A countStat()++; 4701354SN/A 47110796Sbrandon.potter@amd.com SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); 47210796Sbrandon.potter@amd.com SCR scr = tc->readMiscReg(MISCREG_SCR); 4731354SN/A CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR); 4741354SN/A saved_cpsr.nz = tc->readCCReg(CCREG_NZ); 4751354SN/A saved_cpsr.c = tc->readCCReg(CCREG_C); 4761354SN/A saved_cpsr.v = tc->readCCReg(CCREG_V); 4771354SN/A saved_cpsr.ge = tc->readCCReg(CCREG_GE); 4781354SN/A 4791354SN/A Addr curPc M5_VAR_USED = tc->pcState().pc(); 4801354SN/A ITSTATE it = tc->pcState().itstate(); 4811354SN/A saved_cpsr.it2 = it.top6; 4821354SN/A saved_cpsr.it1 = it.bottom2; 48310796Sbrandon.potter@amd.com 4841354SN/A // if we have a valid instruction then use it to annotate this fault with 48510796Sbrandon.potter@amd.com // extra information. This is used to generate the correct fault syndrome 4861354SN/A // information 4871354SN/A if (inst) { 4881354SN/A ArmStaticInst *armInst = static_cast<ArmStaticInst *>(inst.get()); 4891354SN/A armInst->annotateFault(this); 49010796Sbrandon.potter@amd.com } 49110796Sbrandon.potter@amd.com 49210796Sbrandon.potter@amd.com if (have_security && routeToMonitor(tc)) { 49310796Sbrandon.potter@amd.com cpsr.mode = MODE_MON; 49410796Sbrandon.potter@amd.com } else if (have_virtualization && routeToHyp(tc)) { 49510796Sbrandon.potter@amd.com cpsr.mode = MODE_HYP; 49610796Sbrandon.potter@amd.com hypRouted = true; 49710796Sbrandon.potter@amd.com } else { 49810796Sbrandon.potter@amd.com cpsr.mode = nextMode(); 49910796Sbrandon.potter@amd.com } 50010796Sbrandon.potter@amd.com 501360SN/A // Ensure Secure state if initially in Monitor mode 502360SN/A if (have_security && saved_cpsr.mode == MODE_MON) { 503360SN/A SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 504360SN/A if (scr.ns) { 505360SN/A scr.ns = 0; 506360SN/A tc->setMiscRegNoEffect(MISCREG_SCR, scr); 507360SN/A } 50811759Sbrandon.potter@amd.com } 5093113Sgblack@eecs.umich.edu 5103113Sgblack@eecs.umich.edu // some bits are set differently if we have been routed to hyp mode 5113113Sgblack@eecs.umich.edu if (cpsr.mode == MODE_HYP) { 5123113Sgblack@eecs.umich.edu SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR); 5133113Sgblack@eecs.umich.edu cpsr.t = hsctlr.te; 5143113Sgblack@eecs.umich.edu cpsr.e = hsctlr.ee; 5153113Sgblack@eecs.umich.edu if (!scr.ea) {cpsr.a = 1;} 5163113Sgblack@eecs.umich.edu if (!scr.fiq) {cpsr.f = 1;} 5173113Sgblack@eecs.umich.edu if (!scr.irq) {cpsr.i = 1;} 5183113Sgblack@eecs.umich.edu } else if (cpsr.mode == MODE_MON) { 5193113Sgblack@eecs.umich.edu // Special case handling when entering monitor mode 5203113Sgblack@eecs.umich.edu cpsr.t = sctlr.te; 5213113Sgblack@eecs.umich.edu cpsr.e = sctlr.ee; 52212032Sandreas.sandberg@arm.com cpsr.a = 1; 5233113Sgblack@eecs.umich.edu cpsr.f = 1; 5243113Sgblack@eecs.umich.edu cpsr.i = 1; 5254189Sgblack@eecs.umich.edu } else { 5264189Sgblack@eecs.umich.edu cpsr.t = sctlr.te; 5273113Sgblack@eecs.umich.edu cpsr.e = sctlr.ee; 5283113Sgblack@eecs.umich.edu 5293113Sgblack@eecs.umich.edu // The *Disable functions are virtual and different per fault 5303113Sgblack@eecs.umich.edu cpsr.a = cpsr.a | abortDisable(tc); 5318737Skoansin.tan@gmail.com cpsr.f = cpsr.f | fiqDisable(tc); 5323113Sgblack@eecs.umich.edu cpsr.i = 1; 5338737Skoansin.tan@gmail.com } 5343277Sgblack@eecs.umich.edu cpsr.it1 = cpsr.it2 = 0; 5355515SMichael.Adler@intel.com cpsr.j = 0; 5365515SMichael.Adler@intel.com tc->setMiscReg(MISCREG_CPSR, cpsr); 5375515SMichael.Adler@intel.com 5385515SMichael.Adler@intel.com // Make sure mailbox sets to one always 5395515SMichael.Adler@intel.com tc->setMiscReg(MISCREG_SEV_MAILBOX, 1); 5408737Skoansin.tan@gmail.com 5413277Sgblack@eecs.umich.edu // Clear the exclusive monitor 5428737Skoansin.tan@gmail.com tc->setMiscReg(MISCREG_LOCKFLAG, 0); 5433277Sgblack@eecs.umich.edu 5448737Skoansin.tan@gmail.com if (cpsr.mode == MODE_HYP) { 5453277Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_ELR_HYP, curPc + 5468737Skoansin.tan@gmail.com (saved_cpsr.t ? thumbPcOffset(true) : armPcOffset(true))); 5473113Sgblack@eecs.umich.edu } else { 5483113Sgblack@eecs.umich.edu tc->setIntReg(INTREG_LR, curPc + 5493113Sgblack@eecs.umich.edu (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false))); 5503113Sgblack@eecs.umich.edu } 5518737Skoansin.tan@gmail.com 5523113Sgblack@eecs.umich.edu switch (cpsr.mode) { 5538737Skoansin.tan@gmail.com case MODE_FIQ: 5543114Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr); 5558737Skoansin.tan@gmail.com break; 5563114Sgblack@eecs.umich.edu case MODE_IRQ: 5578737Skoansin.tan@gmail.com tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr); 5583114Sgblack@eecs.umich.edu break; 5598737Skoansin.tan@gmail.com case MODE_SVC: 56011906SBrandon.Potter@amd.com tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr); 5614061Sgblack@eecs.umich.edu break; 5624061Sgblack@eecs.umich.edu case MODE_MON: 5638737Skoansin.tan@gmail.com assert(have_security); 5643113Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr); 5658737Skoansin.tan@gmail.com break; 5663113Sgblack@eecs.umich.edu case MODE_ABORT: 5673113Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr); 5683113Sgblack@eecs.umich.edu break; 5693113Sgblack@eecs.umich.edu case MODE_UNDEFINED: 5703113Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr); 57112032Sandreas.sandberg@arm.com if (ec(tc) != EC_UNKNOWN) 5723113Sgblack@eecs.umich.edu setSyndrome(tc, MISCREG_HSR); 5733113Sgblack@eecs.umich.edu break; 5744189Sgblack@eecs.umich.edu case MODE_HYP: 5754189Sgblack@eecs.umich.edu assert(have_virtualization); 5763113Sgblack@eecs.umich.edu tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr); 5773113Sgblack@eecs.umich.edu setSyndrome(tc, MISCREG_HSR); 5783113Sgblack@eecs.umich.edu break; 5798737Skoansin.tan@gmail.com default: 5803113Sgblack@eecs.umich.edu panic("unknown Mode\n"); 5818737Skoansin.tan@gmail.com } 5823113Sgblack@eecs.umich.edu 5838737Skoansin.tan@gmail.com Addr newPc = getVector(tc); 5843113Sgblack@eecs.umich.edu DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x\n", 5853113Sgblack@eecs.umich.edu name(), cpsr, curPc, tc->readIntReg(INTREG_LR), newPc); 5863113Sgblack@eecs.umich.edu PCState pc(newPc); 5873113Sgblack@eecs.umich.edu pc.thumb(cpsr.t); 5883113Sgblack@eecs.umich.edu pc.nextThumb(pc.thumb()); 5893113Sgblack@eecs.umich.edu pc.jazelle(cpsr.j); 5903113Sgblack@eecs.umich.edu pc.nextJazelle(pc.jazelle()); 59111906SBrandon.Potter@amd.com pc.aarch64(!cpsr.width); 5923113Sgblack@eecs.umich.edu pc.nextAArch64(!cpsr.width); 59312032Sandreas.sandberg@arm.com tc->pcState(pc); 5948852Sandreas.hansson@arm.com} 59511906SBrandon.Potter@amd.com 5963113Sgblack@eecs.umich.eduvoid 5973113Sgblack@eecs.umich.eduArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst) 5983113Sgblack@eecs.umich.edu{ 5993113Sgblack@eecs.umich.edu // Determine actual misc. register indices for ELR_ELx and SPSR_ELx 6003113Sgblack@eecs.umich.edu MiscRegIndex elr_idx, spsr_idx; 6013113Sgblack@eecs.umich.edu switch (toEL) { 6023113Sgblack@eecs.umich.edu case EL1: 6033113Sgblack@eecs.umich.edu elr_idx = MISCREG_ELR_EL1; 60412032Sandreas.sandberg@arm.com spsr_idx = MISCREG_SPSR_EL1; 6058852Sandreas.hansson@arm.com break; 60611906SBrandon.Potter@amd.com case EL2: 6073113Sgblack@eecs.umich.edu assert(ArmSystem::haveVirtualization(tc)); 6083113Sgblack@eecs.umich.edu elr_idx = MISCREG_ELR_EL2; 6093113Sgblack@eecs.umich.edu spsr_idx = MISCREG_SPSR_EL2; 6106686Stjones1@inf.ed.ac.uk break; 6113113Sgblack@eecs.umich.edu case EL3: 6123113Sgblack@eecs.umich.edu assert(ArmSystem::haveSecurity(tc)); 6133113Sgblack@eecs.umich.edu elr_idx = MISCREG_ELR_EL3; 61411759Sbrandon.potter@amd.com spsr_idx = MISCREG_SPSR_EL3; 61512032Sandreas.sandberg@arm.com break; 61611759Sbrandon.potter@amd.com default: 61711759Sbrandon.potter@amd.com panic("Invalid target exception level"); 61811759Sbrandon.potter@amd.com break; 61911759Sbrandon.potter@amd.com } 62011759Sbrandon.potter@amd.com 62111812Sbaz21@cam.ac.uk // Save process state into SPSR_ELx 62211812Sbaz21@cam.ac.uk CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 62311812Sbaz21@cam.ac.uk CPSR spsr = cpsr; 62411759Sbrandon.potter@amd.com spsr.nz = tc->readCCReg(CCREG_NZ); 62511812Sbaz21@cam.ac.uk spsr.c = tc->readCCReg(CCREG_C); 62611759Sbrandon.potter@amd.com spsr.v = tc->readCCReg(CCREG_V); 62711759Sbrandon.potter@amd.com if (from64) { 62811759Sbrandon.potter@amd.com // Force some bitfields to 0 62911759Sbrandon.potter@amd.com spsr.q = 0; 63011759Sbrandon.potter@amd.com spsr.it1 = 0; 63111759Sbrandon.potter@amd.com spsr.j = 0; 63211759Sbrandon.potter@amd.com spsr.res0_23_22 = 0; 63311812Sbaz21@cam.ac.uk spsr.ge = 0; 63411812Sbaz21@cam.ac.uk spsr.it2 = 0; 63511812Sbaz21@cam.ac.uk spsr.t = 0; 63611812Sbaz21@cam.ac.uk } else { 63711812Sbaz21@cam.ac.uk spsr.ge = tc->readCCReg(CCREG_GE); 63811812Sbaz21@cam.ac.uk ITSTATE it = tc->pcState().itstate(); 63911812Sbaz21@cam.ac.uk spsr.it2 = it.top6; 64011759Sbrandon.potter@amd.com spsr.it1 = it.bottom2; 64111759Sbrandon.potter@amd.com // Force some bitfields to 0 64211812Sbaz21@cam.ac.uk spsr.res0_23_22 = 0; 64311812Sbaz21@cam.ac.uk spsr.ss = 0; 64411759Sbrandon.potter@amd.com } 64511812Sbaz21@cam.ac.uk tc->setMiscReg(spsr_idx, spsr); 64611812Sbaz21@cam.ac.uk 64711812Sbaz21@cam.ac.uk // Save preferred return address into ELR_ELx 64811812Sbaz21@cam.ac.uk Addr curr_pc = tc->pcState().pc(); 64911812Sbaz21@cam.ac.uk Addr ret_addr = curr_pc; 65011812Sbaz21@cam.ac.uk if (from64) 65111812Sbaz21@cam.ac.uk ret_addr += armPcElrOffset(); 65211759Sbrandon.potter@amd.com else 65311759Sbrandon.potter@amd.com ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset(); 65411759Sbrandon.potter@amd.com tc->setMiscReg(elr_idx, ret_addr); 65511759Sbrandon.potter@amd.com 656378SN/A Addr vec_address = getVector64(tc); 657378SN/A 6589141Smarc.orr@gmail.com // Update process state 6599141Smarc.orr@gmail.com OperatingMode64 mode = 0; 660360SN/A mode.spX = 1; 6611450SN/A mode.el = toEL; 66211856Sbrandon.potter@amd.com mode.width = 0; 663360SN/A cpsr.mode = mode; 6646701Sgblack@eecs.umich.edu cpsr.daif = 0xf; 66511856Sbrandon.potter@amd.com cpsr.il = 0; 66611856Sbrandon.potter@amd.com cpsr.ss = 0; 667360SN/A tc->setMiscReg(MISCREG_CPSR, cpsr); 66810930Sbrandon.potter@amd.com 669360SN/A // Set PC to start of exception handler 67011856Sbrandon.potter@amd.com Addr new_pc = purifyTaggedAddr(vec_address, tc, toEL); 67111856Sbrandon.potter@amd.com DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x " 67210496Ssteve.reinhardt@amd.com "elr:%#x newVec: %#x\n", name(), cpsr, curr_pc, ret_addr, new_pc); 67311856Sbrandon.potter@amd.com PCState pc(new_pc); 67411856Sbrandon.potter@amd.com pc.aarch64(!cpsr.width); 6751458SN/A pc.nextAArch64(!cpsr.width); 676360SN/A tc->pcState(pc); 67711856Sbrandon.potter@amd.com 67811856Sbrandon.potter@amd.com // If we have a valid instruction then use it to annotate this fault with 67911856Sbrandon.potter@amd.com // extra information. This is used to generate the correct fault syndrome 68011856Sbrandon.potter@amd.com // information 68111856Sbrandon.potter@amd.com if (inst) 68211856Sbrandon.potter@amd.com static_cast<ArmStaticInst *>(inst.get())->annotateFault(this); 68311856Sbrandon.potter@amd.com // Save exception syndrome 68411856Sbrandon.potter@amd.com if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ)) 68510496Ssteve.reinhardt@amd.com setSyndrome(tc, getSyndromeReg64()); 68611856Sbrandon.potter@amd.com} 68711856Sbrandon.potter@amd.com 68811856Sbrandon.potter@amd.comvoid 68911856Sbrandon.potter@amd.comReset::invoke(ThreadContext *tc, const StaticInstPtr &inst) 69011856Sbrandon.potter@amd.com{ 69110930Sbrandon.potter@amd.com if (FullSystem) { 6929141Smarc.orr@gmail.com tc->getCpuPtr()->clearInterrupts(tc->threadId()); 693360SN/A tc->clearArchRegs(); 694360SN/A } 695360SN/A if (!ArmSystem::highestELIs64(tc)) { 69611907SBrandon.Potter@amd.com ArmFault::invoke(tc, inst); 69711907SBrandon.Potter@amd.com tc->setMiscReg(MISCREG_VMPIDR, 69811907SBrandon.Potter@amd.com getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc)); 699360SN/A 70011907SBrandon.Potter@amd.com // Unless we have SMC code to get us there, boot in HYP! 70111907SBrandon.Potter@amd.com if (ArmSystem::haveVirtualization(tc) && 70211907SBrandon.Potter@amd.com !ArmSystem::haveSecurity(tc)) { 70311907SBrandon.Potter@amd.com CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 70411907SBrandon.Potter@amd.com cpsr.mode = MODE_HYP; 70511907SBrandon.Potter@amd.com tc->setMiscReg(MISCREG_CPSR, cpsr); 70611907SBrandon.Potter@amd.com } 70711907SBrandon.Potter@amd.com } else { 70811907SBrandon.Potter@amd.com // Advance the PC to the IMPLEMENTATION DEFINED reset value 70911907SBrandon.Potter@amd.com PCState pc = ArmSystem::resetAddr64(tc); 71011907SBrandon.Potter@amd.com pc.aarch64(true); 71111907SBrandon.Potter@amd.com pc.nextAArch64(true); 71211907SBrandon.Potter@amd.com tc->pcState(pc); 71311907SBrandon.Potter@amd.com } 714360SN/A} 71511907SBrandon.Potter@amd.com 7161458SN/Avoid 717360SN/AUndefinedInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst) 71811907SBrandon.Potter@amd.com{ 71911907SBrandon.Potter@amd.com if (FullSystem) { 72011907SBrandon.Potter@amd.com ArmFault::invoke(tc, inst); 72111907SBrandon.Potter@amd.com return; 72211907SBrandon.Potter@amd.com } 72311907SBrandon.Potter@amd.com 72411907SBrandon.Potter@amd.com // If the mnemonic isn't defined this has to be an unknown instruction. 72511907SBrandon.Potter@amd.com assert(unknown || mnemonic != NULL); 72611907SBrandon.Potter@amd.com if (disabled) { 72711907SBrandon.Potter@amd.com panic("Attempted to execute disabled instruction " 728360SN/A "'%s' (inst 0x%08x)", mnemonic, machInst); 72911907SBrandon.Potter@amd.com } else if (unknown) { 73011907SBrandon.Potter@amd.com panic("Attempted to execute unknown instruction (inst 0x%08x)", 73111907SBrandon.Potter@amd.com machInst); 732360SN/A } else { 733360SN/A panic("Attempted to execute unimplemented instruction " 73411907SBrandon.Potter@amd.com "'%s' (inst 0x%08x)", mnemonic, machInst); 73511907SBrandon.Potter@amd.com } 73611907SBrandon.Potter@amd.com} 73711907SBrandon.Potter@amd.com 738360SN/Abool 73911907SBrandon.Potter@amd.comUndefinedInstruction::routeToHyp(ThreadContext *tc) const 740360SN/A{ 741360SN/A bool toHyp; 74211907SBrandon.Potter@amd.com 7433669Sbinkertn@umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 74411907SBrandon.Potter@amd.com HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 74511907SBrandon.Potter@amd.com CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 74611907SBrandon.Potter@amd.com 74711907SBrandon.Potter@amd.com // if in Hyp mode then stay in Hyp mode 74811907SBrandon.Potter@amd.com toHyp = scr.ns && (cpsr.mode == MODE_HYP); 74911907SBrandon.Potter@amd.com // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector 75011907SBrandon.Potter@amd.com toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER); 75111907SBrandon.Potter@amd.com return toHyp; 75211907SBrandon.Potter@amd.com} 75311907SBrandon.Potter@amd.com 75411907SBrandon.Potter@amd.comuint32_t 75511907SBrandon.Potter@amd.comUndefinedInstruction::iss() const 75611907SBrandon.Potter@amd.com{ 75711907SBrandon.Potter@amd.com 75811907SBrandon.Potter@amd.com // If UndefinedInstruction is routed to hypervisor, iss field is 0. 75911907SBrandon.Potter@amd.com if (hypRouted) { 76011907SBrandon.Potter@amd.com return 0; 76111907SBrandon.Potter@amd.com } 76211907SBrandon.Potter@amd.com 76313371Sciro.santilli@arm.com if (overrideEc == EC_INVALID) 76411907SBrandon.Potter@amd.com return issRaw; 7651706SN/A 76611907SBrandon.Potter@amd.com uint32_t new_iss = 0; 76711907SBrandon.Potter@amd.com uint32_t op0, op1, op2, CRn, CRm, Rt, dir; 76811907SBrandon.Potter@amd.com 76911907SBrandon.Potter@amd.com dir = bits(machInst, 21, 21); 77011907SBrandon.Potter@amd.com op0 = bits(machInst, 20, 19); 77111907SBrandon.Potter@amd.com op1 = bits(machInst, 18, 16); 77210496Ssteve.reinhardt@amd.com CRn = bits(machInst, 15, 12); 77310496Ssteve.reinhardt@amd.com CRm = bits(machInst, 11, 8); 77411907SBrandon.Potter@amd.com op2 = bits(machInst, 7, 5); 77511907SBrandon.Potter@amd.com Rt = bits(machInst, 4, 0); 77611907SBrandon.Potter@amd.com 77711907SBrandon.Potter@amd.com new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 | 77811907SBrandon.Potter@amd.com Rt << 5 | CRm << 1 | dir; 77911907SBrandon.Potter@amd.com 78010496Ssteve.reinhardt@amd.com return new_iss; 78111907SBrandon.Potter@amd.com} 78211907SBrandon.Potter@amd.com 78311907SBrandon.Potter@amd.comvoid 78411907SBrandon.Potter@amd.comSupervisorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst) 78510496Ssteve.reinhardt@amd.com{ 78610496Ssteve.reinhardt@amd.com if (FullSystem) { 78711907SBrandon.Potter@amd.com ArmFault::invoke(tc, inst); 78811907SBrandon.Potter@amd.com return; 78911907SBrandon.Potter@amd.com } 79011907SBrandon.Potter@amd.com 79111907SBrandon.Potter@amd.com // As of now, there isn't a 32 bit thumb version of this instruction. 79211907SBrandon.Potter@amd.com assert(!machInst.bigThumb); 79311907SBrandon.Potter@amd.com uint32_t callNum; 79411907SBrandon.Potter@amd.com CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 79511907SBrandon.Potter@amd.com OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode; 79611907SBrandon.Potter@amd.com if (opModeIs64(mode)) 79711907SBrandon.Potter@amd.com callNum = tc->readIntReg(INTREG_X8); 79811907SBrandon.Potter@amd.com else 79911907SBrandon.Potter@amd.com callNum = tc->readIntReg(INTREG_R7); 80011907SBrandon.Potter@amd.com Fault fault; 80111907SBrandon.Potter@amd.com tc->syscall(callNum, &fault); 80211907SBrandon.Potter@amd.com 80311907SBrandon.Potter@amd.com // Advance the PC since that won't happen automatically. 80411907SBrandon.Potter@amd.com PCState pc = tc->pcState(); 80511907SBrandon.Potter@amd.com assert(inst); 80611907SBrandon.Potter@amd.com inst->advancePC(pc); 80711907SBrandon.Potter@amd.com tc->pcState(pc); 80811907SBrandon.Potter@amd.com} 80911907SBrandon.Potter@amd.com 81011907SBrandon.Potter@amd.combool 81111907SBrandon.Potter@amd.comSupervisorCall::routeToHyp(ThreadContext *tc) const 812360SN/A{ 81311907SBrandon.Potter@amd.com bool toHyp; 81411907SBrandon.Potter@amd.com 81511907SBrandon.Potter@amd.com SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 81611907SBrandon.Potter@amd.com HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 81711907SBrandon.Potter@amd.com CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 81811907SBrandon.Potter@amd.com 81911907SBrandon.Potter@amd.com // if in Hyp mode then stay in Hyp mode 82011907SBrandon.Potter@amd.com toHyp = scr.ns && (cpsr.mode == MODE_HYP); 82111907SBrandon.Potter@amd.com // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector 82211907SBrandon.Potter@amd.com toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.mode == MODE_USER); 82311907SBrandon.Potter@amd.com return toHyp; 82411907SBrandon.Potter@amd.com} 82511907SBrandon.Potter@amd.com 826360SN/AExceptionClass 827360SN/ASupervisorCall::ec(ThreadContext *tc) const 82810027SChris.Adeniyi-Jones@arm.com{ 82910027SChris.Adeniyi-Jones@arm.com return (overrideEc != EC_INVALID) ? overrideEc : 83010027SChris.Adeniyi-Jones@arm.com (from64 ? EC_SVC_64 : vals.ec); 83111851Sbrandon.potter@amd.com} 83210027SChris.Adeniyi-Jones@arm.com 83310027SChris.Adeniyi-Jones@arm.comuint32_t 83411907SBrandon.Potter@amd.comSupervisorCall::iss() const 83510027SChris.Adeniyi-Jones@arm.com{ 83610027SChris.Adeniyi-Jones@arm.com // Even if we have a 24 bit imm from an arm32 instruction then we only use 83710027SChris.Adeniyi-Jones@arm.com // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC). 83810027SChris.Adeniyi-Jones@arm.com return issRaw & 0xFFFF; 83910027SChris.Adeniyi-Jones@arm.com} 84011851Sbrandon.potter@amd.com 84111851Sbrandon.potter@amd.comuint32_t 84210027SChris.Adeniyi-Jones@arm.comSecureMonitorCall::iss() const 84311907SBrandon.Potter@amd.com{ 84410027SChris.Adeniyi-Jones@arm.com if (from64) 84510027SChris.Adeniyi-Jones@arm.com return bits(machInst, 20, 5); 84610633Smichaelupton@gmail.com return 0; 84710633Smichaelupton@gmail.com} 84810633Smichaelupton@gmail.com 84911851Sbrandon.potter@amd.comExceptionClass 85010633Smichaelupton@gmail.comUndefinedInstruction::ec(ThreadContext *tc) const 85110633Smichaelupton@gmail.com{ 85210633Smichaelupton@gmail.com // If UndefinedInstruction is routed to hypervisor, 85310633Smichaelupton@gmail.com // HSR.EC field is 0. 85410633Smichaelupton@gmail.com if (hypRouted) 85510633Smichaelupton@gmail.com return EC_UNKNOWN; 85610633Smichaelupton@gmail.com else 85710633Smichaelupton@gmail.com return (overrideEc != EC_INVALID) ? overrideEc : vals.ec; 85810633Smichaelupton@gmail.com} 85910633Smichaelupton@gmail.com 86010203SAli.Saidi@ARM.com 86110203SAli.Saidi@ARM.comHypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) : 86210203SAli.Saidi@ARM.com ArmFaultVals<HypervisorCall>(_machInst, _imm) 86311851Sbrandon.potter@amd.com{} 86411851Sbrandon.potter@amd.com 86510203SAli.Saidi@ARM.comExceptionClass 86610203SAli.Saidi@ARM.comHypervisorCall::ec(ThreadContext *tc) const 86710203SAli.Saidi@ARM.com{ 86810203SAli.Saidi@ARM.com return from64 ? EC_HVC_64 : vals.ec; 86910203SAli.Saidi@ARM.com} 87010203SAli.Saidi@ARM.com 87110203SAli.Saidi@ARM.comExceptionClass 87210203SAli.Saidi@ARM.comHypervisorTrap::ec(ThreadContext *tc) const 87310203SAli.Saidi@ARM.com{ 87410203SAli.Saidi@ARM.com return (overrideEc != EC_INVALID) ? overrideEc : vals.ec; 87510203SAli.Saidi@ARM.com} 87611851Sbrandon.potter@amd.com 87711851Sbrandon.potter@amd.comtemplate<class T> 87810203SAli.Saidi@ARM.comFaultOffset 87910203SAli.Saidi@ARM.comArmFaultVals<T>::offset(ThreadContext *tc) 88010203SAli.Saidi@ARM.com{ 88110203SAli.Saidi@ARM.com bool isHypTrap = false; 88210203SAli.Saidi@ARM.com 88310203SAli.Saidi@ARM.com // Normally we just use the exception vector from the table at the top if 88410203SAli.Saidi@ARM.com // this file, however if this exception has caused a transition to hype 88510203SAli.Saidi@ARM.com // mode, and its an exception type that would only do this if it has been 88610850SGiacomo.Gabrielli@arm.com // trapped then we use the hyp trap vector instead of the normal vector 88710850SGiacomo.Gabrielli@arm.com if (vals.hypTrappable) { 88810850SGiacomo.Gabrielli@arm.com CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 88911851Sbrandon.potter@amd.com if (cpsr.mode == MODE_HYP) { 89010850SGiacomo.Gabrielli@arm.com CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP); 89110850SGiacomo.Gabrielli@arm.com isHypTrap = spsr.mode != MODE_HYP; 89210850SGiacomo.Gabrielli@arm.com } 89310850SGiacomo.Gabrielli@arm.com } 89410850SGiacomo.Gabrielli@arm.com return isHypTrap ? 0x14 : vals.offset; 89510850SGiacomo.Gabrielli@arm.com} 89610850SGiacomo.Gabrielli@arm.com 89710850SGiacomo.Gabrielli@arm.comtemplate<class T> 89810850SGiacomo.Gabrielli@arm.comFaultOffset 89910850SGiacomo.Gabrielli@arm.comArmFaultVals<T>::offset64(ThreadContext *tc) 90010850SGiacomo.Gabrielli@arm.com{ 90110850SGiacomo.Gabrielli@arm.com if (toEL == fromEL) { 90210850SGiacomo.Gabrielli@arm.com if (opModeIsT(fromMode)) 90310850SGiacomo.Gabrielli@arm.com return vals.currELTOffset; 90410850SGiacomo.Gabrielli@arm.com return vals.currELHOffset; 90510850SGiacomo.Gabrielli@arm.com } else { 90610850SGiacomo.Gabrielli@arm.com bool lower_32 = false; 90710850SGiacomo.Gabrielli@arm.com if (toEL == EL3) { 90810850SGiacomo.Gabrielli@arm.com if (!inSecureState(tc) && ArmSystem::haveEL(tc, EL2)) 90910850SGiacomo.Gabrielli@arm.com lower_32 = ELIs32(tc, EL2); 91010850SGiacomo.Gabrielli@arm.com else 91110850SGiacomo.Gabrielli@arm.com lower_32 = ELIs32(tc, EL1); 91210850SGiacomo.Gabrielli@arm.com } else { 91310850SGiacomo.Gabrielli@arm.com lower_32 = ELIs32(tc, static_cast<ExceptionLevel>(toEL - 1)); 91410850SGiacomo.Gabrielli@arm.com } 91510850SGiacomo.Gabrielli@arm.com 91610850SGiacomo.Gabrielli@arm.com if (lower_32) 91710850SGiacomo.Gabrielli@arm.com return vals.lowerEL32Offset; 91810850SGiacomo.Gabrielli@arm.com return vals.lowerEL64Offset; 91910850SGiacomo.Gabrielli@arm.com } 92010850SGiacomo.Gabrielli@arm.com} 92110850SGiacomo.Gabrielli@arm.com 9226640Svince@csl.cornell.edu// void 9236640Svince@csl.cornell.edu// SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx) 9246640Svince@csl.cornell.edu// { 92511851Sbrandon.potter@amd.com// ESR esr = 0; 92611851Sbrandon.potter@amd.com// esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32; 9276640Svince@csl.cornell.edu// esr.il = !machInst.thumb; 9286640Svince@csl.cornell.edu// if (machInst.aarch64) 9296701Sgblack@eecs.umich.edu// esr.imm16 = bits(machInst.instBits, 20, 5); 9306701Sgblack@eecs.umich.edu// else if (machInst.thumb) 93110793Sbrandon.potter@amd.com// esr.imm16 = bits(machInst.instBits, 7, 0); 9326640Svince@csl.cornell.edu// else 93311758Sbrandon.potter@amd.com// esr.imm16 = bits(machInst.instBits, 15, 0); 93411758Sbrandon.potter@amd.com// tc->setMiscReg(esr_idx, esr); 93511758Sbrandon.potter@amd.com// } 9366640Svince@csl.cornell.edu 9378706Sandreas.hansson@arm.comvoid 9386640Svince@csl.cornell.eduSecureMonitorCall::invoke(ThreadContext *tc, const StaticInstPtr &inst) 9396701Sgblack@eecs.umich.edu{ 9406640Svince@csl.cornell.edu if (FullSystem) { 941360SN/A ArmFault::invoke(tc, inst); 9421999SN/A return; 9431999SN/A } 9441999SN/A} 94511851Sbrandon.potter@amd.com 9462680Sktlim@umich.eduExceptionClass 9471999SN/ASecureMonitorCall::ec(ThreadContext *tc) const 9481999SN/A{ 9491999SN/A return (from64 ? EC_SMC_64 : vals.ec); 9506701Sgblack@eecs.umich.edu} 9518852Sandreas.hansson@arm.com 9526701Sgblack@eecs.umich.edubool 9531999SN/ASupervisorTrap::routeToHyp(ThreadContext *tc) const 9546701Sgblack@eecs.umich.edu{ 9551999SN/A bool toHyp = false; 9566701Sgblack@eecs.umich.edu 9571999SN/A SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 9581999SN/A HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2); 9591999SN/A CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 9601999SN/A 9611999SN/A // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector 9623669Sbinkertn@umich.edu toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.el == EL0); 9633669Sbinkertn@umich.edu return toHyp; 9643669Sbinkertn@umich.edu} 9651999SN/A 9661999SN/Auint32_t 9671999SN/ASupervisorTrap::iss() const 9682218SN/A{ 9691999SN/A // If SupervisorTrap is routed to hypervisor, iss field is 0. 9701999SN/A if (hypRouted) { 9711999SN/A return 0; 9721999SN/A } 97313570Sbrandon.potter@amd.com return issRaw; 97413570Sbrandon.potter@amd.com} 97513570Sbrandon.potter@amd.com 97613570Sbrandon.potter@amd.comExceptionClass 97713570Sbrandon.potter@amd.comSupervisorTrap::ec(ThreadContext *tc) const 97813570Sbrandon.potter@amd.com{ 97913570Sbrandon.potter@amd.com if (hypRouted) 98013570Sbrandon.potter@amd.com return EC_UNKNOWN; 98113570Sbrandon.potter@amd.com else 98213570Sbrandon.potter@amd.com return (overrideEc != EC_INVALID) ? overrideEc : vals.ec; 98313570Sbrandon.potter@amd.com} 98413570Sbrandon.potter@amd.com 98513570Sbrandon.potter@amd.comExceptionClass 98613570Sbrandon.potter@amd.comSecureMonitorTrap::ec(ThreadContext *tc) const 98713570Sbrandon.potter@amd.com{ 98813570Sbrandon.potter@amd.com return (overrideEc != EC_INVALID) ? overrideEc : 98913570Sbrandon.potter@amd.com (from64 ? EC_SMC_64 : vals.ec); 99013570Sbrandon.potter@amd.com} 99113570Sbrandon.potter@amd.com 99213570Sbrandon.potter@amd.comtemplate<class T> 99313570Sbrandon.potter@amd.comvoid 99413570Sbrandon.potter@amd.comAbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst) 99513570Sbrandon.potter@amd.com{ 99613570Sbrandon.potter@amd.com if (tranMethod == ArmFault::UnknownTran) { 99713570Sbrandon.potter@amd.com tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran 99813570Sbrandon.potter@amd.com : ArmFault::VmsaTran; 99913570Sbrandon.potter@amd.com 100013570Sbrandon.potter@amd.com if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) { 100113570Sbrandon.potter@amd.com // See ARM ARM B3-1416 100213570Sbrandon.potter@amd.com bool override_LPAE = false; 100313570Sbrandon.potter@amd.com TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S); 100413570Sbrandon.potter@amd.com TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS); 100513570Sbrandon.potter@amd.com if (ttbcr_s.eae) { 100613570Sbrandon.potter@amd.com override_LPAE = true; 100713570Sbrandon.potter@amd.com } else { 100813570Sbrandon.potter@amd.com // Unimplemented code option, not seen in testing. May need 100913570Sbrandon.potter@amd.com // extension according to the manual exceprt above. 101013570Sbrandon.potter@amd.com DPRINTF(Faults, "Warning: Incomplete translation method " 101113570Sbrandon.potter@amd.com "override detected.\n"); 101213570Sbrandon.potter@amd.com } 101313570Sbrandon.potter@amd.com if (override_LPAE) 101413570Sbrandon.potter@amd.com tranMethod = ArmFault::LpaeTran; 101513570Sbrandon.potter@amd.com } 101613570Sbrandon.potter@amd.com } 101713570Sbrandon.potter@amd.com 101813570Sbrandon.potter@amd.com if (source == ArmFault::AsynchronousExternalAbort) { 101913570Sbrandon.potter@amd.com tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0); 102013570Sbrandon.potter@amd.com } 102113570Sbrandon.potter@amd.com // Get effective fault source encoding 102213570Sbrandon.potter@amd.com CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 102313570Sbrandon.potter@amd.com FSR fsr = getFsr(tc); 102413570Sbrandon.potter@amd.com 102513570Sbrandon.potter@amd.com // source must be determined BEFORE invoking generic routines which will 102613570Sbrandon.potter@amd.com // try to set hsr etc. and are based upon source! 102713570Sbrandon.potter@amd.com ArmFaultVals<T>::invoke(tc, inst); 102813570Sbrandon.potter@amd.com 102913570Sbrandon.potter@amd.com if (!this->to64) { // AArch32 103013570Sbrandon.potter@amd.com if (cpsr.mode == MODE_HYP) { 103113570Sbrandon.potter@amd.com tc->setMiscReg(T::HFarIndex, faultAddr); 103213570Sbrandon.potter@amd.com } else if (stage2) { 103313570Sbrandon.potter@amd.com tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf); 103413570Sbrandon.potter@amd.com tc->setMiscReg(T::HFarIndex, OVAddr); 103513570Sbrandon.potter@amd.com } else { 103613570Sbrandon.potter@amd.com tc->setMiscReg(T::FsrIndex, fsr); 103713570Sbrandon.potter@amd.com tc->setMiscReg(T::FarIndex, faultAddr); 103813570Sbrandon.potter@amd.com } 103913570Sbrandon.potter@amd.com DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\ 104013570Sbrandon.potter@amd.com "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod); 104113570Sbrandon.potter@amd.com } else { // AArch64 104213570Sbrandon.potter@amd.com // Set the FAR register. Nothing else to do if we are in AArch64 state 104313570Sbrandon.potter@amd.com // because the syndrome register has already been set inside invoke64() 104413570Sbrandon.potter@amd.com if (stage2) { 104513570Sbrandon.potter@amd.com // stage 2 fault, set HPFAR_EL2 to the faulting IPA 104613570Sbrandon.potter@amd.com // and FAR_EL2 to the Original VA 10471999SN/A tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr); 10481999SN/A tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4); 10491999SN/A 10501999SN/A DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n", 105111856Sbrandon.potter@amd.com OVAddr, faultAddr); 10521999SN/A } else { 10536701Sgblack@eecs.umich.edu tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr); 105411856Sbrandon.potter@amd.com } 105511856Sbrandon.potter@amd.com } 105610931Sbrandon.potter@amd.com} 105711856Sbrandon.potter@amd.com 105811856Sbrandon.potter@amd.comtemplate<class T> 10591999SN/AFSR 106011856Sbrandon.potter@amd.comAbortFault<T>::getFsr(ThreadContext *tc) 10611999SN/A{ 106211856Sbrandon.potter@amd.com FSR fsr = 0; 10631999SN/A 106411856Sbrandon.potter@amd.com if (((CPSR) tc->readMiscRegNoEffect(MISCREG_CPSR)).width) { 10651999SN/A // AArch32 106611856Sbrandon.potter@amd.com assert(tranMethod != ArmFault::UnknownTran); 10671999SN/A if (tranMethod == ArmFault::LpaeTran) { 10681999SN/A srcEncoded = ArmFault::longDescFaultSources[source]; 10695877Shsul@eecs.umich.edu fsr.status = srcEncoded; 10705877Shsul@eecs.umich.edu fsr.lpae = 1; 10715877Shsul@eecs.umich.edu } else { 107211851Sbrandon.potter@amd.com srcEncoded = ArmFault::shortDescFaultSources[source]; 10735877Shsul@eecs.umich.edu fsr.fsLow = bits(srcEncoded, 3, 0); 10746701Sgblack@eecs.umich.edu fsr.fsHigh = bits(srcEncoded, 4); 10756701Sgblack@eecs.umich.edu fsr.domain = static_cast<uint8_t>(domain); 10766701Sgblack@eecs.umich.edu } 10776701Sgblack@eecs.umich.edu fsr.wnr = (write ? 1 : 0); 10786701Sgblack@eecs.umich.edu fsr.ext = 0; 107910027SChris.Adeniyi-Jones@arm.com } else { 108010027SChris.Adeniyi-Jones@arm.com // AArch64 108110027SChris.Adeniyi-Jones@arm.com srcEncoded = ArmFault::aarch64FaultSources[source]; 108210027SChris.Adeniyi-Jones@arm.com } 108310027SChris.Adeniyi-Jones@arm.com if (srcEncoded == ArmFault::FaultSourceInvalid) { 10845877Shsul@eecs.umich.edu panic("Invalid fault source\n"); 108510318Sandreas.hansson@arm.com } 108610318Sandreas.hansson@arm.com return fsr; 10875877Shsul@eecs.umich.edu} 10885877Shsul@eecs.umich.edu 10895877Shsul@eecs.umich.edutemplate<class T> 10905877Shsul@eecs.umich.edubool 109110486Stjablin@gmail.comAbortFault<T>::abortDisable(ThreadContext *tc) 109210486Stjablin@gmail.com{ 10935877Shsul@eecs.umich.edu if (ArmSystem::haveSecurity(tc)) { 109411905SBrandon.Potter@amd.com SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 109511905SBrandon.Potter@amd.com return (!scr.ns || scr.aw); 109611905SBrandon.Potter@amd.com } 109711905SBrandon.Potter@amd.com return true; 109810027SChris.Adeniyi-Jones@arm.com} 109912206Srico.amslinger@informatik.uni-augsburg.de 110012206Srico.amslinger@informatik.uni-augsburg.detemplate<class T> 11015877Shsul@eecs.umich.eduvoid 110211905SBrandon.Potter@amd.comAbortFault<T>::annotate(ArmFault::AnnotationIDs id, uint64_t val) 110311905SBrandon.Potter@amd.com{ 11045877Shsul@eecs.umich.edu switch (id) 11055877Shsul@eecs.umich.edu { 110610027SChris.Adeniyi-Jones@arm.com case ArmFault::S1PTW: 11075877Shsul@eecs.umich.edu s1ptw = val; 11085877Shsul@eecs.umich.edu break; 11095877Shsul@eecs.umich.edu case ArmFault::OVA: 111012206Srico.amslinger@informatik.uni-augsburg.de OVAddr = val; 111112206Srico.amslinger@informatik.uni-augsburg.de break; 111212206Srico.amslinger@informatik.uni-augsburg.de 111312206Srico.amslinger@informatik.uni-augsburg.de // Just ignore unknown ID's 111412206Srico.amslinger@informatik.uni-augsburg.de default: 111512206Srico.amslinger@informatik.uni-augsburg.de break; 111612206Srico.amslinger@informatik.uni-augsburg.de } 111712206Srico.amslinger@informatik.uni-augsburg.de} 111812206Srico.amslinger@informatik.uni-augsburg.de 111910027SChris.Adeniyi-Jones@arm.comtemplate<class T> 112010027SChris.Adeniyi-Jones@arm.comuint32_t 112110027SChris.Adeniyi-Jones@arm.comAbortFault<T>::iss() const 112210027SChris.Adeniyi-Jones@arm.com{ 11235877Shsul@eecs.umich.edu uint32_t val; 112410027SChris.Adeniyi-Jones@arm.com 112510027SChris.Adeniyi-Jones@arm.com val = srcEncoded & 0x3F; 112610027SChris.Adeniyi-Jones@arm.com val |= write << 6; 112710027SChris.Adeniyi-Jones@arm.com val |= s1ptw << 7; 112812206Srico.amslinger@informatik.uni-augsburg.de return (val); 112912206Srico.amslinger@informatik.uni-augsburg.de} 113012206Srico.amslinger@informatik.uni-augsburg.de 113112206Srico.amslinger@informatik.uni-augsburg.detemplate<class T> 113210027SChris.Adeniyi-Jones@arm.combool 113310027SChris.Adeniyi-Jones@arm.comAbortFault<T>::isMMUFault() const 113410027SChris.Adeniyi-Jones@arm.com{ 113510027SChris.Adeniyi-Jones@arm.com // NOTE: Not relying on LL information being aligned to lowest bits here 113610027SChris.Adeniyi-Jones@arm.com return 113710027SChris.Adeniyi-Jones@arm.com (source == ArmFault::AlignmentFault) || 11385877Shsul@eecs.umich.edu ((source >= ArmFault::TranslationLL) && 11395877Shsul@eecs.umich.edu (source < ArmFault::TranslationLL + 4)) || 11405877Shsul@eecs.umich.edu ((source >= ArmFault::AccessFlagLL) && 114110027SChris.Adeniyi-Jones@arm.com (source < ArmFault::AccessFlagLL + 4)) || 114210027SChris.Adeniyi-Jones@arm.com ((source >= ArmFault::DomainLL) && 11438601Ssteve.reinhardt@amd.com (source < ArmFault::DomainLL + 4)) || 114410027SChris.Adeniyi-Jones@arm.com ((source >= ArmFault::PermissionLL) && 11455877Shsul@eecs.umich.edu (source < ArmFault::PermissionLL + 4)); 11465877Shsul@eecs.umich.edu} 11471999SN/A 1148378SN/AExceptionClass 1149360SN/APrefetchAbort::ec(ThreadContext *tc) const 11501450SN/A{ 115111851Sbrandon.potter@amd.com if (to64) { 11522680Sktlim@umich.edu // AArch64 1153360SN/A if (toEL == fromEL) 1154360SN/A return EC_PREFETCH_ABORT_CURR_EL; 1155360SN/A else 11566701Sgblack@eecs.umich.edu return EC_PREFETCH_ABORT_LOWER_EL; 11578852Sandreas.hansson@arm.com } else { 11586701Sgblack@eecs.umich.edu // AArch32 11596701Sgblack@eecs.umich.edu // Abort faults have different EC codes depending on whether 11606701Sgblack@eecs.umich.edu // the fault originated within HYP mode, or not. So override 11616701Sgblack@eecs.umich.edu // the method and add the extra adjustment of the EC value. 1162360SN/A 11633669Sbinkertn@umich.edu ExceptionClass ec = ArmFaultVals<PrefetchAbort>::vals.ec; 11643669Sbinkertn@umich.edu 11653669Sbinkertn@umich.edu CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP); 1166360SN/A if (spsr.mode == MODE_HYP) { 1167360SN/A ec = ((ExceptionClass) (((uint32_t) ec) + 1)); 1168360SN/A } 1169360SN/A return ec; 11702218SN/A } 1171360SN/A} 11728706Sandreas.hansson@arm.com 1173360SN/Abool 11741458SN/APrefetchAbort::routeToMonitor(ThreadContext *tc) const 1175360SN/A{ 1176360SN/A SCR scr = 0; 1177360SN/A if (from64) 11785074Ssaidi@eecs.umich.edu scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 11795074Ssaidi@eecs.umich.edu else 11805074Ssaidi@eecs.umich.edu scr = tc->readMiscRegNoEffect(MISCREG_SCR); 118111851Sbrandon.potter@amd.com 11825074Ssaidi@eecs.umich.edu return scr.ea && !isMMUFault(); 11835074Ssaidi@eecs.umich.edu} 11845074Ssaidi@eecs.umich.edu 11855074Ssaidi@eecs.umich.edubool 11866701Sgblack@eecs.umich.eduPrefetchAbort::routeToHyp(ThreadContext *tc) const 11878852Sandreas.hansson@arm.com{ 11886701Sgblack@eecs.umich.edu bool toHyp; 11895074Ssaidi@eecs.umich.edu 11906701Sgblack@eecs.umich.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 11915074Ssaidi@eecs.umich.edu HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 11925074Ssaidi@eecs.umich.edu CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 11935074Ssaidi@eecs.umich.edu HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR); 11945074Ssaidi@eecs.umich.edu 11955208Ssaidi@eecs.umich.edu // if in Hyp mode then stay in Hyp mode 11965208Ssaidi@eecs.umich.edu toHyp = scr.ns && (cpsr.mode == MODE_HYP); 11975208Ssaidi@eecs.umich.edu // otherwise, check whether to take to Hyp mode through Hyp Trap vector 11985208Ssaidi@eecs.umich.edu toHyp |= (stage2 || 11995074Ssaidi@eecs.umich.edu ( (source == DebugEvent) && hdcr.tde && (cpsr.mode != MODE_HYP)) || 12005074Ssaidi@eecs.umich.edu ( (source == SynchronousExternalAbort) && hcr.tge && (cpsr.mode == MODE_USER)) 12015208Ssaidi@eecs.umich.edu ) && !inSecureState(tc); 12025074Ssaidi@eecs.umich.edu return toHyp; 12035074Ssaidi@eecs.umich.edu} 12045074Ssaidi@eecs.umich.edu 12055074Ssaidi@eecs.umich.eduExceptionClass 12068706Sandreas.hansson@arm.comDataAbort::ec(ThreadContext *tc) const 12075074Ssaidi@eecs.umich.edu{ 12085074Ssaidi@eecs.umich.edu if (to64) { 12095074Ssaidi@eecs.umich.edu // AArch64 12105074Ssaidi@eecs.umich.edu if (source == ArmFault::AsynchronousExternalAbort) { 12115074Ssaidi@eecs.umich.edu panic("Asynchronous External Abort should be handled with " 121210027SChris.Adeniyi-Jones@arm.com "SystemErrors (SErrors)!"); 121310027SChris.Adeniyi-Jones@arm.com } 121410027SChris.Adeniyi-Jones@arm.com if (toEL == fromEL) 121511851Sbrandon.potter@amd.com return EC_DATA_ABORT_CURR_EL; 121610027SChris.Adeniyi-Jones@arm.com else 121710027SChris.Adeniyi-Jones@arm.com return EC_DATA_ABORT_LOWER_EL; 121810027SChris.Adeniyi-Jones@arm.com } else { 121910027SChris.Adeniyi-Jones@arm.com // AArch32 122010027SChris.Adeniyi-Jones@arm.com // Abort faults have different EC codes depending on whether 122110793Sbrandon.potter@amd.com // the fault originated within HYP mode, or not. So override 122210027SChris.Adeniyi-Jones@arm.com // the method and add the extra adjustment of the EC value. 122310027SChris.Adeniyi-Jones@arm.com 122410027SChris.Adeniyi-Jones@arm.com ExceptionClass ec = ArmFaultVals<DataAbort>::vals.ec; 122510027SChris.Adeniyi-Jones@arm.com 122610027SChris.Adeniyi-Jones@arm.com CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP); 122710027SChris.Adeniyi-Jones@arm.com if (spsr.mode == MODE_HYP) { 122810027SChris.Adeniyi-Jones@arm.com ec = ((ExceptionClass) (((uint32_t) ec) + 1)); 122910027SChris.Adeniyi-Jones@arm.com } 123010027SChris.Adeniyi-Jones@arm.com return ec; 123110027SChris.Adeniyi-Jones@arm.com } 123210027SChris.Adeniyi-Jones@arm.com} 123310027SChris.Adeniyi-Jones@arm.com 123410027SChris.Adeniyi-Jones@arm.combool 123510027SChris.Adeniyi-Jones@arm.comDataAbort::routeToMonitor(ThreadContext *tc) const 123610027SChris.Adeniyi-Jones@arm.com{ 123710027SChris.Adeniyi-Jones@arm.com SCR scr = 0; 123810027SChris.Adeniyi-Jones@arm.com if (from64) 123910027SChris.Adeniyi-Jones@arm.com scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 124010027SChris.Adeniyi-Jones@arm.com else 124110027SChris.Adeniyi-Jones@arm.com scr = tc->readMiscRegNoEffect(MISCREG_SCR); 124210027SChris.Adeniyi-Jones@arm.com 124310027SChris.Adeniyi-Jones@arm.com return scr.ea && !isMMUFault(); 124410027SChris.Adeniyi-Jones@arm.com} 124510027SChris.Adeniyi-Jones@arm.com 124610027SChris.Adeniyi-Jones@arm.combool 124710027SChris.Adeniyi-Jones@arm.comDataAbort::routeToHyp(ThreadContext *tc) const 124810027SChris.Adeniyi-Jones@arm.com{ 12491999SN/A bool toHyp; 12501999SN/A 12511999SN/A SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 125211856Sbrandon.potter@amd.com HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 12531999SN/A CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 12546701Sgblack@eecs.umich.edu HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR); 125511856Sbrandon.potter@amd.com 125611856Sbrandon.potter@amd.com // if in Hyp mode then stay in Hyp mode 125710931Sbrandon.potter@amd.com toHyp = scr.ns && (cpsr.mode == MODE_HYP); 125811856Sbrandon.potter@amd.com // otherwise, check whether to take to Hyp mode through Hyp Trap vector 125911856Sbrandon.potter@amd.com toHyp |= (stage2 || 12601999SN/A ( (cpsr.mode != MODE_HYP) && ( ((source == AsynchronousExternalAbort) && hcr.amo) || 126111856Sbrandon.potter@amd.com ((source == DebugEvent) && hdcr.tde) ) 12621999SN/A ) || 12632764Sstever@eecs.umich.edu ( (cpsr.mode == MODE_USER) && hcr.tge && 12642064SN/A ((source == AlignmentFault) || 126510931Sbrandon.potter@amd.com (source == SynchronousExternalAbort)) 12662064SN/A ) 12672064SN/A ) && !inSecureState(tc); 126810931Sbrandon.potter@amd.com return toHyp; 12692064SN/A} 12701999SN/A 12711999SN/Auint32_t 12722218SN/ADataAbort::iss() const 12731999SN/A{ 127410931Sbrandon.potter@amd.com uint32_t val; 12751999SN/A 12761999SN/A // Add on the data abort specific fields to the generic abort ISS value 12771999SN/A val = AbortFault<DataAbort>::iss(); 12781999SN/A // ISS is valid if not caused by a stage 1 page table walk, and when taken 12791999SN/A // to AArch64 only when directed to EL2 1280378SN/A if (!s1ptw && (!to64 || toEL == EL2)) { 1281360SN/A val |= isv << 24; 12821450SN/A if (isv) { 128311851Sbrandon.potter@amd.com val |= sas << 22; 12842680Sktlim@umich.edu val |= sse << 21; 1285360SN/A val |= srt << 16; 1286360SN/A // AArch64 only. These assignments are safe on AArch32 as well 1287360SN/A // because these vars are initialized to false 12886701Sgblack@eecs.umich.edu val |= sf << 15; 12898852Sandreas.hansson@arm.com val |= ar << 14; 12906701Sgblack@eecs.umich.edu } 12916701Sgblack@eecs.umich.edu } 12926701Sgblack@eecs.umich.edu return (val); 12936701Sgblack@eecs.umich.edu} 1294360SN/A 12953669Sbinkertn@umich.eduvoid 12963669Sbinkertn@umich.eduDataAbort::annotate(AnnotationIDs id, uint64_t val) 12973669Sbinkertn@umich.edu{ 1298360SN/A AbortFault<DataAbort>::annotate(id, val); 1299360SN/A switch (id) 1300360SN/A { 1301360SN/A case SAS: 13021458SN/A isv = true; 1303360SN/A sas = val; 13048706Sandreas.hansson@arm.com break; 1305360SN/A case SSE: 13061458SN/A isv = true; 1307360SN/A sse = val; 1308360SN/A break; 13091999SN/A case SRT: 13101999SN/A isv = true; 13111999SN/A srt = val; 131211851Sbrandon.potter@amd.com break; 13132680Sktlim@umich.edu case SF: 13141999SN/A isv = true; 13151999SN/A sf = val; 13161999SN/A break; 13176701Sgblack@eecs.umich.edu case AR: 13188852Sandreas.hansson@arm.com isv = true; 13196701Sgblack@eecs.umich.edu ar = val; 13206701Sgblack@eecs.umich.edu break; 13216701Sgblack@eecs.umich.edu // Just ignore unknown ID's 13226701Sgblack@eecs.umich.edu default: 13231999SN/A break; 13243669Sbinkertn@umich.edu } 13253669Sbinkertn@umich.edu} 13263669Sbinkertn@umich.edu 13272764Sstever@eecs.umich.eduvoid 13282064SN/AVirtualDataAbort::invoke(ThreadContext *tc, const StaticInstPtr &inst) 13292064SN/A{ 13302064SN/A AbortFault<VirtualDataAbort>::invoke(tc, inst); 13311999SN/A HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 13321999SN/A hcr.va = 0; 13332064SN/A tc->setMiscRegNoEffect(MISCREG_HCR, hcr); 13341999SN/A} 13351999SN/A 13361999SN/Abool 13371999SN/AInterrupt::routeToMonitor(ThreadContext *tc) const 13388706Sandreas.hansson@arm.com{ 13391999SN/A assert(ArmSystem::haveSecurity(tc)); 13401999SN/A SCR scr = 0; 13411999SN/A if (from64) 13421999SN/A scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 1343378SN/A else 1344360SN/A scr = tc->readMiscRegNoEffect(MISCREG_SCR); 13451450SN/A return scr.irq; 134611856Sbrandon.potter@amd.com} 1347360SN/A 13486701Sgblack@eecs.umich.edubool 134911856Sbrandon.potter@amd.comInterrupt::routeToHyp(ThreadContext *tc) const 135011856Sbrandon.potter@amd.com{ 1351360SN/A bool toHyp; 135211380Salexandru.dutu@amd.com 1353360SN/A SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 135411856Sbrandon.potter@amd.com HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 135511856Sbrandon.potter@amd.com CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 13561458SN/A // Determine whether IRQs are routed to Hyp mode. 135711856Sbrandon.potter@amd.com toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) || 1358360SN/A (cpsr.mode == MODE_HYP); 1359360SN/A return toHyp; 136010931Sbrandon.potter@amd.com} 1361360SN/A 1362360SN/Abool 13631458SN/AInterrupt::abortDisable(ThreadContext *tc) 1364360SN/A{ 136510931Sbrandon.potter@amd.com if (ArmSystem::haveSecurity(tc)) { 13662021SN/A SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 13671458SN/A return (!scr.ns || scr.aw); 1368360SN/A } 1369360SN/A return true; 13701706SN/A} 13711706SN/A 13721706SN/AVirtualInterrupt::VirtualInterrupt() 137311851Sbrandon.potter@amd.com{} 13742680Sktlim@umich.edu 13751706SN/Abool 137611799Sbrandon.potter@amd.comFastInterrupt::routeToMonitor(ThreadContext *tc) const 137711799Sbrandon.potter@amd.com{ 137811799Sbrandon.potter@amd.com assert(ArmSystem::haveSecurity(tc)); 13791706SN/A SCR scr = 0; 13801706SN/A if (from64) 13816701Sgblack@eecs.umich.edu scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 13828852Sandreas.hansson@arm.com else 13836701Sgblack@eecs.umich.edu scr = tc->readMiscRegNoEffect(MISCREG_SCR); 13846701Sgblack@eecs.umich.edu return scr.fiq; 13856701Sgblack@eecs.umich.edu} 13866701Sgblack@eecs.umich.edu 13871706SN/Abool 13883669Sbinkertn@umich.eduFastInterrupt::routeToHyp(ThreadContext *tc) const 13893669Sbinkertn@umich.edu{ 13903669Sbinkertn@umich.edu bool toHyp; 13911706SN/A 13921706SN/A SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 13931706SN/A HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 13941706SN/A CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 13952218SN/A // Determine whether IRQs are routed to Hyp mode. 13961706SN/A toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) || 139711759Sbrandon.potter@amd.com (cpsr.mode == MODE_HYP); 139811799Sbrandon.potter@amd.com return toHyp; 13991706SN/A} 14001706SN/A 14011706SN/Abool 140211886Sbrandon.potter@amd.comFastInterrupt::abortDisable(ThreadContext *tc) 140311886Sbrandon.potter@amd.com{ 140411886Sbrandon.potter@amd.com if (ArmSystem::haveSecurity(tc)) { 140511886Sbrandon.potter@amd.com SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 140611886Sbrandon.potter@amd.com return (!scr.ns || scr.aw); 140712426Sqtt2@cornell.edu } 140813557Sgabeblack@google.com return true; 140913557Sgabeblack@google.com} 141011886Sbrandon.potter@amd.com 141112426Sqtt2@cornell.edubool 141213534Sandreas.sandberg@arm.comFastInterrupt::fiqDisable(ThreadContext *tc) 141312426Sqtt2@cornell.edu{ 141413534Sandreas.sandberg@arm.com if (ArmSystem::haveVirtualization(tc)) { 141512426Sqtt2@cornell.edu return true; 141612426Sqtt2@cornell.edu } else if (ArmSystem::haveSecurity(tc)) { 141712426Sqtt2@cornell.edu SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR); 141813536Sandreas.sandberg@arm.com return (!scr.ns || scr.fw); 141912426Sqtt2@cornell.edu } 142012426Sqtt2@cornell.edu return true; 142111886Sbrandon.potter@amd.com} 142213536Sandreas.sandberg@arm.com 142312426Sqtt2@cornell.eduVirtualFastInterrupt::VirtualFastInterrupt() 142411886Sbrandon.potter@amd.com{} 142511886Sbrandon.potter@amd.com 142611886Sbrandon.potter@amd.comvoid 142711886Sbrandon.potter@amd.comPCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst) 142811886Sbrandon.potter@amd.com{ 142911886Sbrandon.potter@amd.com ArmFaultVals<PCAlignmentFault>::invoke(tc, inst); 143011886Sbrandon.potter@amd.com assert(from64); 143111886Sbrandon.potter@amd.com // Set the FAR 143211886Sbrandon.potter@amd.com tc->setMiscReg(getFaultAddrReg64(), faultPC); 143311886Sbrandon.potter@amd.com} 143411886Sbrandon.potter@amd.com 143511886Sbrandon.potter@amd.combool 143611886Sbrandon.potter@amd.comPCAlignmentFault::routeToHyp(ThreadContext *tc) const 143711886Sbrandon.potter@amd.com{ 143811886Sbrandon.potter@amd.com bool toHyp = false; 143911886Sbrandon.potter@amd.com 144011886Sbrandon.potter@amd.com SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 144111886Sbrandon.potter@amd.com HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2); 144211886Sbrandon.potter@amd.com CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR); 144311886Sbrandon.potter@amd.com 144411886Sbrandon.potter@amd.com // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector 144511886Sbrandon.potter@amd.com toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (cpsr.el == EL0); 144611886Sbrandon.potter@amd.com return toHyp; 144711886Sbrandon.potter@amd.com} 144811886Sbrandon.potter@amd.com 144911886Sbrandon.potter@amd.comSPAlignmentFault::SPAlignmentFault() 145011886Sbrandon.potter@amd.com{} 145111886Sbrandon.potter@amd.com 145211886Sbrandon.potter@amd.comSystemError::SystemError() 145311886Sbrandon.potter@amd.com{} 145411886Sbrandon.potter@amd.com 145511886Sbrandon.potter@amd.comvoid 145611886Sbrandon.potter@amd.comSystemError::invoke(ThreadContext *tc, const StaticInstPtr &inst) 145711886Sbrandon.potter@amd.com{ 145811886Sbrandon.potter@amd.com tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0); 145911886Sbrandon.potter@amd.com ArmFault::invoke(tc, inst); 146011886Sbrandon.potter@amd.com} 146111886Sbrandon.potter@amd.com 146211886Sbrandon.potter@amd.combool 146311886Sbrandon.potter@amd.comSystemError::routeToMonitor(ThreadContext *tc) const 146411886Sbrandon.potter@amd.com{ 146511886Sbrandon.potter@amd.com assert(ArmSystem::haveSecurity(tc)); 146611886Sbrandon.potter@amd.com assert(from64); 146711886Sbrandon.potter@amd.com SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 146811886Sbrandon.potter@amd.com return scr.ea; 146911886Sbrandon.potter@amd.com} 147011886Sbrandon.potter@amd.com 147111886Sbrandon.potter@amd.combool 147211886Sbrandon.potter@amd.comSystemError::routeToHyp(ThreadContext *tc) const 147311886Sbrandon.potter@amd.com{ 147411886Sbrandon.potter@amd.com bool toHyp; 147511886Sbrandon.potter@amd.com assert(from64); 147611886Sbrandon.potter@amd.com 147711886Sbrandon.potter@amd.com SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3); 147811886Sbrandon.potter@amd.com HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR); 147911886Sbrandon.potter@amd.com 148011886Sbrandon.potter@amd.com toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) || 148111886Sbrandon.potter@amd.com (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc)); 148211886Sbrandon.potter@amd.com return toHyp; 148311886Sbrandon.potter@amd.com} 148411886Sbrandon.potter@amd.com 148511911SBrandon.Potter@amd.com 148611911SBrandon.Potter@amd.comSoftwareBreakpoint::SoftwareBreakpoint(ExtMachInst _mach_inst, uint32_t _iss) 148711911SBrandon.Potter@amd.com : ArmFaultVals<SoftwareBreakpoint>(_mach_inst, _iss) 148811911SBrandon.Potter@amd.com{} 148911911SBrandon.Potter@amd.com 149011911SBrandon.Potter@amd.combool 149111911SBrandon.Potter@amd.comSoftwareBreakpoint::routeToHyp(ThreadContext *tc) const 149211886Sbrandon.potter@amd.com{ 149311886Sbrandon.potter@amd.com assert(from64); 149411886Sbrandon.potter@amd.com 149511886Sbrandon.potter@amd.com const bool have_el2 = ArmSystem::haveVirtualization(tc); 149611886Sbrandon.potter@amd.com 149711886Sbrandon.potter@amd.com const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2); 149811886Sbrandon.potter@amd.com const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2); 149911886Sbrandon.potter@amd.com 150011886Sbrandon.potter@amd.com return have_el2 && !inSecureState(tc) && fromEL <= EL1 && 150111886Sbrandon.potter@amd.com (hcr.tge || mdcr.tde); 150211886Sbrandon.potter@amd.com} 150311886Sbrandon.potter@amd.com 150413536Sandreas.sandberg@arm.comvoid 150511886Sbrandon.potter@amd.comArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) { 150611886Sbrandon.potter@amd.com DPRINTF(Faults, "Invoking ArmSev Fault\n"); 150711886Sbrandon.potter@amd.com if (!FullSystem) 150811886Sbrandon.potter@amd.com return; 150911886Sbrandon.potter@amd.com 151011886Sbrandon.potter@amd.com // Set sev_mailbox to 1, clear the pending interrupt from remote 151111886Sbrandon.potter@amd.com // SEV execution and let pipeline continue as pcState is still 151211886Sbrandon.potter@amd.com // valid. 151311886Sbrandon.potter@amd.com tc->setMiscReg(MISCREG_SEV_MAILBOX, 1); 151411886Sbrandon.potter@amd.com tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0); 151513535Sandreas.sandberg@arm.com} 151613535Sandreas.sandberg@arm.com 151713535Sandreas.sandberg@arm.com// Instantiate all the templates to make the linker happy 151811886Sbrandon.potter@amd.comtemplate class ArmFaultVals<Reset>; 151911886Sbrandon.potter@amd.comtemplate class ArmFaultVals<UndefinedInstruction>; 152011886Sbrandon.potter@amd.comtemplate class ArmFaultVals<SupervisorCall>; 152111886Sbrandon.potter@amd.comtemplate class ArmFaultVals<SecureMonitorCall>; 15221706SN/Atemplate class ArmFaultVals<HypervisorCall>; 15231706SN/Atemplate class ArmFaultVals<PrefetchAbort>; 15241706SN/Atemplate class ArmFaultVals<DataAbort>; 15251706SN/Atemplate class ArmFaultVals<VirtualDataAbort>; 152611856Sbrandon.potter@amd.comtemplate class ArmFaultVals<HypervisorTrap>; 15271706SN/Atemplate class ArmFaultVals<Interrupt>; 15286701Sgblack@eecs.umich.edutemplate class ArmFaultVals<VirtualInterrupt>; 152911856Sbrandon.potter@amd.comtemplate class ArmFaultVals<FastInterrupt>; 153011856Sbrandon.potter@amd.comtemplate class ArmFaultVals<VirtualFastInterrupt>; 15311706SN/Atemplate class ArmFaultVals<SupervisorTrap>; 153211856Sbrandon.potter@amd.comtemplate class ArmFaultVals<SecureMonitorTrap>; 153311856Sbrandon.potter@amd.comtemplate class ArmFaultVals<PCAlignmentFault>; 15341706SN/Atemplate class ArmFaultVals<SPAlignmentFault>; 153511856Sbrandon.potter@amd.comtemplate class ArmFaultVals<SystemError>; 15361706SN/Atemplate class ArmFaultVals<SoftwareBreakpoint>; 15371706SN/Atemplate class ArmFaultVals<ArmSev>; 153810931Sbrandon.potter@amd.comtemplate class AbortFault<PrefetchAbort>; 15391706SN/Atemplate class AbortFault<DataAbort>; 15401706SN/Atemplate class AbortFault<VirtualDataAbort>; 15412218SN/A 15421706SN/A 154311759Sbrandon.potter@amd.comIllegalInstSetStateFault::IllegalInstSetStateFault() 15441706SN/A{} 15451706SN/A 15461706SN/A 15471706SN/A} // namespace ArmISA 154813572Sbrandon.potter@amd.com