faults.cc revision 11851
17405SAli.Saidi@ARM.com/*
211573SDylan.Johnson@ARM.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
37405SAli.Saidi@ARM.com * All rights reserved.
47405SAli.Saidi@ARM.com *
57405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
67405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
77405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
87405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
97405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
107405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
117405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
127405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
137405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
147405SAli.Saidi@ARM.com * this software without specific prior written permission.
157405SAli.Saidi@ARM.com *
167405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277405SAli.Saidi@ARM.com *
287405SAli.Saidi@ARM.com * Authors: Gabe Black
297405SAli.Saidi@ARM.com *          Kevin Lim
307405SAli.Saidi@ARM.com */
317405SAli.Saidi@ARM.com
327405SAli.Saidi@ARM.com#include "arch/sparc/faults.hh"
337405SAli.Saidi@ARM.com
347405SAli.Saidi@ARM.com#include <algorithm>
357405SAli.Saidi@ARM.com
367405SAli.Saidi@ARM.com#include "arch/sparc/isa_traits.hh"
377405SAli.Saidi@ARM.com#include "arch/sparc/process.hh"
387405SAli.Saidi@ARM.com#include "arch/sparc/types.hh"
397405SAli.Saidi@ARM.com#include "base/bitfield.hh"
407405SAli.Saidi@ARM.com#include "base/trace.hh"
417405SAli.Saidi@ARM.com#include "cpu/base.hh"
4211793Sbrandon.potter@amd.com#include "cpu/thread_context.hh"
4310461SAndreas.Sandberg@ARM.com#include "mem/page_table.hh"
449050Schander.sudanthi@arm.com#include "sim/full_system.hh"
4511793Sbrandon.potter@amd.com#include "sim/process.hh"
468887Sgeoffrey.blake@arm.com
478232Snate@binkert.orgusing namespace std;
488232Snate@binkert.org
4910844Sandreas.sandberg@arm.comnamespace SparcISA
509384SAndreas.Sandberg@arm.com{
517678Sgblack@eecs.umich.edu
528059SAli.Saidi@ARM.comtemplate<> SparcFaultBase::FaultVals
538284SAli.Saidi@ARM.com    SparcFault<PowerOnReset>::vals =
547405SAli.Saidi@ARM.com{"power_on_reset", 0x001, 0, {H, H, H}, FaultStat()};
557405SAli.Saidi@ARM.com
567405SAli.Saidi@ARM.comtemplate<> SparcFaultBase::FaultVals
577405SAli.Saidi@ARM.com    SparcFault<WatchDogReset>::vals =
5810037SARM gem5 Developers{"watch_dog_reset", 0x002, 120, {H, H, H}, FaultStat()};
5910037SARM gem5 Developers
6011768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
6110037SARM gem5 Developers    SparcFault<ExternallyInitiatedReset>::vals =
6210037SARM gem5 Developers{"externally_initiated_reset", 0x003, 110, {H, H, H}, FaultStat()};
6310037SARM gem5 Developers
6410037SARM gem5 Developerstemplate<> SparcFaultBase::FaultVals
6511768SCurtis.Dunham@arm.com    SparcFault<SoftwareInitiatedReset>::vals =
6610037SARM gem5 Developers{"software_initiated_reset", 0x004, 130, {SH, SH, H}, FaultStat()};
6710037SARM gem5 Developers
6811768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
6911768SCurtis.Dunham@arm.com    SparcFault<REDStateException>::vals =
7011768SCurtis.Dunham@arm.com{"RED_state_exception", 0x005, 1, {H, H, H}, FaultStat()};
7111768SCurtis.Dunham@arm.com
7211768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
7311768SCurtis.Dunham@arm.com    SparcFault<StoreError>::vals =
7411768SCurtis.Dunham@arm.com{"store_error", 0x007, 201, {H, H, H}, FaultStat()};
7511768SCurtis.Dunham@arm.com
7611768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
7711768SCurtis.Dunham@arm.com    SparcFault<InstructionAccessException>::vals =
7811768SCurtis.Dunham@arm.com{"instruction_access_exception", 0x008, 300, {H, H, H}, FaultStat()};
7911768SCurtis.Dunham@arm.com
8010037SARM gem5 Developers//XXX This trap is apparently dropped from ua2005
8110037SARM gem5 Developers/*template<> SparcFaultBase::FaultVals
8210037SARM gem5 Developers    SparcFault<InstructionAccessMMUMiss>::vals =
8311768SCurtis.Dunham@arm.com    {"inst_mmu", 0x009, 2, {H, H, H}};*/
8411768SCurtis.Dunham@arm.com
8511768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
8611768SCurtis.Dunham@arm.com    SparcFault<InstructionAccessError>::vals =
8711768SCurtis.Dunham@arm.com{"instruction_access_error", 0x00A, 400, {H, H, H}, FaultStat()};
8811768SCurtis.Dunham@arm.com
8911768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
9011768SCurtis.Dunham@arm.com    SparcFault<IllegalInstruction>::vals =
9110037SARM gem5 Developers{"illegal_instruction", 0x010, 620, {H, H, H}, FaultStat()};
9211768SCurtis.Dunham@arm.com
9311768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
9411768SCurtis.Dunham@arm.com    SparcFault<PrivilegedOpcode>::vals =
9511768SCurtis.Dunham@arm.com{"privileged_opcode", 0x011, 700, {P, SH, SH}, FaultStat()};
9610037SARM gem5 Developers
9711768SCurtis.Dunham@arm.com//XXX This trap is apparently dropped from ua2005
9811768SCurtis.Dunham@arm.com/*template<> SparcFaultBase::FaultVals
9911768SCurtis.Dunham@arm.com    SparcFault<UnimplementedLDD>::vals =
10011768SCurtis.Dunham@arm.com    {"unimp_ldd", 0x012, 6, {H, H, H}};*/
10111768SCurtis.Dunham@arm.com
10211768SCurtis.Dunham@arm.com//XXX This trap is apparently dropped from ua2005
10311768SCurtis.Dunham@arm.com/*template<> SparcFaultBase::FaultVals
10411768SCurtis.Dunham@arm.com    SparcFault<UnimplementedSTD>::vals =
10511768SCurtis.Dunham@arm.com    {"unimp_std", 0x013, 6, {H, H, H}};*/
10611768SCurtis.Dunham@arm.com
10711768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
10811768SCurtis.Dunham@arm.com    SparcFault<FpDisabled>::vals =
10911768SCurtis.Dunham@arm.com{"fp_disabled", 0x020, 800, {P, P, H}, FaultStat()};
11011768SCurtis.Dunham@arm.com
11111768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
11211768SCurtis.Dunham@arm.com    SparcFault<FpExceptionIEEE754>::vals =
11311768SCurtis.Dunham@arm.com{"fp_exception_ieee_754", 0x021, 1110, {P, P, H}, FaultStat()};
11411768SCurtis.Dunham@arm.com
11510037SARM gem5 Developerstemplate<> SparcFaultBase::FaultVals
11611768SCurtis.Dunham@arm.com    SparcFault<FpExceptionOther>::vals =
11711768SCurtis.Dunham@arm.com{"fp_exception_other", 0x022, 1110, {P, P, H}, FaultStat()};
11811768SCurtis.Dunham@arm.com
11911768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
12010037SARM gem5 Developers    SparcFault<TagOverflow>::vals =
12111768SCurtis.Dunham@arm.com{"tag_overflow", 0x023, 1400, {P, P, H}, FaultStat()};
12211768SCurtis.Dunham@arm.com
12311768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
12411768SCurtis.Dunham@arm.com    SparcFault<CleanWindow>::vals =
12511768SCurtis.Dunham@arm.com{"clean_window", 0x024, 1010, {P, P, H}, FaultStat()};
12611768SCurtis.Dunham@arm.com
12710037SARM gem5 Developerstemplate<> SparcFaultBase::FaultVals
12811768SCurtis.Dunham@arm.com    SparcFault<DivisionByZero>::vals =
12911768SCurtis.Dunham@arm.com{"division_by_zero", 0x028, 1500, {P, P, H}, FaultStat()};
13011768SCurtis.Dunham@arm.com
13111768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
13211768SCurtis.Dunham@arm.com    SparcFault<InternalProcessorError>::vals =
13311768SCurtis.Dunham@arm.com{"internal_processor_error", 0x029, 4, {H, H, H}, FaultStat()};
13411768SCurtis.Dunham@arm.com
13511768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
13611768SCurtis.Dunham@arm.com    SparcFault<InstructionInvalidTSBEntry>::vals =
13711768SCurtis.Dunham@arm.com{"instruction_invalid_tsb_entry", 0x02A, 210, {H, H, SH}, FaultStat()};
13811768SCurtis.Dunham@arm.com
13911768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
14011768SCurtis.Dunham@arm.com    SparcFault<DataInvalidTSBEntry>::vals =
14111768SCurtis.Dunham@arm.com{"data_invalid_tsb_entry", 0x02B, 1203, {H, H, H}, FaultStat()};
14211768SCurtis.Dunham@arm.com
14311768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
14411768SCurtis.Dunham@arm.com    SparcFault<DataAccessException>::vals =
14511768SCurtis.Dunham@arm.com{"data_access_exception", 0x030, 1201, {H, H, H}, FaultStat()};
14611768SCurtis.Dunham@arm.com
14711768SCurtis.Dunham@arm.com//XXX This trap is apparently dropped from ua2005
14811768SCurtis.Dunham@arm.com/*template<> SparcFaultBase::FaultVals
14911768SCurtis.Dunham@arm.com    SparcFault<DataAccessMMUMiss>::vals =
15011768SCurtis.Dunham@arm.com    {"data_mmu", 0x031, 12, {H, H, H}};*/
15111768SCurtis.Dunham@arm.com
15211768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
15311768SCurtis.Dunham@arm.com    SparcFault<DataAccessError>::vals =
15411768SCurtis.Dunham@arm.com{"data_access_error", 0x032, 1210, {H, H, H}, FaultStat()};
15511768SCurtis.Dunham@arm.com
15611768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
15711768SCurtis.Dunham@arm.com    SparcFault<DataAccessProtection>::vals =
15811768SCurtis.Dunham@arm.com{"data_access_protection", 0x033, 1207, {H, H, H}, FaultStat()};
15911768SCurtis.Dunham@arm.com
16011768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
16111768SCurtis.Dunham@arm.com    SparcFault<MemAddressNotAligned>::vals =
16211768SCurtis.Dunham@arm.com{"mem_address_not_aligned", 0x034, 1020, {H, H, H}, FaultStat()};
16311768SCurtis.Dunham@arm.com
16411768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
16511768SCurtis.Dunham@arm.com    SparcFault<LDDFMemAddressNotAligned>::vals =
16611768SCurtis.Dunham@arm.com{"LDDF_mem_address_not_aligned", 0x035, 1010, {H, H, H}, FaultStat()};
16711768SCurtis.Dunham@arm.com
16811768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
16911768SCurtis.Dunham@arm.com    SparcFault<STDFMemAddressNotAligned>::vals =
17011768SCurtis.Dunham@arm.com{"STDF_mem_address_not_aligned", 0x036, 1010, {H, H, H}, FaultStat()};
17111768SCurtis.Dunham@arm.com
17211768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
17311768SCurtis.Dunham@arm.com    SparcFault<PrivilegedAction>::vals =
17411768SCurtis.Dunham@arm.com{"privileged_action", 0x037, 1110, {H, H, SH}, FaultStat()};
17511768SCurtis.Dunham@arm.com
17611768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
17711768SCurtis.Dunham@arm.com    SparcFault<LDQFMemAddressNotAligned>::vals =
17811768SCurtis.Dunham@arm.com{"LDQF_mem_address_not_aligned", 0x038, 1010, {H, H, H}, FaultStat()};
17911768SCurtis.Dunham@arm.com
18011768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
18111768SCurtis.Dunham@arm.com    SparcFault<STQFMemAddressNotAligned>::vals =
18211768SCurtis.Dunham@arm.com{"STQF_mem_address_not_aligned", 0x039, 1010, {H, H, H}, FaultStat()};
18311768SCurtis.Dunham@arm.com
18411768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
18511768SCurtis.Dunham@arm.com    SparcFault<InstructionRealTranslationMiss>::vals =
18611768SCurtis.Dunham@arm.com{"instruction_real_translation_miss", 0x03E, 208, {H, H, SH}, FaultStat()};
18711768SCurtis.Dunham@arm.com
18811768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
18911768SCurtis.Dunham@arm.com    SparcFault<DataRealTranslationMiss>::vals =
19011768SCurtis.Dunham@arm.com{"data_real_translation_miss", 0x03F, 1203, {H, H, H}, FaultStat()};
19111768SCurtis.Dunham@arm.com
19211768SCurtis.Dunham@arm.com//XXX This trap is apparently dropped from ua2005
19311768SCurtis.Dunham@arm.com/*template<> SparcFaultBase::FaultVals
19411768SCurtis.Dunham@arm.com    SparcFault<AsyncDataError>::vals =
19511768SCurtis.Dunham@arm.com    {"async_data", 0x040, 2, {H, H, H}};*/
19611768SCurtis.Dunham@arm.com
19711768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
19811768SCurtis.Dunham@arm.com    SparcFault<InterruptLevelN>::vals =
19911768SCurtis.Dunham@arm.com{"interrupt_level_n", 0x040, 0, {P, P, SH}, FaultStat()};
20011768SCurtis.Dunham@arm.com
20111768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
20211768SCurtis.Dunham@arm.com    SparcFault<HstickMatch>::vals =
20311768SCurtis.Dunham@arm.com{"hstick_match", 0x05E, 1601, {H, H, H}, FaultStat()};
20411768SCurtis.Dunham@arm.com
20510037SARM gem5 Developerstemplate<> SparcFaultBase::FaultVals
20610037SARM gem5 Developers    SparcFault<TrapLevelZero>::vals =
20710037SARM gem5 Developers{"trap_level_zero", 0x05F, 202, {H, H, SH}, FaultStat()};
2089384SAndreas.Sandberg@arm.com
20910461SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals
21010461SAndreas.Sandberg@ARM.com    SparcFault<InterruptVector>::vals =
21111165SRekai.GonzalezAlberquilla@arm.com{"interrupt_vector", 0x060, 2630, {H, H, H}, FaultStat()};
21212109SRekai.GonzalezAlberquilla@arm.com
21310461SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals
21410461SAndreas.Sandberg@ARM.com    SparcFault<PAWatchpoint>::vals =
2159384SAndreas.Sandberg@arm.com{"PA_watchpoint", 0x061, 1209, {H, H, H}, FaultStat()};
21611770SCurtis.Dunham@arm.com
21710037SARM gem5 Developerstemplate<> SparcFaultBase::FaultVals
21810461SAndreas.Sandberg@ARM.com    SparcFault<VAWatchpoint>::vals =
21910461SAndreas.Sandberg@ARM.com{"VA_watchpoint", 0x062, 1120, {P, P, SH}, FaultStat()};
22010461SAndreas.Sandberg@ARM.com
22110461SAndreas.Sandberg@ARM.comtemplate<> SparcFaultBase::FaultVals
22210461SAndreas.Sandberg@ARM.com    SparcFault<FastInstructionAccessMMUMiss>::vals =
22310461SAndreas.Sandberg@ARM.com{"fast_instruction_access_MMU_miss", 0x064, 208, {H, H, SH}, FaultStat()};
22410609Sandreas.sandberg@arm.com
22510609Sandreas.sandberg@arm.comtemplate<> SparcFaultBase::FaultVals
22610609Sandreas.sandberg@arm.com    SparcFault<FastDataAccessMMUMiss>::vals =
22710037SARM gem5 Developers{"fast_data_access_MMU_miss", 0x068, 1203, {H, H, H}, FaultStat()};
22810037SARM gem5 Developers
22910037SARM gem5 Developerstemplate<> SparcFaultBase::FaultVals
23010037SARM gem5 Developers    SparcFault<FastDataAccessProtection>::vals =
23111771SCurtis.Dunham@arm.com{"fast_data_access_protection", 0x06C, 1207, {H, H, H}, FaultStat()};
23210037SARM gem5 Developers
23310037SARM gem5 Developerstemplate<> SparcFaultBase::FaultVals
23410037SARM gem5 Developers    SparcFault<InstructionBreakpoint>::vals =
23510037SARM gem5 Developers{"instruction_break", 0x076, 610, {H, H, H}, FaultStat()};
23610037SARM gem5 Developers
23710037SARM gem5 Developerstemplate<> SparcFaultBase::FaultVals
23811771SCurtis.Dunham@arm.com    SparcFault<CpuMondo>::vals =
23910037SARM gem5 Developers{"cpu_mondo", 0x07C, 1608, {P, P, SH}, FaultStat()};
24010037SARM gem5 Developers
24110037SARM gem5 Developerstemplate<> SparcFaultBase::FaultVals
24210037SARM gem5 Developers    SparcFault<DevMondo>::vals =
24310037SARM gem5 Developers{"dev_mondo", 0x07D, 1611, {P, P, SH}, FaultStat()};
24410037SARM gem5 Developers
24511768SCurtis.Dunham@arm.comtemplate<> SparcFaultBase::FaultVals
24611768SCurtis.Dunham@arm.com    SparcFault<ResumableError>::vals =
24710037SARM gem5 Developers{"resume_error", 0x07E, 3330, {P, P, SH}, FaultStat()};
24810037SARM gem5 Developers
24910037SARM gem5 Developerstemplate<> SparcFaultBase::FaultVals
25010037SARM gem5 Developers    SparcFault<SpillNNormal>::vals =
2519384SAndreas.Sandberg@arm.com{"spill_n_normal", 0x080, 900, {P, P, H}, FaultStat()};
2529384SAndreas.Sandberg@arm.com
2539384SAndreas.Sandberg@arm.comtemplate<> SparcFaultBase::FaultVals
2549384SAndreas.Sandberg@arm.com    SparcFault<SpillNOther>::vals =
2559384SAndreas.Sandberg@arm.com{"spill_n_other", 0x0A0, 900, {P, P, H}, FaultStat()};
2569384SAndreas.Sandberg@arm.com
2579384SAndreas.Sandberg@arm.comtemplate<> SparcFaultBase::FaultVals
2589384SAndreas.Sandberg@arm.com    SparcFault<FillNNormal>::vals =
2599384SAndreas.Sandberg@arm.com{"fill_n_normal", 0x0C0, 900, {P, P, H}, FaultStat()};
2607427Sgblack@eecs.umich.edu
2617427Sgblack@eecs.umich.edutemplate<> SparcFaultBase::FaultVals
2627427Sgblack@eecs.umich.edu    SparcFault<FillNOther>::vals =
2639385SAndreas.Sandberg@arm.com{"fill_n_other", 0x0E0, 900, {P, P, H}, FaultStat()};
2649385SAndreas.Sandberg@arm.com
2657427Sgblack@eecs.umich.edutemplate<> SparcFaultBase::FaultVals
2667427Sgblack@eecs.umich.edu    SparcFault<TrapInstruction>::vals =
26710037SARM gem5 Developers{"trap_instruction", 0x100, 1602, {P, P, H}, FaultStat()};
26810037SARM gem5 Developers
26910037SARM gem5 Developers/**
27010037SARM gem5 Developers * This causes the thread context to enter RED state. This causes the side
27110037SARM gem5 Developers * effects which go with entering RED state because of a trap.
27210037SARM gem5 Developers */
27310037SARM gem5 Developers
27410037SARM gem5 Developersvoid
27510037SARM gem5 DevelopersenterREDState(ThreadContext *tc)
27610037SARM gem5 Developers{
27710037SARM gem5 Developers    //@todo Disable the mmu?
27810037SARM gem5 Developers    //@todo Disable watchpoints?
27910037SARM gem5 Developers    HPSTATE hpstate= tc->readMiscRegNoEffect(MISCREG_HPSTATE);
28010037SARM gem5 Developers    hpstate.red = 1;
2817427Sgblack@eecs.umich.edu    hpstate.hpriv = 1;
2827427Sgblack@eecs.umich.edu    tc->setMiscReg(MISCREG_HPSTATE, hpstate);
2837427Sgblack@eecs.umich.edu    // PSTATE.priv is set to 1 here. The manual says it should be 0, but
2847427Sgblack@eecs.umich.edu    // Legion sets it to 1.
2857427Sgblack@eecs.umich.edu    PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
2867427Sgblack@eecs.umich.edu    pstate.priv = 1;
28710037SARM gem5 Developers    tc->setMiscReg(MISCREG_PSTATE, pstate);
28810037SARM gem5 Developers}
28910037SARM gem5 Developers
29010037SARM gem5 Developers/**
2917427Sgblack@eecs.umich.edu * This sets everything up for a RED state trap except for actually jumping to
2927427Sgblack@eecs.umich.edu * the handler.
2937427Sgblack@eecs.umich.edu */
29410037SARM gem5 Developers
29510204SAli.Saidi@ARM.comvoid
29610204SAli.Saidi@ARM.comdoREDFault(ThreadContext *tc, TrapType tt)
29710037SARM gem5 Developers{
2987427Sgblack@eecs.umich.edu    MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL);
29910037SARM gem5 Developers    MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE);
3007427Sgblack@eecs.umich.edu    PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
30110037SARM gem5 Developers    HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
3027427Sgblack@eecs.umich.edu    MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2);
3037427Sgblack@eecs.umich.edu    MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI);
30410037SARM gem5 Developers    MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP);
3057427Sgblack@eecs.umich.edu    MiscReg CANSAVE = tc->readMiscRegNoEffect(NumIntArchRegs + 3);
3067427Sgblack@eecs.umich.edu    MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL);
3077427Sgblack@eecs.umich.edu    PCState pc = tc->pcState();
3087427Sgblack@eecs.umich.edu
3097427Sgblack@eecs.umich.edu    TL++;
3107427Sgblack@eecs.umich.edu
3117427Sgblack@eecs.umich.edu    Addr pcMask = pstate.am ? mask(32) : mask(64);
3127427Sgblack@eecs.umich.edu
3137427Sgblack@eecs.umich.edu    // set TSTATE.gl to gl
3147427Sgblack@eecs.umich.edu    replaceBits(TSTATE, 42, 40, GL);
3157427Sgblack@eecs.umich.edu    // set TSTATE.ccr to ccr
3167427Sgblack@eecs.umich.edu    replaceBits(TSTATE, 39, 32, CCR);
3177427Sgblack@eecs.umich.edu    // set TSTATE.asi to asi
3187427Sgblack@eecs.umich.edu    replaceBits(TSTATE, 31, 24, ASI);
3197427Sgblack@eecs.umich.edu    // set TSTATE.pstate to pstate
3207427Sgblack@eecs.umich.edu    replaceBits(TSTATE, 20, 8, pstate);
3217427Sgblack@eecs.umich.edu    // set TSTATE.cwp to cwp
3227427Sgblack@eecs.umich.edu    replaceBits(TSTATE, 4, 0, CWP);
3237427Sgblack@eecs.umich.edu
3247427Sgblack@eecs.umich.edu    // Write back TSTATE
3257427Sgblack@eecs.umich.edu    tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE);
3267427Sgblack@eecs.umich.edu
3277427Sgblack@eecs.umich.edu    // set TPC to PC
3287436Sdam.sunwoo@arm.com    tc->setMiscRegNoEffect(MISCREG_TPC, pc.pc() & pcMask);
3297436Sdam.sunwoo@arm.com    // set TNPC to NPC
33010037SARM gem5 Developers    tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask);
33110037SARM gem5 Developers
3327436Sdam.sunwoo@arm.com    // set HTSTATE.hpstate to hpstate
3337436Sdam.sunwoo@arm.com    tc->setMiscRegNoEffect(MISCREG_HTSTATE, hpstate);
3347436Sdam.sunwoo@arm.com
3357436Sdam.sunwoo@arm.com    // TT = trap type;
3367436Sdam.sunwoo@arm.com    tc->setMiscRegNoEffect(MISCREG_TT, tt);
3377436Sdam.sunwoo@arm.com
3387436Sdam.sunwoo@arm.com    // Update GL
3397436Sdam.sunwoo@arm.com    tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL));
3407436Sdam.sunwoo@arm.com
3417436Sdam.sunwoo@arm.com    bool priv = pstate.priv; // just save the priv bit
3427436Sdam.sunwoo@arm.com    pstate = 0;
3437436Sdam.sunwoo@arm.com    pstate.priv = priv;
34410037SARM gem5 Developers    pstate.pef = 1;
3457436Sdam.sunwoo@arm.com    tc->setMiscRegNoEffect(MISCREG_PSTATE, pstate);
3467436Sdam.sunwoo@arm.com
3477436Sdam.sunwoo@arm.com    hpstate.red = 1;
3487436Sdam.sunwoo@arm.com    hpstate.hpriv = 1;
3497436Sdam.sunwoo@arm.com    hpstate.ibe = 0;
3507436Sdam.sunwoo@arm.com    hpstate.tlz = 0;
3517436Sdam.sunwoo@arm.com    tc->setMiscRegNoEffect(MISCREG_HPSTATE, hpstate);
3527436Sdam.sunwoo@arm.com
3537436Sdam.sunwoo@arm.com    bool changedCWP = true;
3547436Sdam.sunwoo@arm.com    if (tt == 0x24)
3557436Sdam.sunwoo@arm.com        CWP++;
3567436Sdam.sunwoo@arm.com    else if (0x80 <= tt && tt <= 0xbf)
3577436Sdam.sunwoo@arm.com        CWP += (CANSAVE + 2);
3587436Sdam.sunwoo@arm.com    else if (0xc0 <= tt && tt <= 0xff)
3597436Sdam.sunwoo@arm.com        CWP--;
3607436Sdam.sunwoo@arm.com    else
3617644Sali.saidi@arm.com        changedCWP = false;
3628147SAli.Saidi@ARM.com
3639385SAndreas.Sandberg@arm.com    if (changedCWP) {
3649385SAndreas.Sandberg@arm.com        CWP = (CWP + NWindows) % NWindows;
3659385SAndreas.Sandberg@arm.com        tc->setMiscReg(MISCREG_CWP, CWP);
3669385SAndreas.Sandberg@arm.com    }
3679385SAndreas.Sandberg@arm.com}
3689385SAndreas.Sandberg@arm.com
3699385SAndreas.Sandberg@arm.com/**
3709385SAndreas.Sandberg@arm.com * This sets everything up for a normal trap except for actually jumping to
3719385SAndreas.Sandberg@arm.com * the handler.
3729385SAndreas.Sandberg@arm.com */
3739385SAndreas.Sandberg@arm.com
3749385SAndreas.Sandberg@arm.comvoid
3759385SAndreas.Sandberg@arm.comdoNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
3769385SAndreas.Sandberg@arm.com{
37710037SARM gem5 Developers    MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL);
37810037SARM gem5 Developers    MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE);
37910037SARM gem5 Developers    PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
38010037SARM gem5 Developers    HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
38110037SARM gem5 Developers    MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2);
38210037SARM gem5 Developers    MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI);
38310037SARM gem5 Developers    MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP);
38410037SARM gem5 Developers    MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3);
38510037SARM gem5 Developers    MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL);
38610037SARM gem5 Developers    PCState pc = tc->pcState();
38710037SARM gem5 Developers
38810037SARM gem5 Developers    // Increment the trap level
38910037SARM gem5 Developers    TL++;
39010037SARM gem5 Developers    tc->setMiscRegNoEffect(MISCREG_TL, TL);
39110037SARM gem5 Developers
39210037SARM gem5 Developers    Addr pcMask = pstate.am ? mask(32) : mask(64);
3938147SAli.Saidi@ARM.com
3947427Sgblack@eecs.umich.edu    // Save off state
3957427Sgblack@eecs.umich.edu
3967427Sgblack@eecs.umich.edu    // set TSTATE.gl to gl
39710037SARM gem5 Developers    replaceBits(TSTATE, 42, 40, GL);
39810037SARM gem5 Developers    // set TSTATE.ccr to ccr
39910037SARM gem5 Developers    replaceBits(TSTATE, 39, 32, CCR);
40010037SARM gem5 Developers    // set TSTATE.asi to asi
40110037SARM gem5 Developers    replaceBits(TSTATE, 31, 24, ASI);
40210037SARM gem5 Developers    // set TSTATE.pstate to pstate
40310037SARM gem5 Developers    replaceBits(TSTATE, 20, 8, pstate);
40410037SARM gem5 Developers    // set TSTATE.cwp to cwp
40510037SARM gem5 Developers    replaceBits(TSTATE, 4, 0, CWP);
40610037SARM gem5 Developers
40710037SARM gem5 Developers    // Write back TSTATE
40810037SARM gem5 Developers    tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE);
40910037SARM gem5 Developers
41010037SARM gem5 Developers    // set TPC to PC
41110037SARM gem5 Developers    tc->setMiscRegNoEffect(MISCREG_TPC, pc.pc() & pcMask);
41210037SARM gem5 Developers    // set TNPC to NPC
41310037SARM gem5 Developers    tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask);
41410037SARM gem5 Developers
41510037SARM gem5 Developers    // set HTSTATE.hpstate to hpstate
41610037SARM gem5 Developers    tc->setMiscRegNoEffect(MISCREG_HTSTATE, hpstate);
41710037SARM gem5 Developers
41810037SARM gem5 Developers    // TT = trap type;
41910037SARM gem5 Developers    tc->setMiscRegNoEffect(MISCREG_TT, tt);
42010037SARM gem5 Developers
42110037SARM gem5 Developers    // Update the global register level
42210037SARM gem5 Developers    if (!gotoHpriv)
42310037SARM gem5 Developers        tc->setMiscReg(MISCREG_GL, min<int>(GL + 1, MaxPGL));
42410037SARM gem5 Developers    else
42510037SARM gem5 Developers        tc->setMiscReg(MISCREG_GL, min<int>(GL + 1, MaxGL));
42610037SARM gem5 Developers
42710037SARM gem5 Developers    // pstate.mm is unchanged
42810037SARM gem5 Developers    pstate.pef = 1; // PSTATE.pef = whether or not an fpu is present
42910037SARM gem5 Developers    pstate.am = 0;
43010037SARM gem5 Developers    pstate.ie = 0;
43110037SARM gem5 Developers    // pstate.tle is unchanged
43210037SARM gem5 Developers    // pstate.tct = 0
43311770SCurtis.Dunham@arm.com
43410037SARM gem5 Developers    if (gotoHpriv) {
43511574SCurtis.Dunham@arm.com        pstate.cle = 0;
43611770SCurtis.Dunham@arm.com        // The manual says PSTATE.priv should be 0, but Legion leaves it alone
43711770SCurtis.Dunham@arm.com        hpstate.red = 0;
43810037SARM gem5 Developers        hpstate.hpriv = 1;
43911770SCurtis.Dunham@arm.com        hpstate.ibe = 0;
44011770SCurtis.Dunham@arm.com        // hpstate.tlz is unchanged
44110037SARM gem5 Developers        tc->setMiscRegNoEffect(MISCREG_HPSTATE, hpstate);
44210037SARM gem5 Developers    } else { // we are going to priv
44310037SARM gem5 Developers        pstate.priv = 1;
44410037SARM gem5 Developers        pstate.cle = pstate.tle;
44510037SARM gem5 Developers    }
44610037SARM gem5 Developers    tc->setMiscRegNoEffect(MISCREG_PSTATE, pstate);
44710037SARM gem5 Developers
44810461SAndreas.Sandberg@ARM.com
44910461SAndreas.Sandberg@ARM.com    bool changedCWP = true;
45010461SAndreas.Sandberg@ARM.com    if (tt == 0x24)
45110461SAndreas.Sandberg@ARM.com        CWP++;
45210037SARM gem5 Developers    else if (0x80 <= tt && tt <= 0xbf)
45310037SARM gem5 Developers        CWP += (CANSAVE + 2);
45410037SARM gem5 Developers    else if (0xc0 <= tt && tt <= 0xff)
45510037SARM gem5 Developers        CWP--;
45610037SARM gem5 Developers    else
45710037SARM gem5 Developers        changedCWP = false;
45810461SAndreas.Sandberg@ARM.com
45910461SAndreas.Sandberg@ARM.com    if (changedCWP) {
46010461SAndreas.Sandberg@ARM.com        CWP = (CWP + NWindows) % NWindows;
46110461SAndreas.Sandberg@ARM.com        tc->setMiscReg(MISCREG_CWP, CWP);
46210461SAndreas.Sandberg@ARM.com    }
46310037SARM gem5 Developers}
46410037SARM gem5 Developers
46510037SARM gem5 Developersvoid
46610037SARM gem5 DevelopersgetREDVector(MiscReg TT, Addr &PC, Addr &NPC)
46710037SARM gem5 Developers{
46811574SCurtis.Dunham@arm.com    //XXX The following constant might belong in a header file.
46910037SARM gem5 Developers    const Addr RSTVAddr = 0xFFF0000000ULL;
47010037SARM gem5 Developers    PC = RSTVAddr | ((TT << 5) & 0xFF);
47110037SARM gem5 Developers    NPC = PC + sizeof(MachInst);
47211574SCurtis.Dunham@arm.com}
47310037SARM gem5 Developers
47410037SARM gem5 Developersvoid
47510037SARM gem5 DevelopersgetHyperVector(ThreadContext * tc, Addr &PC, Addr &NPC, MiscReg TT)
47610037SARM gem5 Developers{
47710037SARM gem5 Developers    Addr HTBA = tc->readMiscRegNoEffect(MISCREG_HTBA);
47810037SARM gem5 Developers    PC = (HTBA & ~mask(14)) | ((TT << 5) & mask(14));
47910037SARM gem5 Developers    NPC = PC + sizeof(MachInst);
48010037SARM gem5 Developers}
48110037SARM gem5 Developers
48210037SARM gem5 Developersvoid
4837405SAli.Saidi@ARM.comgetPrivVector(ThreadContext *tc, Addr &PC, Addr &NPC, MiscReg TT, MiscReg TL)
48410035Sandreas.hansson@arm.com{
4857405SAli.Saidi@ARM.com    Addr TBA = tc->readMiscRegNoEffect(MISCREG_TBA);
4867405SAli.Saidi@ARM.com    PC = (TBA & ~mask(15)) |
4877614Sminkyu.jeong@arm.com        (TL > 1 ? (1 << 14) : 0) |
48811771SCurtis.Dunham@arm.com        ((TT << 5) & mask(14));
48911771SCurtis.Dunham@arm.com    NPC = PC + sizeof(MachInst);
49011771SCurtis.Dunham@arm.com}
49111771SCurtis.Dunham@arm.com
4927405SAli.Saidi@ARM.comvoid
4937405SAli.Saidi@ARM.comSparcFaultBase::invoke(ThreadContext * tc, const StaticInstPtr &inst)
4947405SAli.Saidi@ARM.com{
4957405SAli.Saidi@ARM.com    FaultBase::invoke(tc);
4967405SAli.Saidi@ARM.com    if (!FullSystem)
4977405SAli.Saidi@ARM.com        return;
49810037SARM gem5 Developers
49910037SARM gem5 Developers    countStat()++;
50010037SARM gem5 Developers
5019050Schander.sudanthi@arm.com    // We can refer to this to see what the trap level -was-, but something
5027405SAli.Saidi@ARM.com    // in the middle could change it in the regfile out from under us.
50310037SARM gem5 Developers    MiscReg tl = tc->readMiscRegNoEffect(MISCREG_TL);
50410037SARM gem5 Developers    MiscReg tt = tc->readMiscRegNoEffect(MISCREG_TT);
5057720Sgblack@eecs.umich.edu    PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
5067720Sgblack@eecs.umich.edu    HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
5077405SAli.Saidi@ARM.com
5087405SAli.Saidi@ARM.com    Addr PC, NPC;
5097757SAli.Saidi@ARM.com
51010037SARM gem5 Developers    PrivilegeLevel current;
51110037SARM gem5 Developers    if (hpstate.hpriv)
51210037SARM gem5 Developers        current = Hyperprivileged;
51310037SARM gem5 Developers    else if (pstate.priv)
51410037SARM gem5 Developers        current = Privileged;
51510037SARM gem5 Developers    else
51610037SARM gem5 Developers        current = User;
51710037SARM gem5 Developers
51810037SARM gem5 Developers    PrivilegeLevel level = getNextLevel(current);
51910037SARM gem5 Developers
52010037SARM gem5 Developers    if (hpstate.red || (tl == MaxTL - 1)) {
52110037SARM gem5 Developers        getREDVector(5, PC, NPC);
52210037SARM gem5 Developers        doREDFault(tc, tt);
52310037SARM gem5 Developers        // This changes the hpstate and pstate, so we need to make sure we
52410037SARM gem5 Developers        // save the old version on the trap stack in doREDFault.
52510037SARM gem5 Developers        enterREDState(tc);
52610037SARM gem5 Developers    } else if (tl == MaxTL) {
52710037SARM gem5 Developers        panic("Should go to error state here.. crap\n");
52810037SARM gem5 Developers        // Do error_state somehow?
52910037SARM gem5 Developers        // Probably inject a WDR fault using the interrupt mechanism.
53010037SARM gem5 Developers        // What should the PC and NPC be set to?
53110037SARM gem5 Developers    } else if (tl > MaxPTL && level == Privileged) {
53210037SARM gem5 Developers        // guest_watchdog fault
53310037SARM gem5 Developers        doNormalFault(tc, trapType(), true);
53410037SARM gem5 Developers        getHyperVector(tc, PC, NPC, 2);
53510037SARM gem5 Developers    } else if (level == Hyperprivileged ||
53610037SARM gem5 Developers               (level == Privileged && trapType() >= 384)) {
53710037SARM gem5 Developers        doNormalFault(tc, trapType(), true);
53810037SARM gem5 Developers        getHyperVector(tc, PC, NPC, trapType());
53910037SARM gem5 Developers    } else {
54010037SARM gem5 Developers        doNormalFault(tc, trapType(), false);
54110037SARM gem5 Developers        getPrivVector(tc, PC, NPC, trapType(), tl + 1);
54210037SARM gem5 Developers    }
54310037SARM gem5 Developers
54410037SARM gem5 Developers    PCState pc;
54510037SARM gem5 Developers    pc.pc(PC);
54610037SARM gem5 Developers    pc.npc(NPC);
54710037SARM gem5 Developers    pc.nnpc(NPC + sizeof(MachInst));
54810037SARM gem5 Developers    pc.upc(0);
54910037SARM gem5 Developers    pc.nupc(1);
55010037SARM gem5 Developers    tc->pcState(pc);
55110037SARM gem5 Developers}
55210037SARM gem5 Developers
55310037SARM gem5 Developersvoid
55410037SARM gem5 DevelopersPowerOnReset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
55510037SARM gem5 Developers{
5568284SAli.Saidi@ARM.com    // For SPARC, when a system is first started, there is a power
55710037SARM gem5 Developers    // on reset Trap which sets the processor into the following state.
55810037SARM gem5 Developers    // Bits that aren't set aren't defined on startup.
55910037SARM gem5 Developers
56010037SARM gem5 Developers    tc->setMiscRegNoEffect(MISCREG_TL, MaxTL);
5619050Schander.sudanthi@arm.com    tc->setMiscRegNoEffect(MISCREG_TT, trapType());
56210037SARM gem5 Developers    tc->setMiscReg(MISCREG_GL, MaxGL);
56310037SARM gem5 Developers
56410037SARM gem5 Developers    PSTATE pstate = 0;
56510037SARM gem5 Developers    pstate.pef = 1;
56610037SARM gem5 Developers    pstate.priv = 1;
56710037SARM gem5 Developers    tc->setMiscRegNoEffect(MISCREG_PSTATE, pstate);
56810037SARM gem5 Developers
56910037SARM gem5 Developers    // Turn on red and hpriv, set everything else to 0
57010037SARM gem5 Developers    HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
57110037SARM gem5 Developers    hpstate.red = 1;
57210037SARM gem5 Developers    hpstate.hpriv = 1;
57310037SARM gem5 Developers    hpstate.ibe = 0;
57410037SARM gem5 Developers    hpstate.tlz = 0;
57510037SARM gem5 Developers    tc->setMiscRegNoEffect(MISCREG_HPSTATE, hpstate);
57610037SARM gem5 Developers
57710037SARM gem5 Developers    // The tick register is unreadable by nonprivileged software
57810037SARM gem5 Developers    tc->setMiscRegNoEffect(MISCREG_TICK, 1ULL << 63);
57910037SARM gem5 Developers
5809050Schander.sudanthi@arm.com    // Enter RED state. We do this last so that the actual state preserved in
5818284SAli.Saidi@ARM.com    // the trap stack is the state from before this fault.
58210037SARM gem5 Developers    enterREDState(tc);
58310037SARM gem5 Developers
58410037SARM gem5 Developers    Addr PC, NPC;
58510037SARM gem5 Developers    getREDVector(trapType(), PC, NPC);
58610037SARM gem5 Developers
58710037SARM gem5 Developers    PCState pc;
58810037SARM gem5 Developers    pc.pc(PC);
5897405SAli.Saidi@ARM.com    pc.npc(NPC);
5907731SAli.Saidi@ARM.com    pc.nnpc(NPC + sizeof(MachInst));
5918468Swade.walker@arm.com    pc.upc(0);
5928468Swade.walker@arm.com    pc.nupc(1);
5938468Swade.walker@arm.com    tc->pcState(pc);
5947405SAli.Saidi@ARM.com
5957731SAli.Saidi@ARM.com    // These registers are specified as "undefined" after a POR, and they
5967405SAli.Saidi@ARM.com    // should have reasonable values after the miscregfile is reset
5977405SAli.Saidi@ARM.com    /*
59811809Sbaz21@cam.ac.uk    // Clear all the soft interrupt bits
59911809Sbaz21@cam.ac.uk    softint = 0;
6009130Satgutier@umich.edu    // disable timer compare interrupts, reset tick_cmpr
6019130Satgutier@umich.edu    tc->setMiscRegNoEffect(MISCREG_
6029130Satgutier@umich.edu    tick_cmprFields.int_dis = 1;
6039130Satgutier@umich.edu    tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
6049814Sandreas.hansson@arm.com    stickFields.npt = 1; // The TICK register is unreadable by by !priv
6059130Satgutier@umich.edu    stick_cmprFields.int_dis = 1; // disable timer compare interrupts
6069130Satgutier@umich.edu    stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
6079130Satgutier@umich.edu
6089130Satgutier@umich.edu    tt[tl] = _trapType;
6099130Satgutier@umich.edu
6109130Satgutier@umich.edu    hintp = 0; // no interrupts pending
6119130Satgutier@umich.edu    hstick_cmprFields.int_dis = 1; // disable timer compare interrupts
6129130Satgutier@umich.edu    hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
6139130Satgutier@umich.edu    */
6149130Satgutier@umich.edu}
6159130Satgutier@umich.edu
6169130Satgutier@umich.eduvoid
6179130Satgutier@umich.eduFastInstructionAccessMMUMiss::invoke(ThreadContext *tc,
6189130Satgutier@umich.edu                                     const StaticInstPtr &inst)
6199130Satgutier@umich.edu{
6209130Satgutier@umich.edu    if (FullSystem) {
6219130Satgutier@umich.edu        SparcFaultBase::invoke(tc, inst);
6229130Satgutier@umich.edu        return;
6239130Satgutier@umich.edu    }
6249130Satgutier@umich.edu
6259130Satgutier@umich.edu    Process *p = tc->getProcessPtr();
6269130Satgutier@umich.edu    TlbEntry entry;
6277583SAli.Saidi@arm.com    bool success = p->pTable->lookup(vaddr, entry);
6287583SAli.Saidi@arm.com    if (!success) {
6297583SAli.Saidi@arm.com        panic("Tried to execute unmapped address %#x.\n", vaddr);
63010461SAndreas.Sandberg@ARM.com    } else {
63110461SAndreas.Sandberg@ARM.com        Addr alignedvaddr = p->pTable->pageAlign(vaddr);
63210461SAndreas.Sandberg@ARM.com
63310461SAndreas.Sandberg@ARM.com        // Grab fields used during instruction translation to figure out
63410461SAndreas.Sandberg@ARM.com        // which context to use.
63510461SAndreas.Sandberg@ARM.com        uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);
63610461SAndreas.Sandberg@ARM.com
6378302SAli.Saidi@ARM.com        // Inside a VM, a real address is the address that guest OS would
6388302SAli.Saidi@ARM.com        // interpret to be a physical address. To map to the physical address,
6397783SGiacomo.Gabrielli@arm.com        // it still needs to undergo a translation. The instruction
6407783SGiacomo.Gabrielli@arm.com        // translation code in the SPARC ITLB code assumes that the context is
6417783SGiacomo.Gabrielli@arm.com        // zero (kernel-level) if real addressing is being used.
6427783SGiacomo.Gabrielli@arm.com        bool is_real_address = !bits(tlbdata, 4);
64310037SARM gem5 Developers
64410037SARM gem5 Developers        // The SPARC ITLB code assumes that traps are executed in context
64510037SARM gem5 Developers        // zero so we carry that assumption through here.
64610037SARM gem5 Developers        bool trapped = bits(tlbdata, 18, 16) > 0;
64710037SARM gem5 Developers
64810037SARM gem5 Developers        // The primary context acts as a PASID. It allows the MMU to
64910037SARM gem5 Developers        // distinguish between virtual addresses that would alias to the
65010037SARM gem5 Developers        // same physical address (if two or more processes shared the same
65110037SARM gem5 Developers        // virtual address mapping).
65210037SARM gem5 Developers        int primary_context = bits(tlbdata, 47, 32);
65310037SARM gem5 Developers
65410037SARM gem5 Developers        // The partition id distinguishes between virtualized environments.
65510037SARM gem5 Developers        int const partition_id = 0;
65610037SARM gem5 Developers
65710037SARM gem5 Developers        // Given the assumptions in the translateInst code in the SPARC ITLB,
65810037SARM gem5 Developers        // the logic works out to the following for the context.
65910037SARM gem5 Developers        int context_id = (is_real_address || trapped) ? 0 : primary_context;
66010037SARM gem5 Developers
66110037SARM gem5 Developers        // Insert the TLB entry.
66210037SARM gem5 Developers        // The entry specifying whether the address is "real" is set to
66310037SARM gem5 Developers        // false for syscall emulation mode regardless of whether the
66410037SARM gem5 Developers        // address is real in preceding code. Not sure sure that this is
66510037SARM gem5 Developers        // correct, but also not sure if it matters at all.
66610037SARM gem5 Developers        tc->getITBPtr()->insert(alignedvaddr, partition_id, context_id,
66710037SARM gem5 Developers                                false, entry.pte);
66810037SARM gem5 Developers    }
66910037SARM gem5 Developers}
67010037SARM gem5 Developers
67110037SARM gem5 Developersvoid
67210037SARM gem5 DevelopersFastDataAccessMMUMiss::invoke(ThreadContext *tc, const StaticInstPtr &inst)
67310037SARM gem5 Developers{
67410037SARM gem5 Developers    if (FullSystem) {
67510037SARM gem5 Developers        SparcFaultBase::invoke(tc, inst);
67610037SARM gem5 Developers        return;
67710037SARM gem5 Developers    }
67810037SARM gem5 Developers
67910037SARM gem5 Developers    Process *p = tc->getProcessPtr();
68010037SARM gem5 Developers    TlbEntry entry;
68110338SCurtis.Dunham@arm.com    bool success = p->pTable->lookup(vaddr, entry);
68210338SCurtis.Dunham@arm.com    if (!success) {
68310338SCurtis.Dunham@arm.com        if (p->fixupStackFault(vaddr))
68410037SARM gem5 Developers            success = p->pTable->lookup(vaddr, entry);
68510037SARM gem5 Developers    }
68610037SARM gem5 Developers    if (!success) {
68710037SARM gem5 Developers        panic("Tried to access unmapped address %#x.\n", vaddr);
68810037SARM gem5 Developers    } else {
68910037SARM gem5 Developers        Addr alignedvaddr = p->pTable->pageAlign(vaddr);
69010037SARM gem5 Developers
69110037SARM gem5 Developers        // Grab fields used during data translation to figure out
69210037SARM gem5 Developers        // which context to use.
69310037SARM gem5 Developers        uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);
69410037SARM gem5 Developers
69510037SARM gem5 Developers        // The primary context acts as a PASID. It allows the MMU to
69610037SARM gem5 Developers        // distinguish between virtual addresses that would alias to the
69710037SARM gem5 Developers        // same physical address (if two or more processes shared the same
69810037SARM gem5 Developers        // virtual address mapping). There's a secondary context used in the
69910037SARM gem5 Developers        // DTLB translation code, but it should __probably__ be zero for
70010037SARM gem5 Developers        // syscall emulation code. (The secondary context is used by Solaris
70110037SARM gem5 Developers        // to allow kernel privilege code to access user space code:
70210037SARM gem5 Developers        // [ISBN 0-13-022496-0]:PG199.)
70310037SARM gem5 Developers        int primary_context = bits(tlbdata, 47, 32);
70410037SARM gem5 Developers
70510037SARM gem5 Developers        // "Hyper-Privileged Mode" is in use. There are three main modes of
70610037SARM gem5 Developers        // operation for Sparc: Hyper-Privileged Mode, Privileged Mode, and
70710037SARM gem5 Developers        // User Mode.
70810037SARM gem5 Developers        int hpriv = bits(tlbdata, 0);
70910037SARM gem5 Developers
71010037SARM gem5 Developers        // Reset, Error and Debug state is in use. Something horrible has
71110037SARM gem5 Developers        // happened or the system is operating in Reset Mode.
7128549Sdaniel.johnson@arm.com        int red = bits(tlbdata, 1);
7138868SMatt.Horsnell@arm.com
7148868SMatt.Horsnell@arm.com        // Inside a VM, a real address is the address that guest OS would
7158868SMatt.Horsnell@arm.com        // interpret to be a physical address. To map to the physical address,
7168868SMatt.Horsnell@arm.com        // it still needs to undergo a translation. The instruction
7178868SMatt.Horsnell@arm.com        // translation code in the SPARC ITLB code assumes that the context is
7188868SMatt.Horsnell@arm.com        // zero (kernel-level) if real addressing is being used.
7198868SMatt.Horsnell@arm.com        int is_real_address = !bits(tlbdata, 5);
7208868SMatt.Horsnell@arm.com
7218868SMatt.Horsnell@arm.com        // Grab the address space identifier register from the thread context.
72210461SAndreas.Sandberg@ARM.com        // XXX: Inspecting how setMiscReg and setMiscRegNoEffect behave for
7238868SMatt.Horsnell@arm.com        // MISCREG_ASI causes me to think that the ASI register implementation
72410461SAndreas.Sandberg@ARM.com        // might be bugged. The NoEffect variant changes the ASI register
72510037SARM gem5 Developers        // value in the architectural state while the normal variant changes
7268868SMatt.Horsnell@arm.com        // the context field in the thread context's currently decoded request
72710037SARM gem5 Developers        // but does not directly affect the ASI register value in the
72811150Smitch.hayenga@arm.com        // architectural state. The ASI values and the context field in the
72910037SARM gem5 Developers        // request packet seem to have completely different uses.
73010037SARM gem5 Developers        MiscReg reg_asi = tc->readMiscRegNoEffect(MISCREG_ASI);
73110037SARM gem5 Developers        ASI asi = static_cast<ASI>(reg_asi);
73210037SARM gem5 Developers
73311150Smitch.hayenga@arm.com        // The SPARC DTLB code assumes that traps are executed in context
73410037SARM gem5 Developers        // zero if the asi value is ASI_IMPLICIT (which is 0x0). There's also
73510037SARM gem5 Developers        // an assumption that the nucleus address space is being used, but
73610037SARM gem5 Developers        // the context is the relevant issue since we need to pass it to TLB.
73710037SARM gem5 Developers        bool trapped = bits(tlbdata, 18, 16) > 0;
73810037SARM gem5 Developers
73910037SARM gem5 Developers        // Given the assumptions in the translateData code in the SPARC DTLB,
74010037SARM gem5 Developers        // the logic works out to the following for the context.
74110037SARM gem5 Developers        int context_id = ((!hpriv && !red && is_real_address) ||
74210037SARM gem5 Developers                          asiIsReal(asi) ||
74310037SARM gem5 Developers                          (trapped && asi == ASI_IMPLICIT))
74410037SARM gem5 Developers                         ? 0 : primary_context;
74510037SARM gem5 Developers
74610037SARM gem5 Developers        // The partition id distinguishes between virtualized environments.
74710037SARM gem5 Developers        int const partition_id = 0;
74810037SARM gem5 Developers
74910037SARM gem5 Developers        // Insert the TLB entry.
75010037SARM gem5 Developers        // The entry specifying whether the address is "real" is set to
75110037SARM gem5 Developers        // false for syscall emulation mode regardless of whether the
75210037SARM gem5 Developers        // address is real in preceding code. Not sure sure that this is
75310037SARM gem5 Developers        // correct, but also not sure if it matters at all.
75410037SARM gem5 Developers        tc->getDTBPtr()->insert(alignedvaddr, partition_id, context_id,
75510037SARM gem5 Developers                                false, entry.pte);
75610037SARM gem5 Developers    }
75710037SARM gem5 Developers}
75810037SARM gem5 Developers
75910037SARM gem5 Developersvoid
76010037SARM gem5 DevelopersSpillNNormal::invoke(ThreadContext *tc, const StaticInstPtr &inst)
76110037SARM gem5 Developers{
76210037SARM gem5 Developers    if (FullSystem) {
76311769SCurtis.Dunham@arm.com        SparcFaultBase::invoke(tc, inst);
76411769SCurtis.Dunham@arm.com        return;
76510037SARM gem5 Developers    }
76611770SCurtis.Dunham@arm.com
76711770SCurtis.Dunham@arm.com    doNormalFault(tc, trapType(), false);
76810037SARM gem5 Developers
76911770SCurtis.Dunham@arm.com    Process *p = tc->getProcessPtr();
77011769SCurtis.Dunham@arm.com
77110844Sandreas.sandberg@arm.com    SparcProcess *sp = dynamic_cast<SparcProcess *>(p);
77211772SCurtis.Dunham@arm.com    assert(sp);
77311772SCurtis.Dunham@arm.com
77411772SCurtis.Dunham@arm.com    // Then adjust the PC and NPC
77511772SCurtis.Dunham@arm.com    tc->pcState(sp->readSpillStart());
77611774SCurtis.Dunham@arm.com}
77711774SCurtis.Dunham@arm.com
77811774SCurtis.Dunham@arm.comvoid
77911774SCurtis.Dunham@arm.comFillNNormal::invoke(ThreadContext *tc, const StaticInstPtr &inst)
78011774SCurtis.Dunham@arm.com{
78111774SCurtis.Dunham@arm.com    if (FullSystem) {
78211774SCurtis.Dunham@arm.com        SparcFaultBase::invoke(tc, inst);
78311773SCurtis.Dunham@arm.com        return;
78411773SCurtis.Dunham@arm.com    }
78511773SCurtis.Dunham@arm.com
78611773SCurtis.Dunham@arm.com    doNormalFault(tc, trapType(), false);
78711773SCurtis.Dunham@arm.com
78811773SCurtis.Dunham@arm.com    Process *p = tc->getProcessPtr();
78911773SCurtis.Dunham@arm.com
79011772SCurtis.Dunham@arm.com    SparcProcess *sp = dynamic_cast<SparcProcess *>(p);
79110037SARM gem5 Developers    assert(sp);
79210844Sandreas.sandberg@arm.com
79310844Sandreas.sandberg@arm.com    // Then adjust the PC and NPC
79410844Sandreas.sandberg@arm.com    tc->pcState(sp->readFillStart());
79510844Sandreas.sandberg@arm.com}
79610844Sandreas.sandberg@arm.com
79710844Sandreas.sandberg@arm.comvoid
79810188Sgeoffrey.blake@arm.comTrapInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
79910037SARM gem5 Developers{
80010037SARM gem5 Developers    if (FullSystem) {
8017405SAli.Saidi@ARM.com        SparcFaultBase::invoke(tc, inst);
8027405SAli.Saidi@ARM.com        return;
8037405SAli.Saidi@ARM.com    }
8047405SAli.Saidi@ARM.com
8057405SAli.Saidi@ARM.com    // In SE, this mechanism is how the process requests a service from
8067405SAli.Saidi@ARM.com    // the operating system. We'll get the process object from the thread
8077405SAli.Saidi@ARM.com    // context and let it service the request.
8087405SAli.Saidi@ARM.com
8097614Sminkyu.jeong@arm.com    Process *p = tc->getProcessPtr();
81011771SCurtis.Dunham@arm.com
81111771SCurtis.Dunham@arm.com    SparcProcess *sp = dynamic_cast<SparcProcess *>(p);
81211771SCurtis.Dunham@arm.com    assert(sp);
81311771SCurtis.Dunham@arm.com
81411771SCurtis.Dunham@arm.com    sp->handleTrap(_n, tc);
81510037SARM gem5 Developers
81611771SCurtis.Dunham@arm.com    // We need to explicitly advance the pc, since that's not done for us
81710037SARM gem5 Developers    // on a faulting instruction
81811771SCurtis.Dunham@arm.com    PCState pc = tc->pcState();
81910037SARM gem5 Developers    pc.advance();
82011771SCurtis.Dunham@arm.com    tc->pcState(pc);
82110037SARM gem5 Developers}
8227405SAli.Saidi@ARM.com
8237405SAli.Saidi@ARM.com} // namespace SparcISA
8247405SAli.Saidi@ARM.com
8257405SAli.Saidi@ARM.com