faults.cc revision 12110
19651SAndreas.Sandberg@ARM.com/* 210858Sandreas.sandberg@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 39651SAndreas.Sandberg@ARM.com * All rights reserved. 49651SAndreas.Sandberg@ARM.com * 59651SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 69651SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 79651SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 89651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 99651SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 109651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 119651SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 129651SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 139651SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 149651SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 159651SAndreas.Sandberg@ARM.com * 169651SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179651SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 189651SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 199651SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 209651SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 219651SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 229651SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239651SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249651SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259651SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 269651SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279651SAndreas.Sandberg@ARM.com * 289651SAndreas.Sandberg@ARM.com * Authors: Gabe Black 299651SAndreas.Sandberg@ARM.com * Kevin Lim 309651SAndreas.Sandberg@ARM.com */ 319651SAndreas.Sandberg@ARM.com 329651SAndreas.Sandberg@ARM.com#include "arch/sparc/faults.hh" 339651SAndreas.Sandberg@ARM.com 349651SAndreas.Sandberg@ARM.com#include <algorithm> 359651SAndreas.Sandberg@ARM.com 369651SAndreas.Sandberg@ARM.com#include "arch/sparc/isa_traits.hh" 379651SAndreas.Sandberg@ARM.com#include "arch/sparc/process.hh" 389651SAndreas.Sandberg@ARM.com#include "arch/sparc/types.hh" 399651SAndreas.Sandberg@ARM.com#include "base/bitfield.hh" 409651SAndreas.Sandberg@ARM.com#include "base/trace.hh" 419651SAndreas.Sandberg@ARM.com#include "cpu/base.hh" 429651SAndreas.Sandberg@ARM.com#include "cpu/thread_context.hh" 439651SAndreas.Sandberg@ARM.com#include "mem/page_table.hh" 449651SAndreas.Sandberg@ARM.com#include "sim/full_system.hh" 459651SAndreas.Sandberg@ARM.com#include "sim/process.hh" 469651SAndreas.Sandberg@ARM.com 479651SAndreas.Sandberg@ARM.comusing namespace std; 489651SAndreas.Sandberg@ARM.com 499760Sandreas@sandberg.pp.senamespace SparcISA 509651SAndreas.Sandberg@ARM.com{ 519651SAndreas.Sandberg@ARM.com 529683Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 539753Sandreas@sandberg.pp.se SparcFault<PowerOnReset>::vals = 549651SAndreas.Sandberg@ARM.com{"power_on_reset", 0x001, 0, {H, H, H}, FaultStat()}; 559651SAndreas.Sandberg@ARM.com 569651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 579651SAndreas.Sandberg@ARM.com SparcFault<WatchDogReset>::vals = 589651SAndreas.Sandberg@ARM.com{"watch_dog_reset", 0x002, 120, {H, H, H}, FaultStat()}; 599651SAndreas.Sandberg@ARM.com 609651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 619753Sandreas@sandberg.pp.se SparcFault<ExternallyInitiatedReset>::vals = 629753Sandreas@sandberg.pp.se{"externally_initiated_reset", 0x003, 110, {H, H, H}, FaultStat()}; 639651SAndreas.Sandberg@ARM.com 649651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 659651SAndreas.Sandberg@ARM.com SparcFault<SoftwareInitiatedReset>::vals = 669651SAndreas.Sandberg@ARM.com{"software_initiated_reset", 0x004, 130, {SH, SH, H}, FaultStat()}; 679651SAndreas.Sandberg@ARM.com 689651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 699651SAndreas.Sandberg@ARM.com SparcFault<REDStateException>::vals = 709651SAndreas.Sandberg@ARM.com{"RED_state_exception", 0x005, 1, {H, H, H}, FaultStat()}; 719651SAndreas.Sandberg@ARM.com 7211399Sandreas.sandberg@arm.comtemplate<> SparcFaultBase::FaultVals 739652SAndreas.Sandberg@ARM.com SparcFault<StoreError>::vals = 749652SAndreas.Sandberg@ARM.com{"store_error", 0x007, 201, {H, H, H}, FaultStat()}; 759651SAndreas.Sandberg@ARM.com 769651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 779651SAndreas.Sandberg@ARM.com SparcFault<InstructionAccessException>::vals = 789651SAndreas.Sandberg@ARM.com{"instruction_access_exception", 0x008, 300, {H, H, H}, FaultStat()}; 799892Sandreas@sandberg.pp.se 809655SAndreas.Sandberg@ARM.com//XXX This trap is apparently dropped from ua2005 819752Sandreas@sandberg.pp.se/*template<> SparcFaultBase::FaultVals 829752Sandreas@sandberg.pp.se SparcFault<InstructionAccessMMUMiss>::vals = 839651SAndreas.Sandberg@ARM.com {"inst_mmu", 0x009, 2, {H, H, H}};*/ 849651SAndreas.Sandberg@ARM.com 859651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 869651SAndreas.Sandberg@ARM.com SparcFault<InstructionAccessError>::vals = 879651SAndreas.Sandberg@ARM.com{"instruction_access_error", 0x00A, 400, {H, H, H}, FaultStat()}; 8810553Salexandru.dutu@amd.com 8910553Salexandru.dutu@amd.comtemplate<> SparcFaultBase::FaultVals 9010553Salexandru.dutu@amd.com SparcFault<IllegalInstruction>::vals = 9110553Salexandru.dutu@amd.com{"illegal_instruction", 0x010, 620, {H, H, H}, FaultStat()}; 9210553Salexandru.dutu@amd.com 9310553Salexandru.dutu@amd.comtemplate<> SparcFaultBase::FaultVals 9410553Salexandru.dutu@amd.com SparcFault<PrivilegedOpcode>::vals = 9510553Salexandru.dutu@amd.com{"privileged_opcode", 0x011, 700, {P, SH, SH}, FaultStat()}; 969651SAndreas.Sandberg@ARM.com 979651SAndreas.Sandberg@ARM.com//XXX This trap is apparently dropped from ua2005 989651SAndreas.Sandberg@ARM.com/*template<> SparcFaultBase::FaultVals 999651SAndreas.Sandberg@ARM.com SparcFault<UnimplementedLDD>::vals = 1009651SAndreas.Sandberg@ARM.com {"unimp_ldd", 0x012, 6, {H, H, H}};*/ 1019651SAndreas.Sandberg@ARM.com 1029651SAndreas.Sandberg@ARM.com//XXX This trap is apparently dropped from ua2005 1039651SAndreas.Sandberg@ARM.com/*template<> SparcFaultBase::FaultVals 1049651SAndreas.Sandberg@ARM.com SparcFault<UnimplementedSTD>::vals = 1059651SAndreas.Sandberg@ARM.com {"unimp_std", 0x013, 6, {H, H, H}};*/ 1069651SAndreas.Sandberg@ARM.com 1079651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 1089651SAndreas.Sandberg@ARM.com SparcFault<FpDisabled>::vals = 1099651SAndreas.Sandberg@ARM.com{"fp_disabled", 0x020, 800, {P, P, H}, FaultStat()}; 1109651SAndreas.Sandberg@ARM.com 1119651SAndreas.Sandberg@ARM.com/* SPARCv8 and SPARCv9 define just fp_disabled trap. SIMD is not contemplated 1129651SAndreas.Sandberg@ARM.com * as a separate part. Therefore, we use the same code and TT */ 1139651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 1149651SAndreas.Sandberg@ARM.com SparcFault<VecDisabled>::vals = 1159651SAndreas.Sandberg@ARM.com{"fp_disabled", 0x020, 800, {P, P, H}, FaultStat()}; 1169651SAndreas.Sandberg@ARM.com 1179651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 1189651SAndreas.Sandberg@ARM.com SparcFault<FpExceptionIEEE754>::vals = 1199651SAndreas.Sandberg@ARM.com{"fp_exception_ieee_754", 0x021, 1110, {P, P, H}, FaultStat()}; 1209651SAndreas.Sandberg@ARM.com 1219651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 1229651SAndreas.Sandberg@ARM.com SparcFault<FpExceptionOther>::vals = 1239651SAndreas.Sandberg@ARM.com{"fp_exception_other", 0x022, 1110, {P, P, H}, FaultStat()}; 1249651SAndreas.Sandberg@ARM.com 1259651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 1269690Sandreas@sandberg.pp.se SparcFault<TagOverflow>::vals = 1279690Sandreas@sandberg.pp.se{"tag_overflow", 0x023, 1400, {P, P, H}, FaultStat()}; 1289690Sandreas@sandberg.pp.se 12911363Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 1309651SAndreas.Sandberg@ARM.com SparcFault<CleanWindow>::vals = 1319651SAndreas.Sandberg@ARM.com{"clean_window", 0x024, 1010, {P, P, H}, FaultStat()}; 1329651SAndreas.Sandberg@ARM.com 1339651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 1349651SAndreas.Sandberg@ARM.com SparcFault<DivisionByZero>::vals = 1359651SAndreas.Sandberg@ARM.com{"division_by_zero", 0x028, 1500, {P, P, H}, FaultStat()}; 1369651SAndreas.Sandberg@ARM.com 1379651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 1389651SAndreas.Sandberg@ARM.com SparcFault<InternalProcessorError>::vals = 1399651SAndreas.Sandberg@ARM.com{"internal_processor_error", 0x029, 4, {H, H, H}, FaultStat()}; 1409651SAndreas.Sandberg@ARM.com 1419651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 1429651SAndreas.Sandberg@ARM.com SparcFault<InstructionInvalidTSBEntry>::vals = 1439651SAndreas.Sandberg@ARM.com{"instruction_invalid_tsb_entry", 0x02A, 210, {H, H, SH}, FaultStat()}; 1449651SAndreas.Sandberg@ARM.com 1459651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 1469651SAndreas.Sandberg@ARM.com SparcFault<DataInvalidTSBEntry>::vals = 1479651SAndreas.Sandberg@ARM.com{"data_invalid_tsb_entry", 0x02B, 1203, {H, H, H}, FaultStat()}; 1489651SAndreas.Sandberg@ARM.com 1499651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 1509651SAndreas.Sandberg@ARM.com SparcFault<DataAccessException>::vals = 1519651SAndreas.Sandberg@ARM.com{"data_access_exception", 0x030, 1201, {H, H, H}, FaultStat()}; 1529651SAndreas.Sandberg@ARM.com 1539651SAndreas.Sandberg@ARM.com//XXX This trap is apparently dropped from ua2005 1549651SAndreas.Sandberg@ARM.com/*template<> SparcFaultBase::FaultVals 1559690Sandreas@sandberg.pp.se SparcFault<DataAccessMMUMiss>::vals = 1569690Sandreas@sandberg.pp.se {"data_mmu", 0x031, 12, {H, H, H}};*/ 1579690Sandreas@sandberg.pp.se 1589651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 1599651SAndreas.Sandberg@ARM.com SparcFault<DataAccessError>::vals = 1609651SAndreas.Sandberg@ARM.com{"data_access_error", 0x032, 1210, {H, H, H}, FaultStat()}; 1619651SAndreas.Sandberg@ARM.com 1629651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 1639651SAndreas.Sandberg@ARM.com SparcFault<DataAccessProtection>::vals = 1649732Sandreas@sandberg.pp.se{"data_access_protection", 0x033, 1207, {H, H, H}, FaultStat()}; 1659732Sandreas@sandberg.pp.se 16610073Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 16710073Sandreas@sandberg.pp.se SparcFault<MemAddressNotAligned>::vals = 16810073Sandreas@sandberg.pp.se{"mem_address_not_aligned", 0x034, 1020, {H, H, H}, FaultStat()}; 16910073Sandreas@sandberg.pp.se 17010073Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 17110073Sandreas@sandberg.pp.se SparcFault<LDDFMemAddressNotAligned>::vals = 17210073Sandreas@sandberg.pp.se{"LDDF_mem_address_not_aligned", 0x035, 1010, {H, H, H}, FaultStat()}; 17310073Sandreas@sandberg.pp.se 17410073Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 17510073Sandreas@sandberg.pp.se SparcFault<STDFMemAddressNotAligned>::vals = 17610073Sandreas@sandberg.pp.se{"STDF_mem_address_not_aligned", 0x036, 1010, {H, H, H}, FaultStat()}; 17710073Sandreas@sandberg.pp.se 17810073Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 17910073Sandreas@sandberg.pp.se SparcFault<PrivilegedAction>::vals = 18010073Sandreas@sandberg.pp.se{"privileged_action", 0x037, 1110, {H, H, SH}, FaultStat()}; 18110073Sandreas@sandberg.pp.se 18210073Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 18310114Sandreas@sandberg.pp.se SparcFault<LDQFMemAddressNotAligned>::vals = 18410114Sandreas@sandberg.pp.se{"LDQF_mem_address_not_aligned", 0x038, 1010, {H, H, H}, FaultStat()}; 18510098Sandreas@sandberg.pp.se 18610098Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 18710098Sandreas@sandberg.pp.se SparcFault<STQFMemAddressNotAligned>::vals = 18810098Sandreas@sandberg.pp.se{"STQF_mem_address_not_aligned", 0x039, 1010, {H, H, H}, FaultStat()}; 18910073Sandreas@sandberg.pp.se 19010073Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 19110073Sandreas@sandberg.pp.se SparcFault<InstructionRealTranslationMiss>::vals = 19210073Sandreas@sandberg.pp.se{"instruction_real_translation_miss", 0x03E, 208, {H, H, SH}, FaultStat()}; 19310114Sandreas@sandberg.pp.se 19410073Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 19510073Sandreas@sandberg.pp.se SparcFault<DataRealTranslationMiss>::vals = 19610073Sandreas@sandberg.pp.se{"data_real_translation_miss", 0x03F, 1203, {H, H, H}, FaultStat()}; 19710114Sandreas@sandberg.pp.se 19810073Sandreas@sandberg.pp.se//XXX This trap is apparently dropped from ua2005 19910073Sandreas@sandberg.pp.se/*template<> SparcFaultBase::FaultVals 20010073Sandreas@sandberg.pp.se SparcFault<AsyncDataError>::vals = 2019651SAndreas.Sandberg@ARM.com {"async_data", 0x040, 2, {H, H, H}};*/ 2029651SAndreas.Sandberg@ARM.com 2039651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2049651SAndreas.Sandberg@ARM.com SparcFault<InterruptLevelN>::vals = 2059651SAndreas.Sandberg@ARM.com{"interrupt_level_n", 0x040, 0, {P, P, SH}, FaultStat()}; 2069651SAndreas.Sandberg@ARM.com 2079651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2089651SAndreas.Sandberg@ARM.com SparcFault<HstickMatch>::vals = 2099651SAndreas.Sandberg@ARM.com{"hstick_match", 0x05E, 1601, {H, H, H}, FaultStat()}; 2109684Sandreas@sandberg.pp.se 2119684Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 2129684Sandreas@sandberg.pp.se SparcFault<TrapLevelZero>::vals = 2139684Sandreas@sandberg.pp.se{"trap_level_zero", 0x05F, 202, {H, H, SH}, FaultStat()}; 2149684Sandreas@sandberg.pp.se 2159651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2169651SAndreas.Sandberg@ARM.com SparcFault<InterruptVector>::vals = 2179651SAndreas.Sandberg@ARM.com{"interrupt_vector", 0x060, 2630, {H, H, H}, FaultStat()}; 2189651SAndreas.Sandberg@ARM.com 2199651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2209755Sandreas@sandberg.pp.se SparcFault<PAWatchpoint>::vals = 2219755Sandreas@sandberg.pp.se{"PA_watchpoint", 0x061, 1209, {H, H, H}, FaultStat()}; 2229755Sandreas@sandberg.pp.se 2239755Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 2249755Sandreas@sandberg.pp.se SparcFault<VAWatchpoint>::vals = 2259755Sandreas@sandberg.pp.se{"VA_watchpoint", 0x062, 1120, {P, P, SH}, FaultStat()}; 2269755Sandreas@sandberg.pp.se 2279755Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 2289755Sandreas@sandberg.pp.se SparcFault<FastInstructionAccessMMUMiss>::vals = 2299755Sandreas@sandberg.pp.se{"fast_instruction_access_MMU_miss", 0x064, 208, {H, H, SH}, FaultStat()}; 2309651SAndreas.Sandberg@ARM.com 2319651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2329651SAndreas.Sandberg@ARM.com SparcFault<FastDataAccessMMUMiss>::vals = 2339651SAndreas.Sandberg@ARM.com{"fast_data_access_MMU_miss", 0x068, 1203, {H, H, H}, FaultStat()}; 2349651SAndreas.Sandberg@ARM.com 2359651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2369651SAndreas.Sandberg@ARM.com SparcFault<FastDataAccessProtection>::vals = 2379651SAndreas.Sandberg@ARM.com{"fast_data_access_protection", 0x06C, 1207, {H, H, H}, FaultStat()}; 2389651SAndreas.Sandberg@ARM.com 2399651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2409651SAndreas.Sandberg@ARM.com SparcFault<InstructionBreakpoint>::vals = 2419651SAndreas.Sandberg@ARM.com{"instruction_break", 0x076, 610, {H, H, H}, FaultStat()}; 2429651SAndreas.Sandberg@ARM.com 2439651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2449651SAndreas.Sandberg@ARM.com SparcFault<CpuMondo>::vals = 2459651SAndreas.Sandberg@ARM.com{"cpu_mondo", 0x07C, 1608, {P, P, SH}, FaultStat()}; 2469651SAndreas.Sandberg@ARM.com 2479651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2489651SAndreas.Sandberg@ARM.com SparcFault<DevMondo>::vals = 2499651SAndreas.Sandberg@ARM.com{"dev_mondo", 0x07D, 1611, {P, P, SH}, FaultStat()}; 2509651SAndreas.Sandberg@ARM.com 2519651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2529651SAndreas.Sandberg@ARM.com SparcFault<ResumableError>::vals = 2539651SAndreas.Sandberg@ARM.com{"resume_error", 0x07E, 3330, {P, P, SH}, FaultStat()}; 2549651SAndreas.Sandberg@ARM.com 2559651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2569651SAndreas.Sandberg@ARM.com SparcFault<SpillNNormal>::vals = 2579651SAndreas.Sandberg@ARM.com{"spill_n_normal", 0x080, 900, {P, P, H}, FaultStat()}; 2589651SAndreas.Sandberg@ARM.com 2599651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2609651SAndreas.Sandberg@ARM.com SparcFault<SpillNOther>::vals = 2619651SAndreas.Sandberg@ARM.com{"spill_n_other", 0x0A0, 900, {P, P, H}, FaultStat()}; 26210905Sandreas.sandberg@arm.com 2639651SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals 2649683Sandreas@sandberg.pp.se SparcFault<FillNNormal>::vals = 2659683Sandreas@sandberg.pp.se{"fill_n_normal", 0x0C0, 900, {P, P, H}, FaultStat()}; 2669683Sandreas@sandberg.pp.se 2679683Sandreas@sandberg.pp.setemplate<> SparcFaultBase::FaultVals 2689683Sandreas@sandberg.pp.se SparcFault<FillNOther>::vals = 2699651SAndreas.Sandberg@ARM.com{"fill_n_other", 0x0E0, 900, {P, P, H}, FaultStat()}; 2709651SAndreas.Sandberg@ARM.com 27110905Sandreas.sandberg@arm.comtemplate<> SparcFaultBase::FaultVals 2729651SAndreas.Sandberg@ARM.com SparcFault<TrapInstruction>::vals = 2739651SAndreas.Sandberg@ARM.com{"trap_instruction", 0x100, 1602, {P, P, H}, FaultStat()}; 2749651SAndreas.Sandberg@ARM.com 27510905Sandreas.sandberg@arm.com/** 2769651SAndreas.Sandberg@ARM.com * This causes the thread context to enter RED state. This causes the side 2779683Sandreas@sandberg.pp.se * effects which go with entering RED state because of a trap. 2789683Sandreas@sandberg.pp.se */ 2799651SAndreas.Sandberg@ARM.com 2809651SAndreas.Sandberg@ARM.comvoid 28110905Sandreas.sandberg@arm.comenterREDState(ThreadContext *tc) 2829652SAndreas.Sandberg@ARM.com{ 2839651SAndreas.Sandberg@ARM.com //@todo Disable the mmu? 2849651SAndreas.Sandberg@ARM.com //@todo Disable watchpoints? 28510913Sandreas.sandberg@arm.com HPSTATE hpstate= tc->readMiscRegNoEffect(MISCREG_HPSTATE); 28610913Sandreas.sandberg@arm.com hpstate.red = 1; 2879651SAndreas.Sandberg@ARM.com hpstate.hpriv = 1; 2889651SAndreas.Sandberg@ARM.com tc->setMiscReg(MISCREG_HPSTATE, hpstate); 28910913Sandreas.sandberg@arm.com // PSTATE.priv is set to 1 here. The manual says it should be 0, but 2909651SAndreas.Sandberg@ARM.com // Legion sets it to 1. 2919753Sandreas@sandberg.pp.se PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); 2929753Sandreas@sandberg.pp.se pstate.priv = 1; 2939753Sandreas@sandberg.pp.se tc->setMiscReg(MISCREG_PSTATE, pstate); 2949753Sandreas@sandberg.pp.se} 2959753Sandreas@sandberg.pp.se 2969753Sandreas@sandberg.pp.se/** 2979753Sandreas@sandberg.pp.se * This sets everything up for a RED state trap except for actually jumping to 2989753Sandreas@sandberg.pp.se * the handler. 29910913Sandreas.sandberg@arm.com */ 30010913Sandreas.sandberg@arm.com 3019651SAndreas.Sandberg@ARM.comvoid 3029753Sandreas@sandberg.pp.sedoREDFault(ThreadContext *tc, TrapType tt) 3039753Sandreas@sandberg.pp.se{ 3049753Sandreas@sandberg.pp.se MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL); 3059753Sandreas@sandberg.pp.se MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE); 3069753Sandreas@sandberg.pp.se PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); 3079753Sandreas@sandberg.pp.se HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); 3089753Sandreas@sandberg.pp.se MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); 3099651SAndreas.Sandberg@ARM.com MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI); 3109753Sandreas@sandberg.pp.se MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP); 3119753Sandreas@sandberg.pp.se MiscReg CANSAVE = tc->readMiscRegNoEffect(NumIntArchRegs + 3); 3129753Sandreas@sandberg.pp.se MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL); 3139753Sandreas@sandberg.pp.se PCState pc = tc->pcState(); 3149753Sandreas@sandberg.pp.se 3159753Sandreas@sandberg.pp.se TL++; 3169753Sandreas@sandberg.pp.se 3179753Sandreas@sandberg.pp.se Addr pcMask = pstate.am ? mask(32) : mask(64); 3189753Sandreas@sandberg.pp.se 31910913Sandreas.sandberg@arm.com // set TSTATE.gl to gl 3209753Sandreas@sandberg.pp.se replaceBits(TSTATE, 42, 40, GL); 3219753Sandreas@sandberg.pp.se // set TSTATE.ccr to ccr 3229753Sandreas@sandberg.pp.se replaceBits(TSTATE, 39, 32, CCR); 3239753Sandreas@sandberg.pp.se // set TSTATE.asi to asi 3249753Sandreas@sandberg.pp.se replaceBits(TSTATE, 31, 24, ASI); 3259753Sandreas@sandberg.pp.se // set TSTATE.pstate to pstate 3269753Sandreas@sandberg.pp.se replaceBits(TSTATE, 20, 8, pstate); 3279753Sandreas@sandberg.pp.se // set TSTATE.cwp to cwp 3289753Sandreas@sandberg.pp.se replaceBits(TSTATE, 4, 0, CWP); 3299753Sandreas@sandberg.pp.se 33010913Sandreas.sandberg@arm.com // Write back TSTATE 3319753Sandreas@sandberg.pp.se tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE); 3329753Sandreas@sandberg.pp.se 3339753Sandreas@sandberg.pp.se // set TPC to PC 3349753Sandreas@sandberg.pp.se tc->setMiscRegNoEffect(MISCREG_TPC, pc.pc() & pcMask); 33510913Sandreas.sandberg@arm.com // set TNPC to NPC 3369753Sandreas@sandberg.pp.se tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask); 3379753Sandreas@sandberg.pp.se 3389753Sandreas@sandberg.pp.se // set HTSTATE.hpstate to hpstate 33910913Sandreas.sandberg@arm.com tc->setMiscRegNoEffect(MISCREG_HTSTATE, hpstate); 3409753Sandreas@sandberg.pp.se 3419651SAndreas.Sandberg@ARM.com // TT = trap type; 3429651SAndreas.Sandberg@ARM.com tc->setMiscRegNoEffect(MISCREG_TT, tt); 3439651SAndreas.Sandberg@ARM.com 3449651SAndreas.Sandberg@ARM.com // Update GL 3459651SAndreas.Sandberg@ARM.com tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL)); 3469651SAndreas.Sandberg@ARM.com 3479651SAndreas.Sandberg@ARM.com bool priv = pstate.priv; // just save the priv bit 3489651SAndreas.Sandberg@ARM.com pstate = 0; 3499651SAndreas.Sandberg@ARM.com pstate.priv = priv; 3509651SAndreas.Sandberg@ARM.com pstate.pef = 1; 3519651SAndreas.Sandberg@ARM.com tc->setMiscRegNoEffect(MISCREG_PSTATE, pstate); 3529651SAndreas.Sandberg@ARM.com 3539651SAndreas.Sandberg@ARM.com hpstate.red = 1; 3549651SAndreas.Sandberg@ARM.com hpstate.hpriv = 1; 3559651SAndreas.Sandberg@ARM.com hpstate.ibe = 0; 3569651SAndreas.Sandberg@ARM.com hpstate.tlz = 0; 3579651SAndreas.Sandberg@ARM.com tc->setMiscRegNoEffect(MISCREG_HPSTATE, hpstate); 3589651SAndreas.Sandberg@ARM.com 3599651SAndreas.Sandberg@ARM.com bool changedCWP = true; 3609651SAndreas.Sandberg@ARM.com if (tt == 0x24) 3619651SAndreas.Sandberg@ARM.com CWP++; 3629651SAndreas.Sandberg@ARM.com else if (0x80 <= tt && tt <= 0xbf) 3639651SAndreas.Sandberg@ARM.com CWP += (CANSAVE + 2); 3649651SAndreas.Sandberg@ARM.com else if (0xc0 <= tt && tt <= 0xff) 3659651SAndreas.Sandberg@ARM.com CWP--; 3669651SAndreas.Sandberg@ARM.com else 36711363Sandreas@sandberg.pp.se changedCWP = false; 36811363Sandreas@sandberg.pp.se 36911363Sandreas@sandberg.pp.se if (changedCWP) { 37011363Sandreas@sandberg.pp.se CWP = (CWP + NWindows) % NWindows; 37111363Sandreas@sandberg.pp.se tc->setMiscReg(MISCREG_CWP, CWP); 37211363Sandreas@sandberg.pp.se } 37311363Sandreas@sandberg.pp.se} 37411363Sandreas@sandberg.pp.se 37511363Sandreas@sandberg.pp.se/** 37611363Sandreas@sandberg.pp.se * This sets everything up for a normal trap except for actually jumping to 37711363Sandreas@sandberg.pp.se * the handler. 37811363Sandreas@sandberg.pp.se */ 37911363Sandreas@sandberg.pp.se 38011363Sandreas@sandberg.pp.sevoid 38111363Sandreas@sandberg.pp.sedoNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) 38211363Sandreas@sandberg.pp.se{ 38311363Sandreas@sandberg.pp.se MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL); 38411363Sandreas@sandberg.pp.se MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE); 38511363Sandreas@sandberg.pp.se PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); 38611363Sandreas@sandberg.pp.se HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); 38711363Sandreas@sandberg.pp.se MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); 38811363Sandreas@sandberg.pp.se MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI); 38911363Sandreas@sandberg.pp.se MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP); 3909651SAndreas.Sandberg@ARM.com MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3); 3919651SAndreas.Sandberg@ARM.com MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL); 3929652SAndreas.Sandberg@ARM.com PCState pc = tc->pcState(); 3939652SAndreas.Sandberg@ARM.com 3949651SAndreas.Sandberg@ARM.com // Increment the trap level 3959651SAndreas.Sandberg@ARM.com TL++; 3969651SAndreas.Sandberg@ARM.com tc->setMiscRegNoEffect(MISCREG_TL, TL); 3979651SAndreas.Sandberg@ARM.com 3989651SAndreas.Sandberg@ARM.com Addr pcMask = pstate.am ? mask(32) : mask(64); 3999651SAndreas.Sandberg@ARM.com 4009651SAndreas.Sandberg@ARM.com // Save off state 4019651SAndreas.Sandberg@ARM.com 4029651SAndreas.Sandberg@ARM.com // set TSTATE.gl to gl 4039651SAndreas.Sandberg@ARM.com replaceBits(TSTATE, 42, 40, GL); 4049651SAndreas.Sandberg@ARM.com // set TSTATE.ccr to ccr 4059651SAndreas.Sandberg@ARM.com replaceBits(TSTATE, 39, 32, CCR); 4069651SAndreas.Sandberg@ARM.com // set TSTATE.asi to asi 4079651SAndreas.Sandberg@ARM.com replaceBits(TSTATE, 31, 24, ASI); 4089651SAndreas.Sandberg@ARM.com // set TSTATE.pstate to pstate 4099651SAndreas.Sandberg@ARM.com replaceBits(TSTATE, 20, 8, pstate); 4109651SAndreas.Sandberg@ARM.com // set TSTATE.cwp to cwp 4119651SAndreas.Sandberg@ARM.com replaceBits(TSTATE, 4, 0, CWP); 4129651SAndreas.Sandberg@ARM.com 4139651SAndreas.Sandberg@ARM.com // Write back TSTATE 4149651SAndreas.Sandberg@ARM.com tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE); 4159651SAndreas.Sandberg@ARM.com 4169651SAndreas.Sandberg@ARM.com // set TPC to PC 4179753Sandreas@sandberg.pp.se tc->setMiscRegNoEffect(MISCREG_TPC, pc.pc() & pcMask); 4189753Sandreas@sandberg.pp.se // set TNPC to NPC 4199753Sandreas@sandberg.pp.se tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask); 4209753Sandreas@sandberg.pp.se 4219753Sandreas@sandberg.pp.se // set HTSTATE.hpstate to hpstate 4229753Sandreas@sandberg.pp.se tc->setMiscRegNoEffect(MISCREG_HTSTATE, hpstate); 4239651SAndreas.Sandberg@ARM.com 4249651SAndreas.Sandberg@ARM.com // TT = trap type; 4259651SAndreas.Sandberg@ARM.com tc->setMiscRegNoEffect(MISCREG_TT, tt); 4269651SAndreas.Sandberg@ARM.com 4279651SAndreas.Sandberg@ARM.com // Update the global register level 4289651SAndreas.Sandberg@ARM.com if (!gotoHpriv) 4299651SAndreas.Sandberg@ARM.com tc->setMiscReg(MISCREG_GL, min<int>(GL + 1, MaxPGL)); 4309651SAndreas.Sandberg@ARM.com else 4319651SAndreas.Sandberg@ARM.com tc->setMiscReg(MISCREG_GL, min<int>(GL + 1, MaxGL)); 4329651SAndreas.Sandberg@ARM.com 4339651SAndreas.Sandberg@ARM.com // pstate.mm is unchanged 4349651SAndreas.Sandberg@ARM.com pstate.pef = 1; // PSTATE.pef = whether or not an fpu is present 43511151Smitch.hayenga@arm.com pstate.am = 0; 4369651SAndreas.Sandberg@ARM.com pstate.ie = 0; 4379651SAndreas.Sandberg@ARM.com // pstate.tle is unchanged 43810157Sandreas@sandberg.pp.se // pstate.tct = 0 43910157Sandreas@sandberg.pp.se 44010157Sandreas@sandberg.pp.se if (gotoHpriv) { 44110157Sandreas@sandberg.pp.se pstate.cle = 0; 44210157Sandreas@sandberg.pp.se // The manual says PSTATE.priv should be 0, but Legion leaves it alone 44310157Sandreas@sandberg.pp.se hpstate.red = 0; 44410157Sandreas@sandberg.pp.se hpstate.hpriv = 1; 4459651SAndreas.Sandberg@ARM.com hpstate.ibe = 0; 4469651SAndreas.Sandberg@ARM.com // hpstate.tlz is unchanged 4479651SAndreas.Sandberg@ARM.com tc->setMiscRegNoEffect(MISCREG_HPSTATE, hpstate); 4489651SAndreas.Sandberg@ARM.com } else { // we are going to priv 4499651SAndreas.Sandberg@ARM.com pstate.priv = 1; 4509651SAndreas.Sandberg@ARM.com pstate.cle = pstate.tle; 4519651SAndreas.Sandberg@ARM.com } 4529651SAndreas.Sandberg@ARM.com tc->setMiscRegNoEffect(MISCREG_PSTATE, pstate); 45310407Smitch.hayenga@arm.com 4549651SAndreas.Sandberg@ARM.com 45510407Smitch.hayenga@arm.com bool changedCWP = true; 4569651SAndreas.Sandberg@ARM.com if (tt == 0x24) 4579651SAndreas.Sandberg@ARM.com CWP++; 4589651SAndreas.Sandberg@ARM.com else if (0x80 <= tt && tt <= 0xbf) 4599651SAndreas.Sandberg@ARM.com CWP += (CANSAVE + 2); 4609651SAndreas.Sandberg@ARM.com else if (0xc0 <= tt && tt <= 0xff) 4619651SAndreas.Sandberg@ARM.com CWP--; 4629651SAndreas.Sandberg@ARM.com else 4639754Sandreas@sandberg.pp.se changedCWP = false; 4649651SAndreas.Sandberg@ARM.com 46510407Smitch.hayenga@arm.com if (changedCWP) { 4669651SAndreas.Sandberg@ARM.com CWP = (CWP + NWindows) % NWindows; 4679651SAndreas.Sandberg@ARM.com tc->setMiscReg(MISCREG_CWP, CWP); 4689651SAndreas.Sandberg@ARM.com } 4699651SAndreas.Sandberg@ARM.com} 4709651SAndreas.Sandberg@ARM.com 4719651SAndreas.Sandberg@ARM.comvoid 4729651SAndreas.Sandberg@ARM.comgetREDVector(MiscReg TT, Addr &PC, Addr &NPC) 4739651SAndreas.Sandberg@ARM.com{ 4749651SAndreas.Sandberg@ARM.com //XXX The following constant might belong in a header file. 4759651SAndreas.Sandberg@ARM.com const Addr RSTVAddr = 0xFFF0000000ULL; 4769651SAndreas.Sandberg@ARM.com PC = RSTVAddr | ((TT << 5) & 0xFF); 4779651SAndreas.Sandberg@ARM.com NPC = PC + sizeof(MachInst); 4789651SAndreas.Sandberg@ARM.com} 4799651SAndreas.Sandberg@ARM.com 4809651SAndreas.Sandberg@ARM.comvoid 48110553Salexandru.dutu@amd.comgetHyperVector(ThreadContext * tc, Addr &PC, Addr &NPC, MiscReg TT) 4829651SAndreas.Sandberg@ARM.com{ 4839651SAndreas.Sandberg@ARM.com Addr HTBA = tc->readMiscRegNoEffect(MISCREG_HTBA); 4849651SAndreas.Sandberg@ARM.com PC = (HTBA & ~mask(14)) | ((TT << 5) & mask(14)); 4859651SAndreas.Sandberg@ARM.com NPC = PC + sizeof(MachInst); 4869651SAndreas.Sandberg@ARM.com} 4879651SAndreas.Sandberg@ARM.com 4889651SAndreas.Sandberg@ARM.comvoid 4899651SAndreas.Sandberg@ARM.comgetPrivVector(ThreadContext *tc, Addr &PC, Addr &NPC, MiscReg TT, MiscReg TL) 4909651SAndreas.Sandberg@ARM.com{ 4919651SAndreas.Sandberg@ARM.com Addr TBA = tc->readMiscRegNoEffect(MISCREG_TBA); 4929651SAndreas.Sandberg@ARM.com PC = (TBA & ~mask(15)) | 4939651SAndreas.Sandberg@ARM.com (TL > 1 ? (1 << 14) : 0) | 4949651SAndreas.Sandberg@ARM.com ((TT << 5) & mask(14)); 4959651SAndreas.Sandberg@ARM.com NPC = PC + sizeof(MachInst); 4969651SAndreas.Sandberg@ARM.com} 4979651SAndreas.Sandberg@ARM.com 4989651SAndreas.Sandberg@ARM.comvoid 4999651SAndreas.Sandberg@ARM.comSparcFaultBase::invoke(ThreadContext * tc, const StaticInstPtr &inst) 5009651SAndreas.Sandberg@ARM.com{ 5019651SAndreas.Sandberg@ARM.com FaultBase::invoke(tc); 5029651SAndreas.Sandberg@ARM.com if (!FullSystem) 5039651SAndreas.Sandberg@ARM.com return; 5049651SAndreas.Sandberg@ARM.com 5059651SAndreas.Sandberg@ARM.com countStat()++; 5069651SAndreas.Sandberg@ARM.com 5079652SAndreas.Sandberg@ARM.com // We can refer to this to see what the trap level -was-, but something 5089652SAndreas.Sandberg@ARM.com // in the middle could change it in the regfile out from under us. 5099652SAndreas.Sandberg@ARM.com MiscReg tl = tc->readMiscRegNoEffect(MISCREG_TL); 5109652SAndreas.Sandberg@ARM.com MiscReg tt = tc->readMiscRegNoEffect(MISCREG_TT); 5119652SAndreas.Sandberg@ARM.com PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); 5129652SAndreas.Sandberg@ARM.com HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); 5139652SAndreas.Sandberg@ARM.com 5149652SAndreas.Sandberg@ARM.com Addr PC, NPC; 5159652SAndreas.Sandberg@ARM.com 5169651SAndreas.Sandberg@ARM.com PrivilegeLevel current; 5179651SAndreas.Sandberg@ARM.com if (hpstate.hpriv) 5189651SAndreas.Sandberg@ARM.com current = Hyperprivileged; 5199752Sandreas@sandberg.pp.se else if (pstate.priv) 5209651SAndreas.Sandberg@ARM.com current = Privileged; 5219651SAndreas.Sandberg@ARM.com else 5229651SAndreas.Sandberg@ARM.com current = User; 5239651SAndreas.Sandberg@ARM.com 5249651SAndreas.Sandberg@ARM.com PrivilegeLevel level = getNextLevel(current); 5259651SAndreas.Sandberg@ARM.com 5269752Sandreas@sandberg.pp.se if (hpstate.red || (tl == MaxTL - 1)) { 5279651SAndreas.Sandberg@ARM.com getREDVector(5, PC, NPC); 5289651SAndreas.Sandberg@ARM.com doREDFault(tc, tt); 5299651SAndreas.Sandberg@ARM.com // This changes the hpstate and pstate, so we need to make sure we 53010905Sandreas.sandberg@arm.com // save the old version on the trap stack in doREDFault. 5319651SAndreas.Sandberg@ARM.com enterREDState(tc); 5329651SAndreas.Sandberg@ARM.com } else if (tl == MaxTL) { 5339651SAndreas.Sandberg@ARM.com panic("Should go to error state here.. crap\n"); 5349651SAndreas.Sandberg@ARM.com // Do error_state somehow? 5359651SAndreas.Sandberg@ARM.com // Probably inject a WDR fault using the interrupt mechanism. 5369651SAndreas.Sandberg@ARM.com // What should the PC and NPC be set to? 5379651SAndreas.Sandberg@ARM.com } else if (tl > MaxPTL && level == Privileged) { 5389753Sandreas@sandberg.pp.se // guest_watchdog fault 5399753Sandreas@sandberg.pp.se doNormalFault(tc, trapType(), true); 5409651SAndreas.Sandberg@ARM.com getHyperVector(tc, PC, NPC, 2); 5419651SAndreas.Sandberg@ARM.com } else if (level == Hyperprivileged || 5429753Sandreas@sandberg.pp.se (level == Privileged && trapType() >= 384)) { 5439753Sandreas@sandberg.pp.se doNormalFault(tc, trapType(), true); 5449753Sandreas@sandberg.pp.se getHyperVector(tc, PC, NPC, trapType()); 5459753Sandreas@sandberg.pp.se } else { 5469753Sandreas@sandberg.pp.se doNormalFault(tc, trapType(), false); 5479753Sandreas@sandberg.pp.se getPrivVector(tc, PC, NPC, trapType(), tl + 1); 5489651SAndreas.Sandberg@ARM.com } 5499651SAndreas.Sandberg@ARM.com 5509753Sandreas@sandberg.pp.se PCState pc; 5519753Sandreas@sandberg.pp.se pc.pc(PC); 55210858Sandreas.sandberg@arm.com pc.npc(NPC); 55310858Sandreas.sandberg@arm.com pc.nnpc(NPC + sizeof(MachInst)); 55410858Sandreas.sandberg@arm.com pc.upc(0); 55510858Sandreas.sandberg@arm.com pc.nupc(1); 55610858Sandreas.sandberg@arm.com tc->pcState(pc); 55710858Sandreas.sandberg@arm.com} 55810858Sandreas.sandberg@arm.com 55910858Sandreas.sandberg@arm.comvoid 5609753Sandreas@sandberg.pp.sePowerOnReset::invoke(ThreadContext *tc, const StaticInstPtr &inst) 56111399Sandreas.sandberg@arm.com{ 56211399Sandreas.sandberg@arm.com // For SPARC, when a system is first started, there is a power 56311399Sandreas.sandberg@arm.com // on reset Trap which sets the processor into the following state. 5649753Sandreas@sandberg.pp.se // Bits that aren't set aren't defined on startup. 5659753Sandreas@sandberg.pp.se 5669753Sandreas@sandberg.pp.se tc->setMiscRegNoEffect(MISCREG_TL, MaxTL); 5679892Sandreas@sandberg.pp.se tc->setMiscRegNoEffect(MISCREG_TT, trapType()); 56810858Sandreas.sandberg@arm.com tc->setMiscReg(MISCREG_GL, MaxGL); 56910858Sandreas.sandberg@arm.com 57010858Sandreas.sandberg@arm.com PSTATE pstate = 0; 57110858Sandreas.sandberg@arm.com pstate.pef = 1; 5729892Sandreas@sandberg.pp.se pstate.priv = 1; 5739753Sandreas@sandberg.pp.se tc->setMiscRegNoEffect(MISCREG_PSTATE, pstate); 57410913Sandreas.sandberg@arm.com 5759753Sandreas@sandberg.pp.se // Turn on red and hpriv, set everything else to 0 5769753Sandreas@sandberg.pp.se HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); 5779753Sandreas@sandberg.pp.se hpstate.red = 1; 5789753Sandreas@sandberg.pp.se hpstate.hpriv = 1; 5799753Sandreas@sandberg.pp.se hpstate.ibe = 0; 5809753Sandreas@sandberg.pp.se hpstate.tlz = 0; 5819753Sandreas@sandberg.pp.se tc->setMiscRegNoEffect(MISCREG_HPSTATE, hpstate); 5829753Sandreas@sandberg.pp.se 5839753Sandreas@sandberg.pp.se // The tick register is unreadable by nonprivileged software 58410112Sandreas@sandberg.pp.se tc->setMiscRegNoEffect(MISCREG_TICK, 1ULL << 63); 58510112Sandreas@sandberg.pp.se 58610112Sandreas@sandberg.pp.se // Enter RED state. We do this last so that the actual state preserved in 58710112Sandreas@sandberg.pp.se // the trap stack is the state from before this fault. 58810112Sandreas@sandberg.pp.se enterREDState(tc); 58910112Sandreas@sandberg.pp.se 5909753Sandreas@sandberg.pp.se Addr PC, NPC; 5919753Sandreas@sandberg.pp.se getREDVector(trapType(), PC, NPC); 5929753Sandreas@sandberg.pp.se 5939753Sandreas@sandberg.pp.se PCState pc; 5949753Sandreas@sandberg.pp.se pc.pc(PC); 59511399Sandreas.sandberg@arm.com pc.npc(NPC); 59611399Sandreas.sandberg@arm.com pc.nnpc(NPC + sizeof(MachInst)); 59711399Sandreas.sandberg@arm.com pc.upc(0); 5989753Sandreas@sandberg.pp.se pc.nupc(1); 5999753Sandreas@sandberg.pp.se tc->pcState(pc); 6009755Sandreas@sandberg.pp.se 6019753Sandreas@sandberg.pp.se // These registers are specified as "undefined" after a POR, and they 6029755Sandreas@sandberg.pp.se // should have reasonable values after the miscregfile is reset 6039755Sandreas@sandberg.pp.se /* 6049753Sandreas@sandberg.pp.se // Clear all the soft interrupt bits 6059755Sandreas@sandberg.pp.se softint = 0; 6069753Sandreas@sandberg.pp.se // disable timer compare interrupts, reset tick_cmpr 6079904Sandreas@sandberg.pp.se tc->setMiscRegNoEffect(MISCREG_ 6089904Sandreas@sandberg.pp.se tick_cmprFields.int_dis = 1; 6099904Sandreas@sandberg.pp.se tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing 6109904Sandreas@sandberg.pp.se stickFields.npt = 1; // The TICK register is unreadable by by !priv 6119904Sandreas@sandberg.pp.se stick_cmprFields.int_dis = 1; // disable timer compare interrupts 6129904Sandreas@sandberg.pp.se stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing 6139753Sandreas@sandberg.pp.se 6149753Sandreas@sandberg.pp.se tt[tl] = _trapType; 6159753Sandreas@sandberg.pp.se 6169753Sandreas@sandberg.pp.se hintp = 0; // no interrupts pending 6179651SAndreas.Sandberg@ARM.com hstick_cmprFields.int_dis = 1; // disable timer compare interrupts 6189753Sandreas@sandberg.pp.se hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing 6199753Sandreas@sandberg.pp.se */ 6209651SAndreas.Sandberg@ARM.com} 6219753Sandreas@sandberg.pp.se 6229753Sandreas@sandberg.pp.sevoid 6239753Sandreas@sandberg.pp.seFastInstructionAccessMMUMiss::invoke(ThreadContext *tc, 6249753Sandreas@sandberg.pp.se const StaticInstPtr &inst) 6259753Sandreas@sandberg.pp.se{ 6269753Sandreas@sandberg.pp.se if (FullSystem) { 6279753Sandreas@sandberg.pp.se SparcFaultBase::invoke(tc, inst); 6289753Sandreas@sandberg.pp.se return; 6299753Sandreas@sandberg.pp.se } 6309753Sandreas@sandberg.pp.se 6319753Sandreas@sandberg.pp.se Process *p = tc->getProcessPtr(); 6329753Sandreas@sandberg.pp.se TlbEntry entry; 6339753Sandreas@sandberg.pp.se bool success = p->pTable->lookup(vaddr, entry); 6349753Sandreas@sandberg.pp.se if (!success) { 6359753Sandreas@sandberg.pp.se panic("Tried to execute unmapped address %#x.\n", vaddr); 6369753Sandreas@sandberg.pp.se } else { 6379753Sandreas@sandberg.pp.se Addr alignedvaddr = p->pTable->pageAlign(vaddr); 6389651SAndreas.Sandberg@ARM.com 6399651SAndreas.Sandberg@ARM.com // Grab fields used during instruction translation to figure out 6409735Sandreas@sandberg.pp.se // which context to use. 6419735Sandreas@sandberg.pp.se uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); 6429735Sandreas@sandberg.pp.se 6439735Sandreas@sandberg.pp.se // Inside a VM, a real address is the address that guest OS would 6449735Sandreas@sandberg.pp.se // interpret to be a physical address. To map to the physical address, 6459735Sandreas@sandberg.pp.se // it still needs to undergo a translation. The instruction 6469651SAndreas.Sandberg@ARM.com // translation code in the SPARC ITLB code assumes that the context is 6479651SAndreas.Sandberg@ARM.com // zero (kernel-level) if real addressing is being used. 6489651SAndreas.Sandberg@ARM.com bool is_real_address = !bits(tlbdata, 4); 6499753Sandreas@sandberg.pp.se 65011363Sandreas@sandberg.pp.se // The SPARC ITLB code assumes that traps are executed in context 65111363Sandreas@sandberg.pp.se // zero so we carry that assumption through here. 65211363Sandreas@sandberg.pp.se bool trapped = bits(tlbdata, 18, 16) > 0; 6539651SAndreas.Sandberg@ARM.com 6549655SAndreas.Sandberg@ARM.com // The primary context acts as a PASID. It allows the MMU to 6559753Sandreas@sandberg.pp.se // distinguish between virtual addresses that would alias to the 6569753Sandreas@sandberg.pp.se // same physical address (if two or more processes shared the same 6579753Sandreas@sandberg.pp.se // virtual address mapping). 6589753Sandreas@sandberg.pp.se int primary_context = bits(tlbdata, 47, 32); 6599753Sandreas@sandberg.pp.se 6609735Sandreas@sandberg.pp.se // The partition id distinguishes between virtualized environments. 6619755Sandreas@sandberg.pp.se int const partition_id = 0; 6629755Sandreas@sandberg.pp.se 66310114Sandreas@sandberg.pp.se // Given the assumptions in the translateInst code in the SPARC ITLB, 66410114Sandreas@sandberg.pp.se // the logic works out to the following for the context. 66510114Sandreas@sandberg.pp.se int context_id = (is_real_address || trapped) ? 0 : primary_context; 6669753Sandreas@sandberg.pp.se 66710114Sandreas@sandberg.pp.se // Insert the TLB entry. 6689655SAndreas.Sandberg@ARM.com // The entry specifying whether the address is "real" is set to 66910114Sandreas@sandberg.pp.se // false for syscall emulation mode regardless of whether the 67010114Sandreas@sandberg.pp.se // address is real in preceding code. Not sure sure that this is 67110114Sandreas@sandberg.pp.se // correct, but also not sure if it matters at all. 6729753Sandreas@sandberg.pp.se tc->getITBPtr()->insert(alignedvaddr, partition_id, context_id, 67310114Sandreas@sandberg.pp.se false, entry.pte); 67410114Sandreas@sandberg.pp.se } 6759753Sandreas@sandberg.pp.se} 6769753Sandreas@sandberg.pp.se 6779753Sandreas@sandberg.pp.sevoid 6789753Sandreas@sandberg.pp.seFastDataAccessMMUMiss::invoke(ThreadContext *tc, const StaticInstPtr &inst) 6799753Sandreas@sandberg.pp.se{ 6809753Sandreas@sandberg.pp.se if (FullSystem) { 6819753Sandreas@sandberg.pp.se SparcFaultBase::invoke(tc, inst); 68210157Sandreas@sandberg.pp.se return; 68310157Sandreas@sandberg.pp.se } 68410157Sandreas@sandberg.pp.se 68510157Sandreas@sandberg.pp.se Process *p = tc->getProcessPtr(); 68610157Sandreas@sandberg.pp.se TlbEntry entry; 68710157Sandreas@sandberg.pp.se bool success = p->pTable->lookup(vaddr, entry); 68810157Sandreas@sandberg.pp.se if (!success) { 68910157Sandreas@sandberg.pp.se if (p->fixupStackFault(vaddr)) 6909753Sandreas@sandberg.pp.se success = p->pTable->lookup(vaddr, entry); 6919753Sandreas@sandberg.pp.se } 6929753Sandreas@sandberg.pp.se if (!success) { 6939753Sandreas@sandberg.pp.se panic("Tried to access unmapped address %#x.\n", vaddr); 6949753Sandreas@sandberg.pp.se } else { 6959753Sandreas@sandberg.pp.se Addr alignedvaddr = p->pTable->pageAlign(vaddr); 6969753Sandreas@sandberg.pp.se 6979753Sandreas@sandberg.pp.se // Grab fields used during data translation to figure out 6989753Sandreas@sandberg.pp.se // which context to use. 6999753Sandreas@sandberg.pp.se uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); 7009753Sandreas@sandberg.pp.se 7019753Sandreas@sandberg.pp.se // The primary context acts as a PASID. It allows the MMU to 7029753Sandreas@sandberg.pp.se // distinguish between virtual addresses that would alias to the 7039753Sandreas@sandberg.pp.se // same physical address (if two or more processes shared the same 7049753Sandreas@sandberg.pp.se // virtual address mapping). There's a secondary context used in the 7059753Sandreas@sandberg.pp.se // DTLB translation code, but it should __probably__ be zero for 7069753Sandreas@sandberg.pp.se // syscall emulation code. (The secondary context is used by Solaris 7079753Sandreas@sandberg.pp.se // to allow kernel privilege code to access user space code: 7089753Sandreas@sandberg.pp.se // [ISBN 0-13-022496-0]:PG199.) 7099753Sandreas@sandberg.pp.se int primary_context = bits(tlbdata, 47, 32); 7109753Sandreas@sandberg.pp.se 7119753Sandreas@sandberg.pp.se // "Hyper-Privileged Mode" is in use. There are three main modes of 7129753Sandreas@sandberg.pp.se // operation for Sparc: Hyper-Privileged Mode, Privileged Mode, and 7139753Sandreas@sandberg.pp.se // User Mode. 7149753Sandreas@sandberg.pp.se int hpriv = bits(tlbdata, 0); 71510114Sandreas@sandberg.pp.se 7169753Sandreas@sandberg.pp.se // Reset, Error and Debug state is in use. Something horrible has 7179753Sandreas@sandberg.pp.se // happened or the system is operating in Reset Mode. 7189753Sandreas@sandberg.pp.se int red = bits(tlbdata, 1); 7199753Sandreas@sandberg.pp.se 72010114Sandreas@sandberg.pp.se // Inside a VM, a real address is the address that guest OS would 7219753Sandreas@sandberg.pp.se // interpret to be a physical address. To map to the physical address, 7229753Sandreas@sandberg.pp.se // it still needs to undergo a translation. The instruction 7239753Sandreas@sandberg.pp.se // translation code in the SPARC ITLB code assumes that the context is 7249753Sandreas@sandberg.pp.se // zero (kernel-level) if real addressing is being used. 7259753Sandreas@sandberg.pp.se int is_real_address = !bits(tlbdata, 5); 7269753Sandreas@sandberg.pp.se 7279753Sandreas@sandberg.pp.se // Grab the address space identifier register from the thread context. 7289753Sandreas@sandberg.pp.se // XXX: Inspecting how setMiscReg and setMiscRegNoEffect behave for 7299753Sandreas@sandberg.pp.se // MISCREG_ASI causes me to think that the ASI register implementation 7309753Sandreas@sandberg.pp.se // might be bugged. The NoEffect variant changes the ASI register 7319753Sandreas@sandberg.pp.se // value in the architectural state while the normal variant changes 7329753Sandreas@sandberg.pp.se // the context field in the thread context's currently decoded request 7339753Sandreas@sandberg.pp.se // but does not directly affect the ASI register value in the 7349753Sandreas@sandberg.pp.se // architectural state. The ASI values and the context field in the 7359753Sandreas@sandberg.pp.se // request packet seem to have completely different uses. 7369753Sandreas@sandberg.pp.se MiscReg reg_asi = tc->readMiscRegNoEffect(MISCREG_ASI); 7379651SAndreas.Sandberg@ARM.com ASI asi = static_cast<ASI>(reg_asi); 7389655SAndreas.Sandberg@ARM.com 7399651SAndreas.Sandberg@ARM.com // The SPARC DTLB code assumes that traps are executed in context 7409651SAndreas.Sandberg@ARM.com // zero if the asi value is ASI_IMPLICIT (which is 0x0). There's also 7419651SAndreas.Sandberg@ARM.com // an assumption that the nucleus address space is being used, but 7429651SAndreas.Sandberg@ARM.com // the context is the relevant issue since we need to pass it to TLB. 7439651SAndreas.Sandberg@ARM.com bool trapped = bits(tlbdata, 18, 16) > 0; 7449651SAndreas.Sandberg@ARM.com 7459651SAndreas.Sandberg@ARM.com // Given the assumptions in the translateData code in the SPARC DTLB, 7469651SAndreas.Sandberg@ARM.com // the logic works out to the following for the context. 7479651SAndreas.Sandberg@ARM.com int context_id = ((!hpriv && !red && is_real_address) || 7489651SAndreas.Sandberg@ARM.com asiIsReal(asi) || 7499651SAndreas.Sandberg@ARM.com (trapped && asi == ASI_IMPLICIT)) 7509651SAndreas.Sandberg@ARM.com ? 0 : primary_context; 7519651SAndreas.Sandberg@ARM.com 7529651SAndreas.Sandberg@ARM.com // The partition id distinguishes between virtualized environments. 7539651SAndreas.Sandberg@ARM.com int const partition_id = 0; 7549651SAndreas.Sandberg@ARM.com 7559651SAndreas.Sandberg@ARM.com // Insert the TLB entry. 7569651SAndreas.Sandberg@ARM.com // The entry specifying whether the address is "real" is set to 7579651SAndreas.Sandberg@ARM.com // false for syscall emulation mode regardless of whether the 7589651SAndreas.Sandberg@ARM.com // address is real in preceding code. Not sure sure that this is 7599651SAndreas.Sandberg@ARM.com // correct, but also not sure if it matters at all. 7609651SAndreas.Sandberg@ARM.com tc->getDTBPtr()->insert(alignedvaddr, partition_id, context_id, 7619651SAndreas.Sandberg@ARM.com false, entry.pte); 7629651SAndreas.Sandberg@ARM.com } 7639651SAndreas.Sandberg@ARM.com} 7649651SAndreas.Sandberg@ARM.com 7659651SAndreas.Sandberg@ARM.comvoid 7669651SAndreas.Sandberg@ARM.comSpillNNormal::invoke(ThreadContext *tc, const StaticInstPtr &inst) 7679651SAndreas.Sandberg@ARM.com{ 7689651SAndreas.Sandberg@ARM.com if (FullSystem) { 7699651SAndreas.Sandberg@ARM.com SparcFaultBase::invoke(tc, inst); 7709651SAndreas.Sandberg@ARM.com return; 7719651SAndreas.Sandberg@ARM.com } 7729651SAndreas.Sandberg@ARM.com 7739651SAndreas.Sandberg@ARM.com doNormalFault(tc, trapType(), false); 7749651SAndreas.Sandberg@ARM.com 7759651SAndreas.Sandberg@ARM.com Process *p = tc->getProcessPtr(); 7769651SAndreas.Sandberg@ARM.com 7779651SAndreas.Sandberg@ARM.com SparcProcess *sp = dynamic_cast<SparcProcess *>(p); 7789651SAndreas.Sandberg@ARM.com assert(sp); 7799651SAndreas.Sandberg@ARM.com 7809651SAndreas.Sandberg@ARM.com // Then adjust the PC and NPC 7819651SAndreas.Sandberg@ARM.com tc->pcState(sp->readSpillStart()); 7829651SAndreas.Sandberg@ARM.com} 7839651SAndreas.Sandberg@ARM.com 7849651SAndreas.Sandberg@ARM.comvoid 7859651SAndreas.Sandberg@ARM.comFillNNormal::invoke(ThreadContext *tc, const StaticInstPtr &inst) 7869651SAndreas.Sandberg@ARM.com{ 7879651SAndreas.Sandberg@ARM.com if (FullSystem) { 7889651SAndreas.Sandberg@ARM.com SparcFaultBase::invoke(tc, inst); 7899651SAndreas.Sandberg@ARM.com return; 7909651SAndreas.Sandberg@ARM.com } 7919651SAndreas.Sandberg@ARM.com 7929651SAndreas.Sandberg@ARM.com doNormalFault(tc, trapType(), false); 7939651SAndreas.Sandberg@ARM.com 7949651SAndreas.Sandberg@ARM.com Process *p = tc->getProcessPtr(); 7959651SAndreas.Sandberg@ARM.com 7969651SAndreas.Sandberg@ARM.com SparcProcess *sp = dynamic_cast<SparcProcess *>(p); 7979651SAndreas.Sandberg@ARM.com assert(sp); 7989651SAndreas.Sandberg@ARM.com 7999651SAndreas.Sandberg@ARM.com // Then adjust the PC and NPC 8009651SAndreas.Sandberg@ARM.com tc->pcState(sp->readFillStart()); 8019651SAndreas.Sandberg@ARM.com} 8029651SAndreas.Sandberg@ARM.com 8039651SAndreas.Sandberg@ARM.comvoid 8049651SAndreas.Sandberg@ARM.comTrapInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst) 8059651SAndreas.Sandberg@ARM.com{ 8069651SAndreas.Sandberg@ARM.com if (FullSystem) { 8079651SAndreas.Sandberg@ARM.com SparcFaultBase::invoke(tc, inst); 8089651SAndreas.Sandberg@ARM.com return; 8099651SAndreas.Sandberg@ARM.com } 8109651SAndreas.Sandberg@ARM.com 8119651SAndreas.Sandberg@ARM.com // In SE, this mechanism is how the process requests a service from 8129651SAndreas.Sandberg@ARM.com // the operating system. We'll get the process object from the thread 8139651SAndreas.Sandberg@ARM.com // context and let it service the request. 8149651SAndreas.Sandberg@ARM.com 8159651SAndreas.Sandberg@ARM.com Process *p = tc->getProcessPtr(); 8169651SAndreas.Sandberg@ARM.com 8179651SAndreas.Sandberg@ARM.com SparcProcess *sp = dynamic_cast<SparcProcess *>(p); 8189651SAndreas.Sandberg@ARM.com assert(sp); 8199651SAndreas.Sandberg@ARM.com 8209651SAndreas.Sandberg@ARM.com Fault fault; 8219651SAndreas.Sandberg@ARM.com sp->handleTrap(_n, tc, &fault); 8229651SAndreas.Sandberg@ARM.com 8239651SAndreas.Sandberg@ARM.com // We need to explicitly advance the pc, since that's not done for us 8249651SAndreas.Sandberg@ARM.com // on a faulting instruction 8259651SAndreas.Sandberg@ARM.com PCState pc = tc->pcState(); 8269651SAndreas.Sandberg@ARM.com pc.advance(); 8279651SAndreas.Sandberg@ARM.com tc->pcState(pc); 8289651SAndreas.Sandberg@ARM.com} 8299651SAndreas.Sandberg@ARM.com 8309651SAndreas.Sandberg@ARM.com} // namespace SparcISA 8319651SAndreas.Sandberg@ARM.com 8329651SAndreas.Sandberg@ARM.com