2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "arch/sparc/faults.hh"
36 #include "arch/sparc/isa_traits.hh"
37 #include "arch/sparc/process.hh"
38 #include "arch/sparc/types.hh"
39 #include "base/bitfield.hh"
40 #include "base/trace.hh"
41 #include "cpu/base.hh"
42 #include "cpu/thread_context.hh"
43 #include "mem/page_table.hh"
44 #include "sim/full_system.hh"
45 #include "sim/process.hh"
52 template<> SparcFaultBase::FaultVals
53 SparcFault
<PowerOnReset
>::vals
=
54 {"power_on_reset", 0x001, 0, {H
, H
, H
}, FaultStat()};
56 template<> SparcFaultBase::FaultVals
57 SparcFault
<WatchDogReset
>::vals
=
58 {"watch_dog_reset", 0x002, 120, {H
, H
, H
}, FaultStat()};
60 template<> SparcFaultBase::FaultVals
61 SparcFault
<ExternallyInitiatedReset
>::vals
=
62 {"externally_initiated_reset", 0x003, 110, {H
, H
, H
}, FaultStat()};
64 template<> SparcFaultBase::FaultVals
65 SparcFault
<SoftwareInitiatedReset
>::vals
=
66 {"software_initiated_reset", 0x004, 130, {SH
, SH
, H
}, FaultStat()};
68 template<> SparcFaultBase::FaultVals
69 SparcFault
<REDStateException
>::vals
=
70 {"RED_state_exception", 0x005, 1, {H
, H
, H
}, FaultStat()};
72 template<> SparcFaultBase::FaultVals
73 SparcFault
<StoreError
>::vals
=
74 {"store_error", 0x007, 201, {H
, H
, H
}, FaultStat()};
76 template<> SparcFaultBase::FaultVals
77 SparcFault
<InstructionAccessException
>::vals
=
78 {"instruction_access_exception", 0x008, 300, {H
, H
, H
}, FaultStat()};
80 //XXX This trap is apparently dropped from ua2005
81 /*template<> SparcFaultBase::FaultVals
82 SparcFault<InstructionAccessMMUMiss>::vals =
83 {"inst_mmu", 0x009, 2, {H, H, H}};*/
85 template<> SparcFaultBase::FaultVals
86 SparcFault
<InstructionAccessError
>::vals
=
87 {"instruction_access_error", 0x00A, 400, {H
, H
, H
}, FaultStat()};
89 template<> SparcFaultBase::FaultVals
90 SparcFault
<IllegalInstruction
>::vals
=
91 {"illegal_instruction", 0x010, 620, {H
, H
, H
}, FaultStat()};
93 template<> SparcFaultBase::FaultVals
94 SparcFault
<PrivilegedOpcode
>::vals
=
95 {"privileged_opcode", 0x011, 700, {P
, SH
, SH
}, FaultStat()};
97 //XXX This trap is apparently dropped from ua2005
98 /*template<> SparcFaultBase::FaultVals
99 SparcFault<UnimplementedLDD>::vals =
100 {"unimp_ldd", 0x012, 6, {H, H, H}};*/
102 //XXX This trap is apparently dropped from ua2005
103 /*template<> SparcFaultBase::FaultVals
104 SparcFault<UnimplementedSTD>::vals =
105 {"unimp_std", 0x013, 6, {H, H, H}};*/
107 template<> SparcFaultBase::FaultVals
108 SparcFault
<FpDisabled
>::vals
=
109 {"fp_disabled", 0x020, 800, {P
, P
, H
}, FaultStat()};
111 /* SPARCv8 and SPARCv9 define just fp_disabled trap. SIMD is not contemplated
112 * as a separate part. Therefore, we use the same code and TT */
113 template<> SparcFaultBase::FaultVals
114 SparcFault
<VecDisabled
>::vals
=
115 {"fp_disabled", 0x020, 800, {P
, P
, H
}, FaultStat()};
117 template<> SparcFaultBase::FaultVals
118 SparcFault
<FpExceptionIEEE754
>::vals
=
119 {"fp_exception_ieee_754", 0x021, 1110, {P
, P
, H
}, FaultStat()};
121 template<> SparcFaultBase::FaultVals
122 SparcFault
<FpExceptionOther
>::vals
=
123 {"fp_exception_other", 0x022, 1110, {P
, P
, H
}, FaultStat()};
125 template<> SparcFaultBase::FaultVals
126 SparcFault
<TagOverflow
>::vals
=
127 {"tag_overflow", 0x023, 1400, {P
, P
, H
}, FaultStat()};
129 template<> SparcFaultBase::FaultVals
130 SparcFault
<CleanWindow
>::vals
=
131 {"clean_window", 0x024, 1010, {P
, P
, H
}, FaultStat()};
133 template<> SparcFaultBase::FaultVals
134 SparcFault
<DivisionByZero
>::vals
=
135 {"division_by_zero", 0x028, 1500, {P
, P
, H
}, FaultStat()};
137 template<> SparcFaultBase::FaultVals
138 SparcFault
<InternalProcessorError
>::vals
=
139 {"internal_processor_error", 0x029, 4, {H
, H
, H
}, FaultStat()};
141 template<> SparcFaultBase::FaultVals
142 SparcFault
<InstructionInvalidTSBEntry
>::vals
=
143 {"instruction_invalid_tsb_entry", 0x02A, 210, {H
, H
, SH
}, FaultStat()};
145 template<> SparcFaultBase::FaultVals
146 SparcFault
<DataInvalidTSBEntry
>::vals
=
147 {"data_invalid_tsb_entry", 0x02B, 1203, {H
, H
, H
}, FaultStat()};
149 template<> SparcFaultBase::FaultVals
150 SparcFault
<DataAccessException
>::vals
=
151 {"data_access_exception", 0x030, 1201, {H
, H
, H
}, FaultStat()};
153 //XXX This trap is apparently dropped from ua2005
154 /*template<> SparcFaultBase::FaultVals
155 SparcFault<DataAccessMMUMiss>::vals =
156 {"data_mmu", 0x031, 12, {H, H, H}};*/
158 template<> SparcFaultBase::FaultVals
159 SparcFault
<DataAccessError
>::vals
=
160 {"data_access_error", 0x032, 1210, {H
, H
, H
}, FaultStat()};
162 template<> SparcFaultBase::FaultVals
163 SparcFault
<DataAccessProtection
>::vals
=
164 {"data_access_protection", 0x033, 1207, {H
, H
, H
}, FaultStat()};
166 template<> SparcFaultBase::FaultVals
167 SparcFault
<MemAddressNotAligned
>::vals
=
168 {"mem_address_not_aligned", 0x034, 1020, {H
, H
, H
}, FaultStat()};
170 template<> SparcFaultBase::FaultVals
171 SparcFault
<LDDFMemAddressNotAligned
>::vals
=
172 {"LDDF_mem_address_not_aligned", 0x035, 1010, {H
, H
, H
}, FaultStat()};
174 template<> SparcFaultBase::FaultVals
175 SparcFault
<STDFMemAddressNotAligned
>::vals
=
176 {"STDF_mem_address_not_aligned", 0x036, 1010, {H
, H
, H
}, FaultStat()};
178 template<> SparcFaultBase::FaultVals
179 SparcFault
<PrivilegedAction
>::vals
=
180 {"privileged_action", 0x037, 1110, {H
, H
, SH
}, FaultStat()};
182 template<> SparcFaultBase::FaultVals
183 SparcFault
<LDQFMemAddressNotAligned
>::vals
=
184 {"LDQF_mem_address_not_aligned", 0x038, 1010, {H
, H
, H
}, FaultStat()};
186 template<> SparcFaultBase::FaultVals
187 SparcFault
<STQFMemAddressNotAligned
>::vals
=
188 {"STQF_mem_address_not_aligned", 0x039, 1010, {H
, H
, H
}, FaultStat()};
190 template<> SparcFaultBase::FaultVals
191 SparcFault
<InstructionRealTranslationMiss
>::vals
=
192 {"instruction_real_translation_miss", 0x03E, 208, {H
, H
, SH
}, FaultStat()};
194 template<> SparcFaultBase::FaultVals
195 SparcFault
<DataRealTranslationMiss
>::vals
=
196 {"data_real_translation_miss", 0x03F, 1203, {H
, H
, H
}, FaultStat()};
198 //XXX This trap is apparently dropped from ua2005
199 /*template<> SparcFaultBase::FaultVals
200 SparcFault<AsyncDataError>::vals =
201 {"async_data", 0x040, 2, {H, H, H}};*/
203 template<> SparcFaultBase::FaultVals
204 SparcFault
<InterruptLevelN
>::vals
=
205 {"interrupt_level_n", 0x040, 0, {P
, P
, SH
}, FaultStat()};
207 template<> SparcFaultBase::FaultVals
208 SparcFault
<HstickMatch
>::vals
=
209 {"hstick_match", 0x05E, 1601, {H
, H
, H
}, FaultStat()};
211 template<> SparcFaultBase::FaultVals
212 SparcFault
<TrapLevelZero
>::vals
=
213 {"trap_level_zero", 0x05F, 202, {H
, H
, SH
}, FaultStat()};
215 template<> SparcFaultBase::FaultVals
216 SparcFault
<InterruptVector
>::vals
=
217 {"interrupt_vector", 0x060, 2630, {H
, H
, H
}, FaultStat()};
219 template<> SparcFaultBase::FaultVals
220 SparcFault
<PAWatchpoint
>::vals
=
221 {"PA_watchpoint", 0x061, 1209, {H
, H
, H
}, FaultStat()};
223 template<> SparcFaultBase::FaultVals
224 SparcFault
<VAWatchpoint
>::vals
=
225 {"VA_watchpoint", 0x062, 1120, {P
, P
, SH
}, FaultStat()};
227 template<> SparcFaultBase::FaultVals
228 SparcFault
<FastInstructionAccessMMUMiss
>::vals
=
229 {"fast_instruction_access_MMU_miss", 0x064, 208, {H
, H
, SH
}, FaultStat()};
231 template<> SparcFaultBase::FaultVals
232 SparcFault
<FastDataAccessMMUMiss
>::vals
=
233 {"fast_data_access_MMU_miss", 0x068, 1203, {H
, H
, H
}, FaultStat()};
235 template<> SparcFaultBase::FaultVals
236 SparcFault
<FastDataAccessProtection
>::vals
=
237 {"fast_data_access_protection", 0x06C, 1207, {H
, H
, H
}, FaultStat()};
239 template<> SparcFaultBase::FaultVals
240 SparcFault
<InstructionBreakpoint
>::vals
=
241 {"instruction_break", 0x076, 610, {H
, H
, H
}, FaultStat()};
243 template<> SparcFaultBase::FaultVals
244 SparcFault
<CpuMondo
>::vals
=
245 {"cpu_mondo", 0x07C, 1608, {P
, P
, SH
}, FaultStat()};
247 template<> SparcFaultBase::FaultVals
248 SparcFault
<DevMondo
>::vals
=
249 {"dev_mondo", 0x07D, 1611, {P
, P
, SH
}, FaultStat()};
251 template<> SparcFaultBase::FaultVals
252 SparcFault
<ResumableError
>::vals
=
253 {"resume_error", 0x07E, 3330, {P
, P
, SH
}, FaultStat()};
255 template<> SparcFaultBase::FaultVals
256 SparcFault
<SpillNNormal
>::vals
=
257 {"spill_n_normal", 0x080, 900, {P
, P
, H
}, FaultStat()};
259 template<> SparcFaultBase::FaultVals
260 SparcFault
<SpillNOther
>::vals
=
261 {"spill_n_other", 0x0A0, 900, {P
, P
, H
}, FaultStat()};
263 template<> SparcFaultBase::FaultVals
264 SparcFault
<FillNNormal
>::vals
=
265 {"fill_n_normal", 0x0C0, 900, {P
, P
, H
}, FaultStat()};
267 template<> SparcFaultBase::FaultVals
268 SparcFault
<FillNOther
>::vals
=
269 {"fill_n_other", 0x0E0, 900, {P
, P
, H
}, FaultStat()};
271 template<> SparcFaultBase::FaultVals
272 SparcFault
<TrapInstruction
>::vals
=
273 {"trap_instruction", 0x100, 1602, {P
, P
, H
}, FaultStat()};
276 * This causes the thread context to enter RED state. This causes the side
277 * effects which go with entering RED state because of a trap.
281 enterREDState(ThreadContext
*tc
)
283 //@todo Disable the mmu?
284 //@todo Disable watchpoints?
285 HPSTATE hpstate
= tc
->readMiscRegNoEffect(MISCREG_HPSTATE
);
288 tc
->setMiscReg(MISCREG_HPSTATE
, hpstate
);
289 // PSTATE.priv is set to 1 here. The manual says it should be 0, but
290 // Legion sets it to 1.
291 PSTATE pstate
= tc
->readMiscRegNoEffect(MISCREG_PSTATE
);
293 tc
->setMiscReg(MISCREG_PSTATE
, pstate
);
297 * This sets everything up for a RED state trap except for actually jumping to
302 doREDFault(ThreadContext
*tc
, TrapType tt
)
304 MiscReg TL
= tc
->readMiscRegNoEffect(MISCREG_TL
);
305 MiscReg TSTATE
= tc
->readMiscRegNoEffect(MISCREG_TSTATE
);
306 PSTATE pstate
= tc
->readMiscRegNoEffect(MISCREG_PSTATE
);
307 HPSTATE hpstate
= tc
->readMiscRegNoEffect(MISCREG_HPSTATE
);
308 MiscReg CCR
= tc
->readIntReg(NumIntArchRegs
+ 2);
309 MiscReg ASI
= tc
->readMiscRegNoEffect(MISCREG_ASI
);
310 MiscReg CWP
= tc
->readMiscRegNoEffect(MISCREG_CWP
);
311 MiscReg CANSAVE
= tc
->readMiscRegNoEffect(NumIntArchRegs
+ 3);
312 MiscReg GL
= tc
->readMiscRegNoEffect(MISCREG_GL
);
313 PCState pc
= tc
->pcState();
317 Addr pcMask
= pstate
.am
? mask(32) : mask(64);
319 // set TSTATE.gl to gl
320 replaceBits(TSTATE
, 42, 40, GL
);
321 // set TSTATE.ccr to ccr
322 replaceBits(TSTATE
, 39, 32, CCR
);
323 // set TSTATE.asi to asi
324 replaceBits(TSTATE
, 31, 24, ASI
);
325 // set TSTATE.pstate to pstate
326 replaceBits(TSTATE
, 20, 8, pstate
);
327 // set TSTATE.cwp to cwp
328 replaceBits(TSTATE
, 4, 0, CWP
);
331 tc
->setMiscRegNoEffect(MISCREG_TSTATE
, TSTATE
);
334 tc
->setMiscRegNoEffect(MISCREG_TPC
, pc
.pc() & pcMask
);
336 tc
->setMiscRegNoEffect(MISCREG_TNPC
, pc
.npc() & pcMask
);
338 // set HTSTATE.hpstate to hpstate
339 tc
->setMiscRegNoEffect(MISCREG_HTSTATE
, hpstate
);
342 tc
->setMiscRegNoEffect(MISCREG_TT
, tt
);
345 tc
->setMiscReg(MISCREG_GL
, min
<int>(GL
+1, MaxGL
));
347 bool priv
= pstate
.priv
; // just save the priv bit
351 tc
->setMiscRegNoEffect(MISCREG_PSTATE
, pstate
);
357 tc
->setMiscRegNoEffect(MISCREG_HPSTATE
, hpstate
);
359 bool changedCWP
= true;
362 else if (0x80 <= tt
&& tt
<= 0xbf)
363 CWP
+= (CANSAVE
+ 2);
364 else if (0xc0 <= tt
&& tt
<= 0xff)
370 CWP
= (CWP
+ NWindows
) % NWindows
;
371 tc
->setMiscReg(MISCREG_CWP
, CWP
);
376 * This sets everything up for a normal trap except for actually jumping to
381 doNormalFault(ThreadContext
*tc
, TrapType tt
, bool gotoHpriv
)
383 MiscReg TL
= tc
->readMiscRegNoEffect(MISCREG_TL
);
384 MiscReg TSTATE
= tc
->readMiscRegNoEffect(MISCREG_TSTATE
);
385 PSTATE pstate
= tc
->readMiscRegNoEffect(MISCREG_PSTATE
);
386 HPSTATE hpstate
= tc
->readMiscRegNoEffect(MISCREG_HPSTATE
);
387 MiscReg CCR
= tc
->readIntReg(NumIntArchRegs
+ 2);
388 MiscReg ASI
= tc
->readMiscRegNoEffect(MISCREG_ASI
);
389 MiscReg CWP
= tc
->readMiscRegNoEffect(MISCREG_CWP
);
390 MiscReg CANSAVE
= tc
->readIntReg(NumIntArchRegs
+ 3);
391 MiscReg GL
= tc
->readMiscRegNoEffect(MISCREG_GL
);
392 PCState pc
= tc
->pcState();
394 // Increment the trap level
396 tc
->setMiscRegNoEffect(MISCREG_TL
, TL
);
398 Addr pcMask
= pstate
.am
? mask(32) : mask(64);
402 // set TSTATE.gl to gl
403 replaceBits(TSTATE
, 42, 40, GL
);
404 // set TSTATE.ccr to ccr
405 replaceBits(TSTATE
, 39, 32, CCR
);
406 // set TSTATE.asi to asi
407 replaceBits(TSTATE
, 31, 24, ASI
);
408 // set TSTATE.pstate to pstate
409 replaceBits(TSTATE
, 20, 8, pstate
);
410 // set TSTATE.cwp to cwp
411 replaceBits(TSTATE
, 4, 0, CWP
);
414 tc
->setMiscRegNoEffect(MISCREG_TSTATE
, TSTATE
);
417 tc
->setMiscRegNoEffect(MISCREG_TPC
, pc
.pc() & pcMask
);
419 tc
->setMiscRegNoEffect(MISCREG_TNPC
, pc
.npc() & pcMask
);
421 // set HTSTATE.hpstate to hpstate
422 tc
->setMiscRegNoEffect(MISCREG_HTSTATE
, hpstate
);
425 tc
->setMiscRegNoEffect(MISCREG_TT
, tt
);
427 // Update the global register level
429 tc
->setMiscReg(MISCREG_GL
, min
<int>(GL
+ 1, MaxPGL
));
431 tc
->setMiscReg(MISCREG_GL
, min
<int>(GL
+ 1, MaxGL
));
433 // pstate.mm is unchanged
434 pstate
.pef
= 1; // PSTATE.pef = whether or not an fpu is present
437 // pstate.tle is unchanged
442 // The manual says PSTATE.priv should be 0, but Legion leaves it alone
446 // hpstate.tlz is unchanged
447 tc
->setMiscRegNoEffect(MISCREG_HPSTATE
, hpstate
);
448 } else { // we are going to priv
450 pstate
.cle
= pstate
.tle
;
452 tc
->setMiscRegNoEffect(MISCREG_PSTATE
, pstate
);
455 bool changedCWP
= true;
458 else if (0x80 <= tt
&& tt
<= 0xbf)
459 CWP
+= (CANSAVE
+ 2);
460 else if (0xc0 <= tt
&& tt
<= 0xff)
466 CWP
= (CWP
+ NWindows
) % NWindows
;
467 tc
->setMiscReg(MISCREG_CWP
, CWP
);
472 getREDVector(MiscReg TT
, Addr
&PC
, Addr
&NPC
)
474 //XXX The following constant might belong in a header file.
475 const Addr RSTVAddr
= 0xFFF0000000ULL
;
476 PC
= RSTVAddr
| ((TT
<< 5) & 0xFF);
477 NPC
= PC
+ sizeof(MachInst
);
481 getHyperVector(ThreadContext
* tc
, Addr
&PC
, Addr
&NPC
, MiscReg TT
)
483 Addr HTBA
= tc
->readMiscRegNoEffect(MISCREG_HTBA
);
484 PC
= (HTBA
& ~mask(14)) | ((TT
<< 5) & mask(14));
485 NPC
= PC
+ sizeof(MachInst
);
489 getPrivVector(ThreadContext
*tc
, Addr
&PC
, Addr
&NPC
, MiscReg TT
, MiscReg TL
)
491 Addr TBA
= tc
->readMiscRegNoEffect(MISCREG_TBA
);
492 PC
= (TBA
& ~mask(15)) |
493 (TL
> 1 ? (1 << 14) : 0) |
494 ((TT
<< 5) & mask(14));
495 NPC
= PC
+ sizeof(MachInst
);
499 SparcFaultBase::invoke(ThreadContext
* tc
, const StaticInstPtr
&inst
)
501 FaultBase::invoke(tc
);
507 // We can refer to this to see what the trap level -was-, but something
508 // in the middle could change it in the regfile out from under us.
509 MiscReg tl
= tc
->readMiscRegNoEffect(MISCREG_TL
);
510 MiscReg tt
= tc
->readMiscRegNoEffect(MISCREG_TT
);
511 PSTATE pstate
= tc
->readMiscRegNoEffect(MISCREG_PSTATE
);
512 HPSTATE hpstate
= tc
->readMiscRegNoEffect(MISCREG_HPSTATE
);
516 PrivilegeLevel current
;
518 current
= Hyperprivileged
;
519 else if (pstate
.priv
)
520 current
= Privileged
;
524 PrivilegeLevel level
= getNextLevel(current
);
526 if (hpstate
.red
|| (tl
== MaxTL
- 1)) {
527 getREDVector(5, PC
, NPC
);
529 // This changes the hpstate and pstate, so we need to make sure we
530 // save the old version on the trap stack in doREDFault.
532 } else if (tl
== MaxTL
) {
533 panic("Should go to error state here.. crap\n");
534 // Do error_state somehow?
535 // Probably inject a WDR fault using the interrupt mechanism.
536 // What should the PC and NPC be set to?
537 } else if (tl
> MaxPTL
&& level
== Privileged
) {
538 // guest_watchdog fault
539 doNormalFault(tc
, trapType(), true);
540 getHyperVector(tc
, PC
, NPC
, 2);
541 } else if (level
== Hyperprivileged
||
542 (level
== Privileged
&& trapType() >= 384)) {
543 doNormalFault(tc
, trapType(), true);
544 getHyperVector(tc
, PC
, NPC
, trapType());
546 doNormalFault(tc
, trapType(), false);
547 getPrivVector(tc
, PC
, NPC
, trapType(), tl
+ 1);
553 pc
.nnpc(NPC
+ sizeof(MachInst
));
560 PowerOnReset::invoke(ThreadContext
*tc
, const StaticInstPtr
&inst
)
562 // For SPARC, when a system is first started, there is a power
563 // on reset Trap which sets the processor into the following state.
564 // Bits that aren't set aren't defined on startup.
566 tc
->setMiscRegNoEffect(MISCREG_TL
, MaxTL
);
567 tc
->setMiscRegNoEffect(MISCREG_TT
, trapType());
568 tc
->setMiscReg(MISCREG_GL
, MaxGL
);
573 tc
->setMiscRegNoEffect(MISCREG_PSTATE
, pstate
);
575 // Turn on red and hpriv, set everything else to 0
576 HPSTATE hpstate
= tc
->readMiscRegNoEffect(MISCREG_HPSTATE
);
581 tc
->setMiscRegNoEffect(MISCREG_HPSTATE
, hpstate
);
583 // The tick register is unreadable by nonprivileged software
584 tc
->setMiscRegNoEffect(MISCREG_TICK
, 1ULL << 63);
586 // Enter RED state. We do this last so that the actual state preserved in
587 // the trap stack is the state from before this fault.
591 getREDVector(trapType(), PC
, NPC
);
596 pc
.nnpc(NPC
+ sizeof(MachInst
));
601 // These registers are specified as "undefined" after a POR, and they
602 // should have reasonable values after the miscregfile is reset
604 // Clear all the soft interrupt bits
606 // disable timer compare interrupts, reset tick_cmpr
607 tc->setMiscRegNoEffect(MISCREG_
608 tick_cmprFields.int_dis = 1;
609 tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
610 stickFields.npt = 1; // The TICK register is unreadable by by !priv
611 stick_cmprFields.int_dis = 1; // disable timer compare interrupts
612 stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
616 hintp = 0; // no interrupts pending
617 hstick_cmprFields.int_dis = 1; // disable timer compare interrupts
618 hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
623 FastInstructionAccessMMUMiss::invoke(ThreadContext
*tc
,
624 const StaticInstPtr
&inst
)
627 SparcFaultBase::invoke(tc
, inst
);
631 Process
*p
= tc
->getProcessPtr();
633 bool success
= p
->pTable
->lookup(vaddr
, entry
);
635 panic("Tried to execute unmapped address %#x.\n", vaddr
);
637 Addr alignedvaddr
= p
->pTable
->pageAlign(vaddr
);
639 // Grab fields used during instruction translation to figure out
640 // which context to use.
641 uint64_t tlbdata
= tc
->readMiscRegNoEffect(MISCREG_TLB_DATA
);
643 // Inside a VM, a real address is the address that guest OS would
644 // interpret to be a physical address. To map to the physical address,
645 // it still needs to undergo a translation. The instruction
646 // translation code in the SPARC ITLB code assumes that the context is
647 // zero (kernel-level) if real addressing is being used.
648 bool is_real_address
= !bits(tlbdata
, 4);
650 // The SPARC ITLB code assumes that traps are executed in context
651 // zero so we carry that assumption through here.
652 bool trapped
= bits(tlbdata
, 18, 16) > 0;
654 // The primary context acts as a PASID. It allows the MMU to
655 // distinguish between virtual addresses that would alias to the
656 // same physical address (if two or more processes shared the same
657 // virtual address mapping).
658 int primary_context
= bits(tlbdata
, 47, 32);
660 // The partition id distinguishes between virtualized environments.
661 int const partition_id
= 0;
663 // Given the assumptions in the translateInst code in the SPARC ITLB,
664 // the logic works out to the following for the context.
665 int context_id
= (is_real_address
|| trapped
) ? 0 : primary_context
;
667 // Insert the TLB entry.
668 // The entry specifying whether the address is "real" is set to
669 // false for syscall emulation mode regardless of whether the
670 // address is real in preceding code. Not sure sure that this is
671 // correct, but also not sure if it matters at all.
672 tc
->getITBPtr()->insert(alignedvaddr
, partition_id
, context_id
,
678 FastDataAccessMMUMiss::invoke(ThreadContext
*tc
, const StaticInstPtr
&inst
)
681 SparcFaultBase::invoke(tc
, inst
);
685 Process
*p
= tc
->getProcessPtr();
687 bool success
= p
->pTable
->lookup(vaddr
, entry
);
689 if (p
->fixupStackFault(vaddr
))
690 success
= p
->pTable
->lookup(vaddr
, entry
);
693 panic("Tried to access unmapped address %#x.\n", vaddr
);
695 Addr alignedvaddr
= p
->pTable
->pageAlign(vaddr
);
697 // Grab fields used during data translation to figure out
698 // which context to use.
699 uint64_t tlbdata
= tc
->readMiscRegNoEffect(MISCREG_TLB_DATA
);
701 // The primary context acts as a PASID. It allows the MMU to
702 // distinguish between virtual addresses that would alias to the
703 // same physical address (if two or more processes shared the same
704 // virtual address mapping). There's a secondary context used in the
705 // DTLB translation code, but it should __probably__ be zero for
706 // syscall emulation code. (The secondary context is used by Solaris
707 // to allow kernel privilege code to access user space code:
708 // [ISBN 0-13-022496-0]:PG199.)
709 int primary_context
= bits(tlbdata
, 47, 32);
711 // "Hyper-Privileged Mode" is in use. There are three main modes of
712 // operation for Sparc: Hyper-Privileged Mode, Privileged Mode, and
714 int hpriv
= bits(tlbdata
, 0);
716 // Reset, Error and Debug state is in use. Something horrible has
717 // happened or the system is operating in Reset Mode.
718 int red
= bits(tlbdata
, 1);
720 // Inside a VM, a real address is the address that guest OS would
721 // interpret to be a physical address. To map to the physical address,
722 // it still needs to undergo a translation. The instruction
723 // translation code in the SPARC ITLB code assumes that the context is
724 // zero (kernel-level) if real addressing is being used.
725 int is_real_address
= !bits(tlbdata
, 5);
727 // Grab the address space identifier register from the thread context.
728 // XXX: Inspecting how setMiscReg and setMiscRegNoEffect behave for
729 // MISCREG_ASI causes me to think that the ASI register implementation
730 // might be bugged. The NoEffect variant changes the ASI register
731 // value in the architectural state while the normal variant changes
732 // the context field in the thread context's currently decoded request
733 // but does not directly affect the ASI register value in the
734 // architectural state. The ASI values and the context field in the
735 // request packet seem to have completely different uses.
736 MiscReg reg_asi
= tc
->readMiscRegNoEffect(MISCREG_ASI
);
737 ASI asi
= static_cast<ASI
>(reg_asi
);
739 // The SPARC DTLB code assumes that traps are executed in context
740 // zero if the asi value is ASI_IMPLICIT (which is 0x0). There's also
741 // an assumption that the nucleus address space is being used, but
742 // the context is the relevant issue since we need to pass it to TLB.
743 bool trapped
= bits(tlbdata
, 18, 16) > 0;
745 // Given the assumptions in the translateData code in the SPARC DTLB,
746 // the logic works out to the following for the context.
747 int context_id
= ((!hpriv
&& !red
&& is_real_address
) ||
749 (trapped
&& asi
== ASI_IMPLICIT
))
750 ? 0 : primary_context
;
752 // The partition id distinguishes between virtualized environments.
753 int const partition_id
= 0;
755 // Insert the TLB entry.
756 // The entry specifying whether the address is "real" is set to
757 // false for syscall emulation mode regardless of whether the
758 // address is real in preceding code. Not sure sure that this is
759 // correct, but also not sure if it matters at all.
760 tc
->getDTBPtr()->insert(alignedvaddr
, partition_id
, context_id
,
766 SpillNNormal::invoke(ThreadContext
*tc
, const StaticInstPtr
&inst
)
769 SparcFaultBase::invoke(tc
, inst
);
773 doNormalFault(tc
, trapType(), false);
775 Process
*p
= tc
->getProcessPtr();
777 SparcProcess
*sp
= dynamic_cast<SparcProcess
*>(p
);
780 // Then adjust the PC and NPC
781 tc
->pcState(sp
->readSpillStart());
785 FillNNormal::invoke(ThreadContext
*tc
, const StaticInstPtr
&inst
)
788 SparcFaultBase::invoke(tc
, inst
);
792 doNormalFault(tc
, trapType(), false);
794 Process
*p
= tc
->getProcessPtr();
796 SparcProcess
*sp
= dynamic_cast<SparcProcess
*>(p
);
799 // Then adjust the PC and NPC
800 tc
->pcState(sp
->readFillStart());
804 TrapInstruction::invoke(ThreadContext
*tc
, const StaticInstPtr
&inst
)
807 SparcFaultBase::invoke(tc
, inst
);
811 // In SE, this mechanism is how the process requests a service from
812 // the operating system. We'll get the process object from the thread
813 // context and let it service the request.
815 Process
*p
= tc
->getProcessPtr();
817 SparcProcess
*sp
= dynamic_cast<SparcProcess
*>(p
);
821 sp
->handleTrap(_n
, tc
, &fault
);
823 // We need to explicitly advance the pc, since that's not done for us
824 // on a faulting instruction
825 PCState pc
= tc
->pcState();
830 } // namespace SparcISA