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.
34 #include "arch/sparc/faults.hh"
35 #include "arch/sparc/isa_traits.hh"
36 #include "arch/sparc/process.hh"
37 #include "base/bitfield.hh"
38 #include "base/trace.hh"
39 #include "cpu/base.hh"
40 #include "cpu/thread_context.hh"
42 #include "mem/page_table.hh"
43 #include "sim/process.hh"
51 FaultName
InternalProcessorError::_name
= "intprocerr";
52 TrapType
InternalProcessorError::_trapType
= 0x029;
53 FaultPriority
InternalProcessorError::_priority
= 4;
54 FaultStat
InternalProcessorError::_count
;
56 FaultName
MemAddressNotAligned::_name
= "unalign";
57 TrapType
MemAddressNotAligned::_trapType
= 0x034;
58 FaultPriority
MemAddressNotAligned::_priority
= 10;
59 FaultStat
MemAddressNotAligned::_count
;
61 FaultName
PowerOnReset::_name
= "pow_reset";
62 TrapType
PowerOnReset::_trapType
= 0x001;
63 FaultPriority
PowerOnReset::_priority
= 0;
64 FaultStat
PowerOnReset::_count
;
66 FaultName
WatchDogReset::_name
= "watch_dog_reset";
67 TrapType
WatchDogReset::_trapType
= 0x002;
68 FaultPriority
WatchDogReset::_priority
= 1;
69 FaultStat
WatchDogReset::_count
;
71 FaultName
ExternallyInitiatedReset::_name
= "extern_reset";
72 TrapType
ExternallyInitiatedReset::_trapType
= 0x003;
73 FaultPriority
ExternallyInitiatedReset::_priority
= 1;
74 FaultStat
ExternallyInitiatedReset::_count
;
76 FaultName
SoftwareInitiatedReset::_name
= "software_reset";
77 TrapType
SoftwareInitiatedReset::_trapType
= 0x004;
78 FaultPriority
SoftwareInitiatedReset::_priority
= 1;
79 FaultStat
SoftwareInitiatedReset::_count
;
81 FaultName
REDStateException::_name
= "red_counte";
82 TrapType
REDStateException::_trapType
= 0x005;
83 FaultPriority
REDStateException::_priority
= 1;
84 FaultStat
REDStateException::_count
;
86 FaultName
InstructionAccessException::_name
= "inst_access";
87 TrapType
InstructionAccessException::_trapType
= 0x008;
88 FaultPriority
InstructionAccessException::_priority
= 5;
89 FaultStat
InstructionAccessException::_count
;
91 FaultName
InstructionAccessMMUMiss::_name
= "inst_mmu";
92 TrapType
InstructionAccessMMUMiss::_trapType
= 0x009;
93 FaultPriority
InstructionAccessMMUMiss::_priority
= 2;
94 FaultStat
InstructionAccessMMUMiss::_count
;
96 FaultName
InstructionAccessError::_name
= "inst_error";
97 TrapType
InstructionAccessError::_trapType
= 0x00A;
98 FaultPriority
InstructionAccessError::_priority
= 3;
99 FaultStat
InstructionAccessError::_count
;
101 FaultName
IllegalInstruction::_name
= "illegal_inst";
102 TrapType
IllegalInstruction::_trapType
= 0x010;
103 FaultPriority
IllegalInstruction::_priority
= 7;
104 FaultStat
IllegalInstruction::_count
;
106 FaultName
PrivilegedOpcode::_name
= "priv_opcode";
107 TrapType
PrivilegedOpcode::_trapType
= 0x011;
108 FaultPriority
PrivilegedOpcode::_priority
= 6;
109 FaultStat
PrivilegedOpcode::_count
;
111 FaultName
UnimplementedLDD::_name
= "unimp_ldd";
112 TrapType
UnimplementedLDD::_trapType
= 0x012;
113 FaultPriority
UnimplementedLDD::_priority
= 6;
114 FaultStat
UnimplementedLDD::_count
;
116 FaultName
UnimplementedSTD::_name
= "unimp_std";
117 TrapType
UnimplementedSTD::_trapType
= 0x013;
118 FaultPriority
UnimplementedSTD::_priority
= 6;
119 FaultStat
UnimplementedSTD::_count
;
121 FaultName
FpDisabled::_name
= "fp_disabled";
122 TrapType
FpDisabled::_trapType
= 0x020;
123 FaultPriority
FpDisabled::_priority
= 8;
124 FaultStat
FpDisabled::_count
;
126 FaultName
FpExceptionIEEE754::_name
= "fp_754";
127 TrapType
FpExceptionIEEE754::_trapType
= 0x021;
128 FaultPriority
FpExceptionIEEE754::_priority
= 11;
129 FaultStat
FpExceptionIEEE754::_count
;
131 FaultName
FpExceptionOther::_name
= "fp_other";
132 TrapType
FpExceptionOther::_trapType
= 0x022;
133 FaultPriority
FpExceptionOther::_priority
= 11;
134 FaultStat
FpExceptionOther::_count
;
136 FaultName
TagOverflow::_name
= "tag_overflow";
137 TrapType
TagOverflow::_trapType
= 0x023;
138 FaultPriority
TagOverflow::_priority
= 14;
139 FaultStat
TagOverflow::_count
;
141 FaultName
DivisionByZero::_name
= "div_by_zero";
142 TrapType
DivisionByZero::_trapType
= 0x028;
143 FaultPriority
DivisionByZero::_priority
= 15;
144 FaultStat
DivisionByZero::_count
;
146 FaultName
DataAccessException::_name
= "data_access";
147 TrapType
DataAccessException::_trapType
= 0x030;
148 FaultPriority
DataAccessException::_priority
= 12;
149 FaultStat
DataAccessException::_count
;
151 FaultName
DataAccessMMUMiss::_name
= "data_mmu";
152 TrapType
DataAccessMMUMiss::_trapType
= 0x031;
153 FaultPriority
DataAccessMMUMiss::_priority
= 12;
154 FaultStat
DataAccessMMUMiss::_count
;
156 FaultName
DataAccessError::_name
= "data_error";
157 TrapType
DataAccessError::_trapType
= 0x032;
158 FaultPriority
DataAccessError::_priority
= 12;
159 FaultStat
DataAccessError::_count
;
161 FaultName
DataAccessProtection::_name
= "data_protection";
162 TrapType
DataAccessProtection::_trapType
= 0x033;
163 FaultPriority
DataAccessProtection::_priority
= 12;
164 FaultStat
DataAccessProtection::_count
;
166 FaultName
LDDFMemAddressNotAligned::_name
= "unalign_lddf";
167 TrapType
LDDFMemAddressNotAligned::_trapType
= 0x035;
168 FaultPriority
LDDFMemAddressNotAligned::_priority
= 10;
169 FaultStat
LDDFMemAddressNotAligned::_count
;
171 FaultName
STDFMemAddressNotAligned::_name
= "unalign_stdf";
172 TrapType
STDFMemAddressNotAligned::_trapType
= 0x036;
173 FaultPriority
STDFMemAddressNotAligned::_priority
= 10;
174 FaultStat
STDFMemAddressNotAligned::_count
;
176 FaultName
PrivilegedAction::_name
= "priv_action";
177 TrapType
PrivilegedAction::_trapType
= 0x037;
178 FaultPriority
PrivilegedAction::_priority
= 11;
179 FaultStat
PrivilegedAction::_count
;
181 FaultName
LDQFMemAddressNotAligned::_name
= "unalign_ldqf";
182 TrapType
LDQFMemAddressNotAligned::_trapType
= 0x038;
183 FaultPriority
LDQFMemAddressNotAligned::_priority
= 10;
184 FaultStat
LDQFMemAddressNotAligned::_count
;
186 FaultName
STQFMemAddressNotAligned::_name
= "unalign_stqf";
187 TrapType
STQFMemAddressNotAligned::_trapType
= 0x039;
188 FaultPriority
STQFMemAddressNotAligned::_priority
= 10;
189 FaultStat
STQFMemAddressNotAligned::_count
;
191 FaultName
AsyncDataError::_name
= "async_data";
192 TrapType
AsyncDataError::_trapType
= 0x040;
193 FaultPriority
AsyncDataError::_priority
= 2;
194 FaultStat
AsyncDataError::_count
;
196 FaultName
CleanWindow::_name
= "clean_win";
197 TrapType
CleanWindow::_trapType
= 0x024;
198 FaultPriority
CleanWindow::_priority
= 10;
199 FaultStat
CleanWindow::_count
;
201 //The enumerated faults
203 FaultName
InterruptLevelN::_name
= "interrupt_n";
204 TrapType
InterruptLevelN::_baseTrapType
= 0x041;
205 FaultStat
InterruptLevelN::_count
;
207 FaultName
SpillNNormal::_name
= "spill_n_normal";
208 TrapType
SpillNNormal::_baseTrapType
= 0x080;
209 FaultPriority
SpillNNormal::_priority
= 9;
210 FaultStat
SpillNNormal::_count
;
212 FaultName
SpillNOther::_name
= "spill_n_other";
213 TrapType
SpillNOther::_baseTrapType
= 0x0A0;
214 FaultPriority
SpillNOther::_priority
= 9;
215 FaultStat
SpillNOther::_count
;
217 FaultName
FillNNormal::_name
= "fill_n_normal";
218 TrapType
FillNNormal::_baseTrapType
= 0x0C0;
219 FaultPriority
FillNNormal::_priority
= 9;
220 FaultStat
FillNNormal::_count
;
222 FaultName
FillNOther::_name
= "fill_n_other";
223 TrapType
FillNOther::_baseTrapType
= 0x0E0;
224 FaultPriority
FillNOther::_priority
= 9;
225 FaultStat
FillNOther::_count
;
227 FaultName
TrapInstruction::_name
= "trap_inst_n";
228 TrapType
TrapInstruction::_baseTrapType
= 0x100;
229 FaultPriority
TrapInstruction::_priority
= 16;
230 FaultStat
TrapInstruction::_count
;
233 FaultName
PageTableFault::_name
= "page_table_fault";
234 TrapType
PageTableFault::_trapType
= 0x0000;
235 FaultPriority
PageTableFault::_priority
= 0;
236 FaultStat
PageTableFault::_count
;
240 * This sets everything up for a normal trap except for actually jumping to
241 * the handler. It will need to be expanded to include the state machine in
242 * the manual. Right now it assumes that traps will always be to the
246 void doNormalFault(ThreadContext
*tc
, TrapType tt
)
248 uint64_t TL
= tc
->readMiscReg(MISCREG_TL
);
249 uint64_t TSTATE
= tc
->readMiscReg(MISCREG_TSTATE
);
250 uint64_t PSTATE
= tc
->readMiscReg(MISCREG_PSTATE
);
251 uint64_t HPSTATE
= tc
->readMiscReg(MISCREG_HPSTATE
);
252 uint64_t CCR
= tc
->readMiscReg(MISCREG_CCR
);
253 uint64_t ASI
= tc
->readMiscReg(MISCREG_ASI
);
254 uint64_t CWP
= tc
->readMiscReg(MISCREG_CWP
);
255 uint64_t CANSAVE
= tc
->readMiscReg(MISCREG_CANSAVE
);
256 uint64_t GL
= tc
->readMiscReg(MISCREG_GL
);
257 uint64_t PC
= tc
->readPC();
258 uint64_t NPC
= tc
->readNextPC();
260 //Increment the trap level
262 tc
->setMiscReg(MISCREG_TL
, TL
);
266 //set TSTATE.gl to gl
267 replaceBits(TSTATE
, 42, 40, GL
);
268 //set TSTATE.ccr to ccr
269 replaceBits(TSTATE
, 39, 32, CCR
);
270 //set TSTATE.asi to asi
271 replaceBits(TSTATE
, 31, 24, ASI
);
272 //set TSTATE.pstate to pstate
273 replaceBits(TSTATE
, 20, 8, PSTATE
);
274 //set TSTATE.cwp to cwp
275 replaceBits(TSTATE
, 4, 0, CWP
);
278 tc
->setMiscReg(MISCREG_TSTATE
, TSTATE
);
281 tc
->setMiscReg(MISCREG_TPC
, PC
);
283 tc
->setMiscReg(MISCREG_TNPC
, NPC
);
285 //set HTSTATE.hpstate to hpstate
286 tc
->setMiscReg(MISCREG_HTSTATE
, HPSTATE
);
289 tc
->setMiscReg(MISCREG_TT
, tt
);
291 //Update the global register level
292 if(1/*We're delivering the trap in priveleged mode*/)
293 tc
->setMiscReg(MISCREG_GL
, max
<int>(GL
+1, MaxGL
));
295 tc
->setMiscReg(MISCREG_GL
, max
<int>(GL
+1, MaxPGL
));
297 //PSTATE.mm is unchanged
298 //PSTATE.pef = whether or not an fpu is present
299 //XXX We'll say there's one present, even though there aren't
300 //implementations for a decent number of the instructions
304 if(1/*We're delivering the trap in priveleged mode*/)
308 //PSTATE.cle = PSTATE.tle
309 replaceBits(PSTATE
, 9, 9, PSTATE
>> 8);
320 //PSTATE.tle is unchanged
322 //XXX Where exactly is this field?
323 tc
->setMiscReg(MISCREG_PSTATE
, PSTATE
);
325 if(0/*We're delivering the trap in hyperprivileged mode*/)
328 HPSTATE
&= ~(1 << 5);
332 HPSTATE
&= ~(1 << 10);
333 //HPSTATE.tlz is unchanged
334 tc
->setMiscReg(MISCREG_HPSTATE
, HPSTATE
);
337 bool changedCWP
= true;
340 else if(0x80 <= tt
&& tt
<= 0xbf)
341 CWP
+= (CANSAVE
+ 2);
342 else if(0xc0 <= tt
&& tt
<= 0xff)
349 CWP
= (CWP
+ NWindows
) % NWindows
;
350 tc
->setMiscRegWithEffect(MISCREG_CWP
, CWP
);
356 void SparcFault::invoke(ThreadContext
* tc
)
358 FaultBase::invoke(tc
);
361 //Use the SPARC trap state machine
362 /*// exception restart address
363 if (setRestartAddress() || !tc->inPalMode())
364 tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, tc->regs.pc);
366 if (skipFaultingInstruction()) {
367 // traps... skip faulting instruction.
368 tc->setMiscReg(AlphaISA::IPR_EXC_ADDR,
369 tc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4);
372 if (!tc->inPalMode())
373 AlphaISA::swap_palshadow(&(tc->regs), true);
375 tc->regs.pc = tc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect();
376 tc->regs.npc = tc->regs.pc + sizeof(MachInst);*/
383 void TrapInstruction::invoke(ThreadContext
* tc
)
385 // Should be handled in ISA.
388 void SpillNNormal::invoke(ThreadContext
*tc
)
390 doNormalFault(tc
, trapType());
392 Process
*p
= tc
->getProcessPtr();
394 //This will only work in faults from a SparcLiveProcess
395 SparcLiveProcess
*lp
= dynamic_cast<SparcLiveProcess
*>(p
);
398 //Then adjust the PC and NPC
399 Addr spillStart
= lp
->readSpillStart();
400 tc
->setPC(spillStart
);
401 tc
->setNextPC(spillStart
+ sizeof(MachInst
));
402 tc
->setNextNPC(spillStart
+ 2*sizeof(MachInst
));
405 void FillNNormal::invoke(ThreadContext
*tc
)
407 doNormalFault(tc
, trapType());
409 Process
* p
= tc
->getProcessPtr();
411 //This will only work in faults from a SparcLiveProcess
412 SparcLiveProcess
*lp
= dynamic_cast<SparcLiveProcess
*>(p
);
415 //The adjust the PC and NPC
416 Addr fillStart
= lp
->readFillStart();
417 tc
->setPC(fillStart
);
418 tc
->setNextPC(fillStart
+ sizeof(MachInst
));
419 tc
->setNextNPC(fillStart
+ 2*sizeof(MachInst
));
422 void PageTableFault::invoke(ThreadContext
*tc
)
424 Process
*p
= tc
->getProcessPtr();
426 // address is higher than the stack region or in the current stack region
427 if (vaddr
> p
->stack_base
|| vaddr
> p
->stack_min
)
428 FaultBase::invoke(tc
);
430 // We've accessed the next page
431 if (vaddr
> p
->stack_min
- PageBytes
) {
432 p
->stack_min
-= PageBytes
;
433 if (p
->stack_base
- p
->stack_min
> 8*1024*1024)
434 fatal("Over max stack size for one thread\n");
435 p
->pTable
->allocate(p
->stack_min
, PageBytes
);
436 warn("Increasing stack size by one page.");
438 FaultBase::invoke(tc
);
444 } // namespace SparcISA