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/tlb.hh"
39 #include "arch/sparc/types.hh"
40 #include "base/bitfield.hh"
41 #include "base/trace.hh"
42 #include "cpu/base.hh"
43 #include "cpu/thread_context.hh"
44 #include "mem/page_table.hh"
45 #include "sim/full_system.hh"
46 #include "sim/process.hh"
53 template<> SparcFaultBase::FaultVals
54 SparcFault
<PowerOnReset
>::vals
55 ("power_on_reset", 0x001, 0, {{H
, H
, H
}});
57 template<> SparcFaultBase::FaultVals
58 SparcFault
<WatchDogReset
>::vals
59 ("watch_dog_reset", 0x002, 120, {{H
, H
, H
}});
61 template<> SparcFaultBase::FaultVals
62 SparcFault
<ExternallyInitiatedReset
>::vals
63 ("externally_initiated_reset", 0x003, 110, {{H
, H
, H
}});
65 template<> SparcFaultBase::FaultVals
66 SparcFault
<SoftwareInitiatedReset
>::vals
67 ("software_initiated_reset", 0x004, 130, {{SH
, SH
, H
}});
69 template<> SparcFaultBase::FaultVals
70 SparcFault
<REDStateException
>::vals
71 ("RED_state_exception", 0x005, 1, {{H
, H
, H
}});
73 template<> SparcFaultBase::FaultVals
74 SparcFault
<StoreError
>::vals
75 ("store_error", 0x007, 201, {{H
, H
, H
}});
77 template<> SparcFaultBase::FaultVals
78 SparcFault
<InstructionAccessException
>::vals
79 ("instruction_access_exception", 0x008, 300, {{H
, H
, H
}});
81 //XXX This trap is apparently dropped from ua2005
82 /*template<> SparcFaultBase::FaultVals
83 SparcFault<InstructionAccessMMUMiss>::vals
84 ("inst_mmu", 0x009, 2, {{H, H, H}});*/
86 template<> SparcFaultBase::FaultVals
87 SparcFault
<InstructionAccessError
>::vals
88 ("instruction_access_error", 0x00A, 400, {{H
, H
, H
}});
90 template<> SparcFaultBase::FaultVals
91 SparcFault
<IllegalInstruction
>::vals
92 ("illegal_instruction", 0x010, 620, {{H
, H
, H
}});
94 template<> SparcFaultBase::FaultVals
95 SparcFault
<PrivilegedOpcode
>::vals
96 ("privileged_opcode", 0x011, 700, {{P
, SH
, SH
}});
98 //XXX This trap is apparently dropped from ua2005
99 /*template<> SparcFaultBase::FaultVals
100 SparcFault<UnimplementedLDD>::vals
101 ("unimp_ldd", 0x012, 6, {{H, H, H}});*/
103 //XXX This trap is apparently dropped from ua2005
104 /*template<> SparcFaultBase::FaultVals
105 SparcFault<UnimplementedSTD>::vals
106 ("unimp_std", 0x013, 6, {{H, H, H}});*/
108 template<> SparcFaultBase::FaultVals
109 SparcFault
<FpDisabled
>::vals
110 ("fp_disabled", 0x020, 800, {{P
, P
, H
}});
112 /* SPARCv8 and SPARCv9 define just fp_disabled trap. SIMD is not contemplated
113 * as a separate part. Therefore, we use the same code and TT */
114 template<> SparcFaultBase::FaultVals
115 SparcFault
<VecDisabled
>::vals
116 ("fp_disabled", 0x020, 800, {{P
, P
, H
}});
118 template<> SparcFaultBase::FaultVals
119 SparcFault
<FpExceptionIEEE754
>::vals
120 ("fp_exception_ieee_754", 0x021, 1110, {{P
, P
, H
}});
122 template<> SparcFaultBase::FaultVals
123 SparcFault
<FpExceptionOther
>::vals
124 ("fp_exception_other", 0x022, 1110, {{P
, P
, H
}});
126 template<> SparcFaultBase::FaultVals
127 SparcFault
<TagOverflow
>::vals
128 ("tag_overflow", 0x023, 1400, {{P
, P
, H
}});
130 template<> SparcFaultBase::FaultVals
131 SparcFault
<CleanWindow
>::vals
132 ("clean_window", 0x024, 1010, {{P
, P
, H
}});
134 template<> SparcFaultBase::FaultVals
135 SparcFault
<DivisionByZero
>::vals
136 ("division_by_zero", 0x028, 1500, {{P
, P
, H
}});
138 template<> SparcFaultBase::FaultVals
139 SparcFault
<InternalProcessorError
>::vals
140 ("internal_processor_error", 0x029, 4, {{H
, H
, H
}});
142 template<> SparcFaultBase::FaultVals
143 SparcFault
<InstructionInvalidTSBEntry
>::vals
144 ("instruction_invalid_tsb_entry", 0x02A, 210, {{H
, H
, SH
}});
146 template<> SparcFaultBase::FaultVals
147 SparcFault
<DataInvalidTSBEntry
>::vals
148 ("data_invalid_tsb_entry", 0x02B, 1203, {{H
, H
, H
}});
150 template<> SparcFaultBase::FaultVals
151 SparcFault
<DataAccessException
>::vals
152 ("data_access_exception", 0x030, 1201, {{H
, H
, H
}});
154 //XXX This trap is apparently dropped from ua2005
155 /*template<> SparcFaultBase::FaultVals
156 SparcFault<DataAccessMMUMiss>::vals
157 ("data_mmu", 0x031, 12, {{H, H, H}});*/
159 template<> SparcFaultBase::FaultVals
160 SparcFault
<DataAccessError
>::vals
161 ("data_access_error", 0x032, 1210, {{H
, H
, H
}});
163 template<> SparcFaultBase::FaultVals
164 SparcFault
<DataAccessProtection
>::vals
165 ("data_access_protection", 0x033, 1207, {{H
, H
, H
}});
167 template<> SparcFaultBase::FaultVals
168 SparcFault
<MemAddressNotAligned
>::vals
169 ("mem_address_not_aligned", 0x034, 1020, {{H
, H
, H
}});
171 template<> SparcFaultBase::FaultVals
172 SparcFault
<LDDFMemAddressNotAligned
>::vals
173 ("LDDF_mem_address_not_aligned", 0x035, 1010, {{H
, H
, H
}});
175 template<> SparcFaultBase::FaultVals
176 SparcFault
<STDFMemAddressNotAligned
>::vals
177 ("STDF_mem_address_not_aligned", 0x036, 1010, {{H
, H
, H
}});
179 template<> SparcFaultBase::FaultVals
180 SparcFault
<PrivilegedAction
>::vals
181 ("privileged_action", 0x037, 1110, {{H
, H
, SH
}});
183 template<> SparcFaultBase::FaultVals
184 SparcFault
<LDQFMemAddressNotAligned
>::vals
185 ("LDQF_mem_address_not_aligned", 0x038, 1010, {{H
, H
, H
}});
187 template<> SparcFaultBase::FaultVals
188 SparcFault
<STQFMemAddressNotAligned
>::vals
189 ("STQF_mem_address_not_aligned", 0x039, 1010, {{H
, H
, H
}});
191 template<> SparcFaultBase::FaultVals
192 SparcFault
<InstructionRealTranslationMiss
>::vals
193 ("instruction_real_translation_miss", 0x03E, 208, {{H
, H
, SH
}});
195 template<> SparcFaultBase::FaultVals
196 SparcFault
<DataRealTranslationMiss
>::vals
197 ("data_real_translation_miss", 0x03F, 1203, {{H
, H
, H
}});
199 //XXX This trap is apparently dropped from ua2005
200 /*template<> SparcFaultBase::FaultVals
201 SparcFault<AsyncDataError>::vals
202 ("async_data", 0x040, 2, {{H, H, H}});*/
204 template<> SparcFaultBase::FaultVals
205 SparcFault
<InterruptLevelN
>::vals
206 ("interrupt_level_n", 0x040, 0, {{P
, P
, SH
}});
208 template<> SparcFaultBase::FaultVals
209 SparcFault
<HstickMatch
>::vals
210 ("hstick_match", 0x05E, 1601, {{H
, H
, H
}});
212 template<> SparcFaultBase::FaultVals
213 SparcFault
<TrapLevelZero
>::vals
214 ("trap_level_zero", 0x05F, 202, {{H
, H
, SH
}});
216 template<> SparcFaultBase::FaultVals
217 SparcFault
<InterruptVector
>::vals
218 ("interrupt_vector", 0x060, 2630, {{H
, H
, H
}});
220 template<> SparcFaultBase::FaultVals
221 SparcFault
<PAWatchpoint
>::vals
222 ("PA_watchpoint", 0x061, 1209, {{H
, H
, H
}});
224 template<> SparcFaultBase::FaultVals
225 SparcFault
<VAWatchpoint
>::vals
226 ("VA_watchpoint", 0x062, 1120, {{P
, P
, SH
}});
228 template<> SparcFaultBase::FaultVals
229 SparcFault
<FastInstructionAccessMMUMiss
>::vals
230 ("fast_instruction_access_MMU_miss", 0x064, 208, {{H
, H
, SH
}});
232 template<> SparcFaultBase::FaultVals
233 SparcFault
<FastDataAccessMMUMiss
>::vals
234 ("fast_data_access_MMU_miss", 0x068, 1203, {{H
, H
, H
}});
236 template<> SparcFaultBase::FaultVals
237 SparcFault
<FastDataAccessProtection
>::vals
238 ("fast_data_access_protection", 0x06C, 1207, {{H
, H
, H
}});
240 template<> SparcFaultBase::FaultVals
241 SparcFault
<InstructionBreakpoint
>::vals
242 ("instruction_break", 0x076, 610, {{H
, H
, H
}});
244 template<> SparcFaultBase::FaultVals
245 SparcFault
<CpuMondo
>::vals
246 ("cpu_mondo", 0x07C, 1608, {{P
, P
, SH
}});
248 template<> SparcFaultBase::FaultVals
249 SparcFault
<DevMondo
>::vals
250 ("dev_mondo", 0x07D, 1611, {{P
, P
, SH
}});
252 template<> SparcFaultBase::FaultVals
253 SparcFault
<ResumableError
>::vals
254 ("resume_error", 0x07E, 3330, {{P
, P
, SH
}});
256 template<> SparcFaultBase::FaultVals
257 SparcFault
<SpillNNormal
>::vals
258 ("spill_n_normal", 0x080, 900, {{P
, P
, H
}});
260 template<> SparcFaultBase::FaultVals
261 SparcFault
<SpillNOther
>::vals
262 ("spill_n_other", 0x0A0, 900, {{P
, P
, H
}});
264 template<> SparcFaultBase::FaultVals
265 SparcFault
<FillNNormal
>::vals
266 ("fill_n_normal", 0x0C0, 900, {{P
, P
, H
}});
268 template<> SparcFaultBase::FaultVals
269 SparcFault
<FillNOther
>::vals
270 ("fill_n_other", 0x0E0, 900, {{P
, P
, H
}});
272 template<> SparcFaultBase::FaultVals
273 SparcFault
<TrapInstruction
>::vals
274 ("trap_instruction", 0x100, 1602, {{P
, P
, H
}});
277 * This causes the thread context to enter RED state. This causes the side
278 * effects which go with entering RED state because of a trap.
282 enterREDState(ThreadContext
*tc
)
284 //@todo Disable the mmu?
285 //@todo Disable watchpoints?
286 HPSTATE hpstate
= tc
->readMiscRegNoEffect(MISCREG_HPSTATE
);
289 tc
->setMiscReg(MISCREG_HPSTATE
, hpstate
);
290 // PSTATE.priv is set to 1 here. The manual says it should be 0, but
291 // Legion sets it to 1.
292 PSTATE pstate
= tc
->readMiscRegNoEffect(MISCREG_PSTATE
);
294 tc
->setMiscReg(MISCREG_PSTATE
, pstate
);
298 * This sets everything up for a RED state trap except for actually jumping to
303 doREDFault(ThreadContext
*tc
, TrapType tt
)
305 RegVal TL
= tc
->readMiscRegNoEffect(MISCREG_TL
);
306 RegVal TSTATE
= tc
->readMiscRegNoEffect(MISCREG_TSTATE
);
307 PSTATE pstate
= tc
->readMiscRegNoEffect(MISCREG_PSTATE
);
308 HPSTATE hpstate
= tc
->readMiscRegNoEffect(MISCREG_HPSTATE
);
309 RegVal CCR
= tc
->readIntReg(NumIntArchRegs
+ 2);
310 RegVal ASI
= tc
->readMiscRegNoEffect(MISCREG_ASI
);
311 RegVal CWP
= tc
->readMiscRegNoEffect(MISCREG_CWP
);
312 RegVal CANSAVE
= tc
->readMiscRegNoEffect(NumIntArchRegs
+ 3);
313 RegVal GL
= tc
->readMiscRegNoEffect(MISCREG_GL
);
314 PCState pc
= tc
->pcState();
318 Addr pcMask
= pstate
.am
? mask(32) : mask(64);
320 // set TSTATE.gl to gl
321 replaceBits(TSTATE
, 42, 40, GL
);
322 // set TSTATE.ccr to ccr
323 replaceBits(TSTATE
, 39, 32, CCR
);
324 // set TSTATE.asi to asi
325 replaceBits(TSTATE
, 31, 24, ASI
);
326 // set TSTATE.pstate to pstate
327 replaceBits(TSTATE
, 20, 8, pstate
);
328 // set TSTATE.cwp to cwp
329 replaceBits(TSTATE
, 4, 0, CWP
);
332 tc
->setMiscRegNoEffect(MISCREG_TSTATE
, TSTATE
);
335 tc
->setMiscRegNoEffect(MISCREG_TPC
, pc
.pc() & pcMask
);
337 tc
->setMiscRegNoEffect(MISCREG_TNPC
, pc
.npc() & pcMask
);
339 // set HTSTATE.hpstate to hpstate
340 tc
->setMiscRegNoEffect(MISCREG_HTSTATE
, hpstate
);
343 tc
->setMiscRegNoEffect(MISCREG_TT
, tt
);
346 tc
->setMiscReg(MISCREG_GL
, min
<int>(GL
+1, MaxGL
));
348 bool priv
= pstate
.priv
; // just save the priv bit
352 tc
->setMiscRegNoEffect(MISCREG_PSTATE
, pstate
);
358 tc
->setMiscRegNoEffect(MISCREG_HPSTATE
, hpstate
);
360 bool changedCWP
= true;
363 else if (0x80 <= tt
&& tt
<= 0xbf)
364 CWP
+= (CANSAVE
+ 2);
365 else if (0xc0 <= tt
&& tt
<= 0xff)
371 CWP
= (CWP
+ NWindows
) % NWindows
;
372 tc
->setMiscReg(MISCREG_CWP
, CWP
);
377 * This sets everything up for a normal trap except for actually jumping to
382 doNormalFault(ThreadContext
*tc
, TrapType tt
, bool gotoHpriv
)
384 RegVal TL
= tc
->readMiscRegNoEffect(MISCREG_TL
);
385 RegVal TSTATE
= tc
->readMiscRegNoEffect(MISCREG_TSTATE
);
386 PSTATE pstate
= tc
->readMiscRegNoEffect(MISCREG_PSTATE
);
387 HPSTATE hpstate
= tc
->readMiscRegNoEffect(MISCREG_HPSTATE
);
388 RegVal CCR
= tc
->readIntReg(NumIntArchRegs
+ 2);
389 RegVal ASI
= tc
->readMiscRegNoEffect(MISCREG_ASI
);
390 RegVal CWP
= tc
->readMiscRegNoEffect(MISCREG_CWP
);
391 RegVal CANSAVE
= tc
->readIntReg(NumIntArchRegs
+ 3);
392 RegVal GL
= tc
->readMiscRegNoEffect(MISCREG_GL
);
393 PCState pc
= tc
->pcState();
395 // Increment the trap level
397 tc
->setMiscRegNoEffect(MISCREG_TL
, TL
);
399 Addr pcMask
= pstate
.am
? mask(32) : mask(64);
403 // set TSTATE.gl to gl
404 replaceBits(TSTATE
, 42, 40, GL
);
405 // set TSTATE.ccr to ccr
406 replaceBits(TSTATE
, 39, 32, CCR
);
407 // set TSTATE.asi to asi
408 replaceBits(TSTATE
, 31, 24, ASI
);
409 // set TSTATE.pstate to pstate
410 replaceBits(TSTATE
, 20, 8, pstate
);
411 // set TSTATE.cwp to cwp
412 replaceBits(TSTATE
, 4, 0, CWP
);
415 tc
->setMiscRegNoEffect(MISCREG_TSTATE
, TSTATE
);
418 tc
->setMiscRegNoEffect(MISCREG_TPC
, pc
.pc() & pcMask
);
420 tc
->setMiscRegNoEffect(MISCREG_TNPC
, pc
.npc() & pcMask
);
422 // set HTSTATE.hpstate to hpstate
423 tc
->setMiscRegNoEffect(MISCREG_HTSTATE
, hpstate
);
426 tc
->setMiscRegNoEffect(MISCREG_TT
, tt
);
428 // Update the global register level
430 tc
->setMiscReg(MISCREG_GL
, min
<int>(GL
+ 1, MaxPGL
));
432 tc
->setMiscReg(MISCREG_GL
, min
<int>(GL
+ 1, MaxGL
));
434 // pstate.mm is unchanged
435 pstate
.pef
= 1; // PSTATE.pef = whether or not an fpu is present
438 // pstate.tle is unchanged
443 // The manual says PSTATE.priv should be 0, but Legion leaves it alone
447 // hpstate.tlz is unchanged
448 tc
->setMiscRegNoEffect(MISCREG_HPSTATE
, hpstate
);
449 } else { // we are going to priv
451 pstate
.cle
= pstate
.tle
;
453 tc
->setMiscRegNoEffect(MISCREG_PSTATE
, pstate
);
456 bool changedCWP
= true;
459 else if (0x80 <= tt
&& tt
<= 0xbf)
460 CWP
+= (CANSAVE
+ 2);
461 else if (0xc0 <= tt
&& tt
<= 0xff)
467 CWP
= (CWP
+ NWindows
) % NWindows
;
468 tc
->setMiscReg(MISCREG_CWP
, CWP
);
473 getREDVector(RegVal TT
, Addr
&PC
, Addr
&NPC
)
475 //XXX The following constant might belong in a header file.
476 const Addr RSTVAddr
= 0xFFF0000000ULL
;
477 PC
= RSTVAddr
| ((TT
<< 5) & 0xFF);
478 NPC
= PC
+ sizeof(MachInst
);
482 getHyperVector(ThreadContext
* tc
, Addr
&PC
, Addr
&NPC
, RegVal TT
)
484 Addr HTBA
= tc
->readMiscRegNoEffect(MISCREG_HTBA
);
485 PC
= (HTBA
& ~mask(14)) | ((TT
<< 5) & mask(14));
486 NPC
= PC
+ sizeof(MachInst
);
490 getPrivVector(ThreadContext
*tc
, Addr
&PC
, Addr
&NPC
, RegVal TT
, RegVal TL
)
492 Addr TBA
= tc
->readMiscRegNoEffect(MISCREG_TBA
);
493 PC
= (TBA
& ~mask(15)) |
494 (TL
> 1 ? (1 << 14) : 0) |
495 ((TT
<< 5) & mask(14));
496 NPC
= PC
+ sizeof(MachInst
);
500 SparcFaultBase::invoke(ThreadContext
* tc
, const StaticInstPtr
&inst
)
502 FaultBase::invoke(tc
);
508 // We can refer to this to see what the trap level -was-, but something
509 // in the middle could change it in the regfile out from under us.
510 RegVal tl
= tc
->readMiscRegNoEffect(MISCREG_TL
);
511 RegVal tt
= tc
->readMiscRegNoEffect(MISCREG_TT
);
512 PSTATE pstate
= tc
->readMiscRegNoEffect(MISCREG_PSTATE
);
513 HPSTATE hpstate
= tc
->readMiscRegNoEffect(MISCREG_HPSTATE
);
517 PrivilegeLevel current
;
519 current
= Hyperprivileged
;
520 else if (pstate
.priv
)
521 current
= Privileged
;
525 PrivilegeLevel level
= getNextLevel(current
);
527 if (hpstate
.red
|| (tl
== MaxTL
- 1)) {
528 getREDVector(5, PC
, NPC
);
530 // This changes the hpstate and pstate, so we need to make sure we
531 // save the old version on the trap stack in doREDFault.
533 } else if (tl
== MaxTL
) {
534 panic("Should go to error state here.. crap\n");
535 // Do error_state somehow?
536 // Probably inject a WDR fault using the interrupt mechanism.
537 // What should the PC and NPC be set to?
538 } else if (tl
> MaxPTL
&& level
== Privileged
) {
539 // guest_watchdog fault
540 doNormalFault(tc
, trapType(), true);
541 getHyperVector(tc
, PC
, NPC
, 2);
542 } else if (level
== Hyperprivileged
||
543 (level
== Privileged
&& trapType() >= 384)) {
544 doNormalFault(tc
, trapType(), true);
545 getHyperVector(tc
, PC
, NPC
, trapType());
547 doNormalFault(tc
, trapType(), false);
548 getPrivVector(tc
, PC
, NPC
, trapType(), tl
+ 1);
554 pc
.nnpc(NPC
+ sizeof(MachInst
));
561 PowerOnReset::invoke(ThreadContext
*tc
, const StaticInstPtr
&inst
)
563 // For SPARC, when a system is first started, there is a power
564 // on reset Trap which sets the processor into the following state.
565 // Bits that aren't set aren't defined on startup.
567 tc
->setMiscRegNoEffect(MISCREG_TL
, MaxTL
);
568 tc
->setMiscRegNoEffect(MISCREG_TT
, trapType());
569 tc
->setMiscReg(MISCREG_GL
, MaxGL
);
574 tc
->setMiscRegNoEffect(MISCREG_PSTATE
, pstate
);
576 // Turn on red and hpriv, set everything else to 0
577 HPSTATE hpstate
= tc
->readMiscRegNoEffect(MISCREG_HPSTATE
);
582 tc
->setMiscRegNoEffect(MISCREG_HPSTATE
, hpstate
);
584 // The tick register is unreadable by nonprivileged software
585 tc
->setMiscRegNoEffect(MISCREG_TICK
, 1ULL << 63);
587 // Enter RED state. We do this last so that the actual state preserved in
588 // the trap stack is the state from before this fault.
592 getREDVector(trapType(), PC
, NPC
);
597 pc
.nnpc(NPC
+ sizeof(MachInst
));
602 // These registers are specified as "undefined" after a POR, and they
603 // should have reasonable values after the miscregfile is reset
605 // Clear all the soft interrupt bits
607 // disable timer compare interrupts, reset tick_cmpr
608 tc->setMiscRegNoEffect(MISCREG_
609 tick_cmprFields.int_dis = 1;
610 tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
611 stickFields.npt = 1; // The TICK register is unreadable by by !priv
612 stick_cmprFields.int_dis = 1; // disable timer compare interrupts
613 stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
617 hintp = 0; // no interrupts pending
618 hstick_cmprFields.int_dis = 1; // disable timer compare interrupts
619 hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
624 FastInstructionAccessMMUMiss::invoke(ThreadContext
*tc
,
625 const StaticInstPtr
&inst
)
628 SparcFaultBase::invoke(tc
, inst
);
632 Process
*p
= tc
->getProcessPtr();
633 const EmulationPageTable::Entry
*pte
= p
->pTable
->lookup(vaddr
);
634 panic_if(!pte
, "Tried to execute unmapped address %#x.\n", vaddr
);
636 Addr alignedvaddr
= p
->pTable
->pageAlign(vaddr
);
638 // Grab fields used during instruction translation to figure out
639 // which context to use.
640 uint64_t tlbdata
= tc
->readMiscRegNoEffect(MISCREG_TLB_DATA
);
642 // Inside a VM, a real address is the address that guest OS would
643 // interpret to be a physical address. To map to the physical address,
644 // it still needs to undergo a translation. The instruction
645 // translation code in the SPARC ITLB code assumes that the context is
646 // zero (kernel-level) if real addressing is being used.
647 bool is_real_address
= !bits(tlbdata
, 4);
649 // The SPARC ITLB code assumes that traps are executed in context
650 // zero so we carry that assumption through here.
651 bool trapped
= bits(tlbdata
, 18, 16) > 0;
653 // The primary context acts as a PASID. It allows the MMU to
654 // distinguish between virtual addresses that would alias to the
655 // same physical address (if two or more processes shared the same
656 // virtual address mapping).
657 int primary_context
= bits(tlbdata
, 47, 32);
659 // The partition id distinguishes between virtualized environments.
660 int const partition_id
= 0;
662 // Given the assumptions in the translateInst code in the SPARC ITLB,
663 // the logic works out to the following for the context.
664 int context_id
= (is_real_address
|| trapped
) ? 0 : primary_context
;
666 TlbEntry
entry(p
->pTable
->pid(), alignedvaddr
, pte
->paddr
,
667 pte
->flags
& EmulationPageTable::Uncacheable
,
668 pte
->flags
& EmulationPageTable::ReadOnly
);
670 // Insert the TLB entry.
671 // The entry specifying whether the address is "real" is set to
672 // false for syscall emulation mode regardless of whether the
673 // address is real in preceding code. Not sure sure that this is
674 // correct, but also not sure if it matters at all.
675 dynamic_cast<TLB
*>(tc
->getITBPtr())->
676 insert(alignedvaddr
, partition_id
, context_id
, false, entry
.pte
);
680 FastDataAccessMMUMiss::invoke(ThreadContext
*tc
, const StaticInstPtr
&inst
)
683 SparcFaultBase::invoke(tc
, inst
);
687 Process
*p
= tc
->getProcessPtr();
688 const EmulationPageTable::Entry
*pte
= p
->pTable
->lookup(vaddr
);
689 if (!pte
&& p
->fixupStackFault(vaddr
))
690 pte
= p
->pTable
->lookup(vaddr
);
691 panic_if(!pte
, "Tried to access unmapped address %#x.\n", vaddr
);
693 Addr alignedvaddr
= p
->pTable
->pageAlign(vaddr
);
695 // Grab fields used during data translation to figure out
696 // which context to use.
697 uint64_t tlbdata
= tc
->readMiscRegNoEffect(MISCREG_TLB_DATA
);
699 // The primary context acts as a PASID. It allows the MMU to
700 // distinguish between virtual addresses that would alias to the
701 // same physical address (if two or more processes shared the same
702 // virtual address mapping). There's a secondary context used in the
703 // DTLB translation code, but it should __probably__ be zero for
704 // syscall emulation code. (The secondary context is used by Solaris
705 // to allow kernel privilege code to access user space code:
706 // [ISBN 0-13-022496-0]:PG199.)
707 int primary_context
= bits(tlbdata
, 47, 32);
709 // "Hyper-Privileged Mode" is in use. There are three main modes of
710 // operation for Sparc: Hyper-Privileged Mode, Privileged Mode, and
712 int hpriv
= bits(tlbdata
, 0);
714 // Reset, Error and Debug state is in use. Something horrible has
715 // happened or the system is operating in Reset Mode.
716 int red
= bits(tlbdata
, 1);
718 // Inside a VM, a real address is the address that guest OS would
719 // interpret to be a physical address. To map to the physical address,
720 // it still needs to undergo a translation. The instruction
721 // translation code in the SPARC ITLB code assumes that the context is
722 // zero (kernel-level) if real addressing is being used.
723 int is_real_address
= !bits(tlbdata
, 5);
725 // Grab the address space identifier register from the thread context.
726 // XXX: Inspecting how setMiscReg and setMiscRegNoEffect behave for
727 // MISCREG_ASI causes me to think that the ASI register implementation
728 // might be bugged. The NoEffect variant changes the ASI register
729 // value in the architectural state while the normal variant changes
730 // the context field in the thread context's currently decoded request
731 // but does not directly affect the ASI register value in the
732 // architectural state. The ASI values and the context field in the
733 // request packet seem to have completely different uses.
734 RegVal reg_asi
= tc
->readMiscRegNoEffect(MISCREG_ASI
);
735 ASI asi
= static_cast<ASI
>(reg_asi
);
737 // The SPARC DTLB code assumes that traps are executed in context
738 // zero if the asi value is ASI_IMPLICIT (which is 0x0). There's also
739 // an assumption that the nucleus address space is being used, but
740 // the context is the relevant issue since we need to pass it to TLB.
741 bool trapped
= bits(tlbdata
, 18, 16) > 0;
743 // Given the assumptions in the translateData code in the SPARC DTLB,
744 // the logic works out to the following for the context.
745 int context_id
= ((!hpriv
&& !red
&& is_real_address
) ||
747 (trapped
&& asi
== ASI_IMPLICIT
))
748 ? 0 : primary_context
;
750 // The partition id distinguishes between virtualized environments.
751 int const partition_id
= 0;
753 TlbEntry
entry(p
->pTable
->pid(), alignedvaddr
, pte
->paddr
,
754 pte
->flags
& EmulationPageTable::Uncacheable
,
755 pte
->flags
& EmulationPageTable::ReadOnly
);
757 // Insert the TLB entry.
758 // The entry specifying whether the address is "real" is set to
759 // false for syscall emulation mode regardless of whether the
760 // address is real in preceding code. Not sure sure that this is
761 // correct, but also not sure if it matters at all.
762 dynamic_cast<TLB
*>(tc
->getDTBPtr())->
763 insert(alignedvaddr
, partition_id
, context_id
, false, entry
.pte
);
767 SpillNNormal::invoke(ThreadContext
*tc
, const StaticInstPtr
&inst
)
770 SparcFaultBase::invoke(tc
, inst
);
774 doNormalFault(tc
, trapType(), false);
776 Process
*p
= tc
->getProcessPtr();
778 SparcProcess
*sp
= dynamic_cast<SparcProcess
*>(p
);
781 // Then adjust the PC and NPC
782 tc
->pcState(sp
->readSpillStart());
786 FillNNormal::invoke(ThreadContext
*tc
, const StaticInstPtr
&inst
)
789 SparcFaultBase::invoke(tc
, inst
);
793 doNormalFault(tc
, trapType(), false);
795 Process
*p
= tc
->getProcessPtr();
797 SparcProcess
*sp
= dynamic_cast<SparcProcess
*>(p
);
800 // Then adjust the PC and NPC
801 tc
->pcState(sp
->readFillStart());
805 TrapInstruction::invoke(ThreadContext
*tc
, const StaticInstPtr
&inst
)
808 SparcFaultBase::invoke(tc
, inst
);
812 // In SE, this mechanism is how the process requests a service from
813 // the operating system. We'll get the process object from the thread
814 // context and let it service the request.
816 Process
*p
= tc
->getProcessPtr();
818 SparcProcess
*sp
= dynamic_cast<SparcProcess
*>(p
);
822 sp
->handleTrap(_n
, tc
, &fault
);
824 // We need to explicitly advance the pc, since that's not done for us
825 // on a faulting instruction
826 PCState pc
= tc
->pcState();
831 } // namespace SparcISA