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 "base/bitfield.hh"
37 #include "base/trace.hh"
38 #include "config/full_system.hh"
39 #include "cpu/base.hh"
40 #include "cpu/thread_context.hh"
42 #include "arch/sparc/process.hh"
43 #include "mem/page_table.hh"
44 #include "sim/process.hh"
52 FaultName
InternalProcessorError::_name
= "intprocerr";
53 TrapType
InternalProcessorError::_trapType
= 0x029;
54 FaultPriority
InternalProcessorError::_priority
= 4;
55 FaultStat
InternalProcessorError::_count
;
57 FaultName
MemAddressNotAligned::_name
= "unalign";
58 TrapType
MemAddressNotAligned::_trapType
= 0x034;
59 FaultPriority
MemAddressNotAligned::_priority
= 10;
60 FaultStat
MemAddressNotAligned::_count
;
62 FaultName
PowerOnReset::_name
= "pow_reset";
63 TrapType
PowerOnReset::_trapType
= 0x001;
64 FaultPriority
PowerOnReset::_priority
= 0;
65 FaultStat
PowerOnReset::_count
;
67 FaultName
WatchDogReset::_name
= "watch_dog_reset";
68 TrapType
WatchDogReset::_trapType
= 0x002;
69 FaultPriority
WatchDogReset::_priority
= 1;
70 FaultStat
WatchDogReset::_count
;
72 FaultName
ExternallyInitiatedReset::_name
= "extern_reset";
73 TrapType
ExternallyInitiatedReset::_trapType
= 0x003;
74 FaultPriority
ExternallyInitiatedReset::_priority
= 1;
75 FaultStat
ExternallyInitiatedReset::_count
;
77 FaultName
SoftwareInitiatedReset::_name
= "software_reset";
78 TrapType
SoftwareInitiatedReset::_trapType
= 0x004;
79 FaultPriority
SoftwareInitiatedReset::_priority
= 1;
80 FaultStat
SoftwareInitiatedReset::_count
;
82 FaultName
REDStateException::_name
= "red_counte";
83 TrapType
REDStateException::_trapType
= 0x005;
84 FaultPriority
REDStateException::_priority
= 1;
85 FaultStat
REDStateException::_count
;
87 FaultName
InstructionAccessException::_name
= "inst_access";
88 TrapType
InstructionAccessException::_trapType
= 0x008;
89 FaultPriority
InstructionAccessException::_priority
= 5;
90 FaultStat
InstructionAccessException::_count
;
92 FaultName
InstructionAccessMMUMiss::_name
= "inst_mmu";
93 TrapType
InstructionAccessMMUMiss::_trapType
= 0x009;
94 FaultPriority
InstructionAccessMMUMiss::_priority
= 2;
95 FaultStat
InstructionAccessMMUMiss::_count
;
97 FaultName
InstructionAccessError::_name
= "inst_error";
98 TrapType
InstructionAccessError::_trapType
= 0x00A;
99 FaultPriority
InstructionAccessError::_priority
= 3;
100 FaultStat
InstructionAccessError::_count
;
102 FaultName
IllegalInstruction::_name
= "illegal_inst";
103 TrapType
IllegalInstruction::_trapType
= 0x010;
104 FaultPriority
IllegalInstruction::_priority
= 7;
105 FaultStat
IllegalInstruction::_count
;
107 FaultName
PrivilegedOpcode::_name
= "priv_opcode";
108 TrapType
PrivilegedOpcode::_trapType
= 0x011;
109 FaultPriority
PrivilegedOpcode::_priority
= 6;
110 FaultStat
PrivilegedOpcode::_count
;
112 FaultName
UnimplementedLDD::_name
= "unimp_ldd";
113 TrapType
UnimplementedLDD::_trapType
= 0x012;
114 FaultPriority
UnimplementedLDD::_priority
= 6;
115 FaultStat
UnimplementedLDD::_count
;
117 FaultName
UnimplementedSTD::_name
= "unimp_std";
118 TrapType
UnimplementedSTD::_trapType
= 0x013;
119 FaultPriority
UnimplementedSTD::_priority
= 6;
120 FaultStat
UnimplementedSTD::_count
;
122 FaultName
FpDisabled::_name
= "fp_disabled";
123 TrapType
FpDisabled::_trapType
= 0x020;
124 FaultPriority
FpDisabled::_priority
= 8;
125 FaultStat
FpDisabled::_count
;
127 FaultName
FpExceptionIEEE754::_name
= "fp_754";
128 TrapType
FpExceptionIEEE754::_trapType
= 0x021;
129 FaultPriority
FpExceptionIEEE754::_priority
= 11;
130 FaultStat
FpExceptionIEEE754::_count
;
132 FaultName
FpExceptionOther::_name
= "fp_other";
133 TrapType
FpExceptionOther::_trapType
= 0x022;
134 FaultPriority
FpExceptionOther::_priority
= 11;
135 FaultStat
FpExceptionOther::_count
;
137 FaultName
TagOverflow::_name
= "tag_overflow";
138 TrapType
TagOverflow::_trapType
= 0x023;
139 FaultPriority
TagOverflow::_priority
= 14;
140 FaultStat
TagOverflow::_count
;
142 FaultName
DivisionByZero::_name
= "div_by_zero";
143 TrapType
DivisionByZero::_trapType
= 0x028;
144 FaultPriority
DivisionByZero::_priority
= 15;
145 FaultStat
DivisionByZero::_count
;
147 FaultName
DataAccessException::_name
= "data_access";
148 TrapType
DataAccessException::_trapType
= 0x030;
149 FaultPriority
DataAccessException::_priority
= 12;
150 FaultStat
DataAccessException::_count
;
152 FaultName
DataAccessMMUMiss::_name
= "data_mmu";
153 TrapType
DataAccessMMUMiss::_trapType
= 0x031;
154 FaultPriority
DataAccessMMUMiss::_priority
= 12;
155 FaultStat
DataAccessMMUMiss::_count
;
157 FaultName
DataAccessError::_name
= "data_error";
158 TrapType
DataAccessError::_trapType
= 0x032;
159 FaultPriority
DataAccessError::_priority
= 12;
160 FaultStat
DataAccessError::_count
;
162 FaultName
DataAccessProtection::_name
= "data_protection";
163 TrapType
DataAccessProtection::_trapType
= 0x033;
164 FaultPriority
DataAccessProtection::_priority
= 12;
165 FaultStat
DataAccessProtection::_count
;
167 FaultName
LDDFMemAddressNotAligned::_name
= "unalign_lddf";
168 TrapType
LDDFMemAddressNotAligned::_trapType
= 0x035;
169 FaultPriority
LDDFMemAddressNotAligned::_priority
= 10;
170 FaultStat
LDDFMemAddressNotAligned::_count
;
172 FaultName
STDFMemAddressNotAligned::_name
= "unalign_stdf";
173 TrapType
STDFMemAddressNotAligned::_trapType
= 0x036;
174 FaultPriority
STDFMemAddressNotAligned::_priority
= 10;
175 FaultStat
STDFMemAddressNotAligned::_count
;
177 FaultName
PrivilegedAction::_name
= "priv_action";
178 TrapType
PrivilegedAction::_trapType
= 0x037;
179 FaultPriority
PrivilegedAction::_priority
= 11;
180 FaultStat
PrivilegedAction::_count
;
182 FaultName
LDQFMemAddressNotAligned::_name
= "unalign_ldqf";
183 TrapType
LDQFMemAddressNotAligned::_trapType
= 0x038;
184 FaultPriority
LDQFMemAddressNotAligned::_priority
= 10;
185 FaultStat
LDQFMemAddressNotAligned::_count
;
187 FaultName
STQFMemAddressNotAligned::_name
= "unalign_stqf";
188 TrapType
STQFMemAddressNotAligned::_trapType
= 0x039;
189 FaultPriority
STQFMemAddressNotAligned::_priority
= 10;
190 FaultStat
STQFMemAddressNotAligned::_count
;
192 FaultName
AsyncDataError::_name
= "async_data";
193 TrapType
AsyncDataError::_trapType
= 0x040;
194 FaultPriority
AsyncDataError::_priority
= 2;
195 FaultStat
AsyncDataError::_count
;
197 FaultName
CleanWindow::_name
= "clean_win";
198 TrapType
CleanWindow::_trapType
= 0x024;
199 FaultPriority
CleanWindow::_priority
= 10;
200 FaultStat
CleanWindow::_count
;
202 //The enumerated faults
204 FaultName
InterruptLevelN::_name
= "interrupt_n";
205 TrapType
InterruptLevelN::_baseTrapType
= 0x041;
206 FaultStat
InterruptLevelN::_count
;
208 FaultName
SpillNNormal::_name
= "spill_n_normal";
209 TrapType
SpillNNormal::_baseTrapType
= 0x080;
210 FaultPriority
SpillNNormal::_priority
= 9;
211 FaultStat
SpillNNormal::_count
;
213 FaultName
SpillNOther::_name
= "spill_n_other";
214 TrapType
SpillNOther::_baseTrapType
= 0x0A0;
215 FaultPriority
SpillNOther::_priority
= 9;
216 FaultStat
SpillNOther::_count
;
218 FaultName
FillNNormal::_name
= "fill_n_normal";
219 TrapType
FillNNormal::_baseTrapType
= 0x0C0;
220 FaultPriority
FillNNormal::_priority
= 9;
221 FaultStat
FillNNormal::_count
;
223 FaultName
FillNOther::_name
= "fill_n_other";
224 TrapType
FillNOther::_baseTrapType
= 0x0E0;
225 FaultPriority
FillNOther::_priority
= 9;
226 FaultStat
FillNOther::_count
;
228 FaultName
TrapInstruction::_name
= "trap_inst_n";
229 TrapType
TrapInstruction::_baseTrapType
= 0x100;
230 FaultPriority
TrapInstruction::_priority
= 16;
231 FaultStat
TrapInstruction::_count
;
234 FaultName
PageTableFault::_name
= "page_table_fault";
235 TrapType
PageTableFault::_trapType
= 0x0000;
236 FaultPriority
PageTableFault::_priority
= 0;
237 FaultStat
PageTableFault::_count
;
241 * This sets everything up for a normal trap except for actually jumping to
242 * the handler. It will need to be expanded to include the state machine in
243 * the manual. Right now it assumes that traps will always be to the
247 void doNormalFault(ThreadContext
*tc
, TrapType tt
)
249 uint64_t TL
= tc
->readMiscReg(MISCREG_TL
);
250 uint64_t TSTATE
= tc
->readMiscReg(MISCREG_TSTATE
);
251 uint64_t PSTATE
= tc
->readMiscReg(MISCREG_PSTATE
);
252 uint64_t HPSTATE
= tc
->readMiscReg(MISCREG_HPSTATE
);
253 uint64_t CCR
= tc
->readMiscReg(MISCREG_CCR
);
254 uint64_t ASI
= tc
->readMiscReg(MISCREG_ASI
);
255 uint64_t CWP
= tc
->readMiscReg(MISCREG_CWP
);
256 uint64_t CANSAVE
= tc
->readMiscReg(MISCREG_CANSAVE
);
257 uint64_t GL
= tc
->readMiscReg(MISCREG_GL
);
258 uint64_t PC
= tc
->readPC();
259 uint64_t NPC
= tc
->readNextPC();
261 //Increment the trap level
263 tc
->setMiscReg(MISCREG_TL
, TL
);
267 //set TSTATE.gl to gl
268 replaceBits(TSTATE
, 42, 40, GL
);
269 //set TSTATE.ccr to ccr
270 replaceBits(TSTATE
, 39, 32, CCR
);
271 //set TSTATE.asi to asi
272 replaceBits(TSTATE
, 31, 24, ASI
);
273 //set TSTATE.pstate to pstate
274 replaceBits(TSTATE
, 20, 8, PSTATE
);
275 //set TSTATE.cwp to cwp
276 replaceBits(TSTATE
, 4, 0, CWP
);
279 tc
->setMiscReg(MISCREG_TSTATE
, TSTATE
);
282 tc
->setMiscReg(MISCREG_TPC
, PC
);
284 tc
->setMiscReg(MISCREG_TNPC
, NPC
);
286 //set HTSTATE.hpstate to hpstate
287 tc
->setMiscReg(MISCREG_HTSTATE
, HPSTATE
);
290 tc
->setMiscReg(MISCREG_TT
, tt
);
292 //Update the global register level
293 if(1/*We're delivering the trap in priveleged mode*/)
294 tc
->setMiscReg(MISCREG_GL
, max
<int>(GL
+1, MaxGL
));
296 tc
->setMiscReg(MISCREG_GL
, max
<int>(GL
+1, MaxPGL
));
298 //PSTATE.mm is unchanged
299 //PSTATE.pef = whether or not an fpu is present
300 //XXX We'll say there's one present, even though there aren't
301 //implementations for a decent number of the instructions
305 if(1/*We're delivering the trap in priveleged mode*/)
309 //PSTATE.cle = PSTATE.tle
310 replaceBits(PSTATE
, 9, 9, PSTATE
>> 8);
321 //PSTATE.tle is unchanged
323 //XXX Where exactly is this field?
324 tc
->setMiscReg(MISCREG_PSTATE
, PSTATE
);
326 if(0/*We're delivering the trap in hyperprivileged mode*/)
329 HPSTATE
&= ~(1 << 5);
333 HPSTATE
&= ~(1 << 10);
334 //HPSTATE.tlz is unchanged
335 tc
->setMiscReg(MISCREG_HPSTATE
, HPSTATE
);
338 bool changedCWP
= true;
341 else if(0x80 <= tt
&& tt
<= 0xbf)
342 CWP
+= (CANSAVE
+ 2);
343 else if(0xc0 <= tt
&& tt
<= 0xff)
350 CWP
= (CWP
+ NWindows
) % NWindows
;
351 tc
->setMiscRegWithEffect(MISCREG_CWP
, CWP
);
357 void SparcFault::invoke(ThreadContext
* tc
)
359 FaultBase::invoke(tc
);
362 //Use the SPARC trap state machine
365 void PowerOnReset::invoke(ThreadContext
* tc
)
367 //For SPARC, when a system is first started, there is a power
368 //on reset Trap which sets the processor into the following state.
369 //Bits that aren't set aren't defined on startup.
374 tickFields.counter = 0; //The TICK register is unreadable bya
375 tickFields.npt = 1; //The TICK register is unreadable by by !priv
377 softint = 0; // Clear all the soft interrupt bits
378 tick_cmprFields.int_dis = 1; // disable timer compare interrupts
379 tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
380 stickFields.npt = 1; //The TICK register is unreadable by by !priv
381 stick_cmprFields.int_dis = 1; // disable timer compare interrupts
382 stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
385 pstate = 0; // fields 0 but pef
386 pstateFields.pef = 1;
389 hpstateFields.red = 1;
390 hpstateFields.hpriv = 1;
391 hpstateFields.tlz = 0; // this is a guess
392 hintp = 0; // no interrupts pending
393 hstick_cmprFields.int_dis = 1; // disable timer compare interrupts
394 hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
402 void SpillNNormal::invoke(ThreadContext
*tc
)
404 doNormalFault(tc
, trapType());
406 Process
*p
= tc
->getProcessPtr();
408 //This will only work in faults from a SparcLiveProcess
409 SparcLiveProcess
*lp
= dynamic_cast<SparcLiveProcess
*>(p
);
412 //Then adjust the PC and NPC
413 Addr spillStart
= lp
->readSpillStart();
414 tc
->setPC(spillStart
);
415 tc
->setNextPC(spillStart
+ sizeof(MachInst
));
416 tc
->setNextNPC(spillStart
+ 2*sizeof(MachInst
));
419 void FillNNormal::invoke(ThreadContext
*tc
)
421 doNormalFault(tc
, trapType());
423 Process
* p
= tc
->getProcessPtr();
425 //This will only work in faults from a SparcLiveProcess
426 SparcLiveProcess
*lp
= dynamic_cast<SparcLiveProcess
*>(p
);
429 //The adjust the PC and NPC
430 Addr fillStart
= lp
->readFillStart();
431 tc
->setPC(fillStart
);
432 tc
->setNextPC(fillStart
+ sizeof(MachInst
));
433 tc
->setNextNPC(fillStart
+ 2*sizeof(MachInst
));
436 void PageTableFault::invoke(ThreadContext
*tc
)
438 Process
*p
= tc
->getProcessPtr();
440 // address is higher than the stack region or in the current stack region
441 if (vaddr
> p
->stack_base
|| vaddr
> p
->stack_min
)
442 FaultBase::invoke(tc
);
444 // We've accessed the next page
445 if (vaddr
> p
->stack_min
- PageBytes
) {
446 p
->stack_min
-= PageBytes
;
447 if (p
->stack_base
- p
->stack_min
> 8*1024*1024)
448 fatal("Over max stack size for one thread\n");
449 p
->pTable
->allocate(p
->stack_min
, PageBytes
);
450 warn("Increasing stack size by one page.");
452 FaultBase::invoke(tc
);
458 } // namespace SparcISA