Got rid of some debug output
[gem5.git] / src / arch / sparc / faults.cc
1 /*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
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.
15 *
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.
27 *
28 * Authors: Gabe Black
29 * Kevin Lim
30 */
31
32 #include <algorithm>
33
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"
41 #if !FULL_SYSTEM
42 #include "mem/page_table.hh"
43 #include "sim/process.hh"
44 #endif
45
46 using namespace std;
47
48 namespace SparcISA
49 {
50
51 FaultName InternalProcessorError::_name = "intprocerr";
52 TrapType InternalProcessorError::_trapType = 0x029;
53 FaultPriority InternalProcessorError::_priority = 4;
54 FaultStat InternalProcessorError::_count;
55
56 FaultName MemAddressNotAligned::_name = "unalign";
57 TrapType MemAddressNotAligned::_trapType = 0x034;
58 FaultPriority MemAddressNotAligned::_priority = 10;
59 FaultStat MemAddressNotAligned::_count;
60
61 FaultName PowerOnReset::_name = "pow_reset";
62 TrapType PowerOnReset::_trapType = 0x001;
63 FaultPriority PowerOnReset::_priority = 0;
64 FaultStat PowerOnReset::_count;
65
66 FaultName WatchDogReset::_name = "watch_dog_reset";
67 TrapType WatchDogReset::_trapType = 0x002;
68 FaultPriority WatchDogReset::_priority = 1;
69 FaultStat WatchDogReset::_count;
70
71 FaultName ExternallyInitiatedReset::_name = "extern_reset";
72 TrapType ExternallyInitiatedReset::_trapType = 0x003;
73 FaultPriority ExternallyInitiatedReset::_priority = 1;
74 FaultStat ExternallyInitiatedReset::_count;
75
76 FaultName SoftwareInitiatedReset::_name = "software_reset";
77 TrapType SoftwareInitiatedReset::_trapType = 0x004;
78 FaultPriority SoftwareInitiatedReset::_priority = 1;
79 FaultStat SoftwareInitiatedReset::_count;
80
81 FaultName REDStateException::_name = "red_counte";
82 TrapType REDStateException::_trapType = 0x005;
83 FaultPriority REDStateException::_priority = 1;
84 FaultStat REDStateException::_count;
85
86 FaultName InstructionAccessException::_name = "inst_access";
87 TrapType InstructionAccessException::_trapType = 0x008;
88 FaultPriority InstructionAccessException::_priority = 5;
89 FaultStat InstructionAccessException::_count;
90
91 FaultName InstructionAccessMMUMiss::_name = "inst_mmu";
92 TrapType InstructionAccessMMUMiss::_trapType = 0x009;
93 FaultPriority InstructionAccessMMUMiss::_priority = 2;
94 FaultStat InstructionAccessMMUMiss::_count;
95
96 FaultName InstructionAccessError::_name = "inst_error";
97 TrapType InstructionAccessError::_trapType = 0x00A;
98 FaultPriority InstructionAccessError::_priority = 3;
99 FaultStat InstructionAccessError::_count;
100
101 FaultName IllegalInstruction::_name = "illegal_inst";
102 TrapType IllegalInstruction::_trapType = 0x010;
103 FaultPriority IllegalInstruction::_priority = 7;
104 FaultStat IllegalInstruction::_count;
105
106 FaultName PrivilegedOpcode::_name = "priv_opcode";
107 TrapType PrivilegedOpcode::_trapType = 0x011;
108 FaultPriority PrivilegedOpcode::_priority = 6;
109 FaultStat PrivilegedOpcode::_count;
110
111 FaultName UnimplementedLDD::_name = "unimp_ldd";
112 TrapType UnimplementedLDD::_trapType = 0x012;
113 FaultPriority UnimplementedLDD::_priority = 6;
114 FaultStat UnimplementedLDD::_count;
115
116 FaultName UnimplementedSTD::_name = "unimp_std";
117 TrapType UnimplementedSTD::_trapType = 0x013;
118 FaultPriority UnimplementedSTD::_priority = 6;
119 FaultStat UnimplementedSTD::_count;
120
121 FaultName FpDisabled::_name = "fp_disabled";
122 TrapType FpDisabled::_trapType = 0x020;
123 FaultPriority FpDisabled::_priority = 8;
124 FaultStat FpDisabled::_count;
125
126 FaultName FpExceptionIEEE754::_name = "fp_754";
127 TrapType FpExceptionIEEE754::_trapType = 0x021;
128 FaultPriority FpExceptionIEEE754::_priority = 11;
129 FaultStat FpExceptionIEEE754::_count;
130
131 FaultName FpExceptionOther::_name = "fp_other";
132 TrapType FpExceptionOther::_trapType = 0x022;
133 FaultPriority FpExceptionOther::_priority = 11;
134 FaultStat FpExceptionOther::_count;
135
136 FaultName TagOverflow::_name = "tag_overflow";
137 TrapType TagOverflow::_trapType = 0x023;
138 FaultPriority TagOverflow::_priority = 14;
139 FaultStat TagOverflow::_count;
140
141 FaultName DivisionByZero::_name = "div_by_zero";
142 TrapType DivisionByZero::_trapType = 0x028;
143 FaultPriority DivisionByZero::_priority = 15;
144 FaultStat DivisionByZero::_count;
145
146 FaultName DataAccessException::_name = "data_access";
147 TrapType DataAccessException::_trapType = 0x030;
148 FaultPriority DataAccessException::_priority = 12;
149 FaultStat DataAccessException::_count;
150
151 FaultName DataAccessMMUMiss::_name = "data_mmu";
152 TrapType DataAccessMMUMiss::_trapType = 0x031;
153 FaultPriority DataAccessMMUMiss::_priority = 12;
154 FaultStat DataAccessMMUMiss::_count;
155
156 FaultName DataAccessError::_name = "data_error";
157 TrapType DataAccessError::_trapType = 0x032;
158 FaultPriority DataAccessError::_priority = 12;
159 FaultStat DataAccessError::_count;
160
161 FaultName DataAccessProtection::_name = "data_protection";
162 TrapType DataAccessProtection::_trapType = 0x033;
163 FaultPriority DataAccessProtection::_priority = 12;
164 FaultStat DataAccessProtection::_count;
165
166 FaultName LDDFMemAddressNotAligned::_name = "unalign_lddf";
167 TrapType LDDFMemAddressNotAligned::_trapType = 0x035;
168 FaultPriority LDDFMemAddressNotAligned::_priority = 10;
169 FaultStat LDDFMemAddressNotAligned::_count;
170
171 FaultName STDFMemAddressNotAligned::_name = "unalign_stdf";
172 TrapType STDFMemAddressNotAligned::_trapType = 0x036;
173 FaultPriority STDFMemAddressNotAligned::_priority = 10;
174 FaultStat STDFMemAddressNotAligned::_count;
175
176 FaultName PrivilegedAction::_name = "priv_action";
177 TrapType PrivilegedAction::_trapType = 0x037;
178 FaultPriority PrivilegedAction::_priority = 11;
179 FaultStat PrivilegedAction::_count;
180
181 FaultName LDQFMemAddressNotAligned::_name = "unalign_ldqf";
182 TrapType LDQFMemAddressNotAligned::_trapType = 0x038;
183 FaultPriority LDQFMemAddressNotAligned::_priority = 10;
184 FaultStat LDQFMemAddressNotAligned::_count;
185
186 FaultName STQFMemAddressNotAligned::_name = "unalign_stqf";
187 TrapType STQFMemAddressNotAligned::_trapType = 0x039;
188 FaultPriority STQFMemAddressNotAligned::_priority = 10;
189 FaultStat STQFMemAddressNotAligned::_count;
190
191 FaultName AsyncDataError::_name = "async_data";
192 TrapType AsyncDataError::_trapType = 0x040;
193 FaultPriority AsyncDataError::_priority = 2;
194 FaultStat AsyncDataError::_count;
195
196 FaultName CleanWindow::_name = "clean_win";
197 TrapType CleanWindow::_trapType = 0x024;
198 FaultPriority CleanWindow::_priority = 10;
199 FaultStat CleanWindow::_count;
200
201 //The enumerated faults
202
203 FaultName InterruptLevelN::_name = "interrupt_n";
204 TrapType InterruptLevelN::_baseTrapType = 0x041;
205 FaultStat InterruptLevelN::_count;
206
207 FaultName SpillNNormal::_name = "spill_n_normal";
208 TrapType SpillNNormal::_baseTrapType = 0x080;
209 FaultPriority SpillNNormal::_priority = 9;
210 FaultStat SpillNNormal::_count;
211
212 FaultName SpillNOther::_name = "spill_n_other";
213 TrapType SpillNOther::_baseTrapType = 0x0A0;
214 FaultPriority SpillNOther::_priority = 9;
215 FaultStat SpillNOther::_count;
216
217 FaultName FillNNormal::_name = "fill_n_normal";
218 TrapType FillNNormal::_baseTrapType = 0x0C0;
219 FaultPriority FillNNormal::_priority = 9;
220 FaultStat FillNNormal::_count;
221
222 FaultName FillNOther::_name = "fill_n_other";
223 TrapType FillNOther::_baseTrapType = 0x0E0;
224 FaultPriority FillNOther::_priority = 9;
225 FaultStat FillNOther::_count;
226
227 FaultName TrapInstruction::_name = "trap_inst_n";
228 TrapType TrapInstruction::_baseTrapType = 0x100;
229 FaultPriority TrapInstruction::_priority = 16;
230 FaultStat TrapInstruction::_count;
231
232 #if !FULL_SYSTEM
233 FaultName PageTableFault::_name = "page_table_fault";
234 TrapType PageTableFault::_trapType = 0x0000;
235 FaultPriority PageTableFault::_priority = 0;
236 FaultStat PageTableFault::_count;
237 #endif
238
239 /**
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
243 * privileged level.
244 */
245
246 void doNormalFault(ThreadContext *tc, TrapType tt)
247 {
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();
259
260 //Increment the trap level
261 TL++;
262 tc->setMiscReg(MISCREG_TL, TL);
263
264 //Save off state
265
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);
276
277 //Write back TSTATE
278 tc->setMiscReg(MISCREG_TSTATE, TSTATE);
279
280 //set TPC to PC
281 tc->setMiscReg(MISCREG_TPC, PC);
282 //set TNPC to NPC
283 tc->setMiscReg(MISCREG_TNPC, NPC);
284
285 //set HTSTATE.hpstate to hpstate
286 tc->setMiscReg(MISCREG_HTSTATE, HPSTATE);
287
288 //TT = trap type;
289 tc->setMiscReg(MISCREG_TT, tt);
290
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));
294 else
295 tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxPGL));
296
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
301 PSTATE |= (1 << 4);
302 //PSTATE.am = 0
303 PSTATE &= ~(1 << 3);
304 if(1/*We're delivering the trap in priveleged mode*/)
305 {
306 //PSTATE.priv = 1
307 PSTATE |= (1 << 2);
308 //PSTATE.cle = PSTATE.tle
309 replaceBits(PSTATE, 9, 9, PSTATE >> 8);
310 }
311 else
312 {
313 //PSTATE.priv = 0
314 PSTATE &= ~(1 << 2);
315 //PSTATE.cle = 0
316 PSTATE &= ~(1 << 9);
317 }
318 //PSTATE.ie = 0
319 PSTATE &= ~(1 << 1);
320 //PSTATE.tle is unchanged
321 //PSTATE.tct = 0
322 //XXX Where exactly is this field?
323 tc->setMiscReg(MISCREG_PSTATE, PSTATE);
324
325 if(0/*We're delivering the trap in hyperprivileged mode*/)
326 {
327 //HPSTATE.red = 0
328 HPSTATE &= ~(1 << 5);
329 //HPSTATE.hpriv = 1
330 HPSTATE |= (1 << 2);
331 //HPSTATE.ibe = 0
332 HPSTATE &= ~(1 << 10);
333 //HPSTATE.tlz is unchanged
334 tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
335 }
336
337 bool changedCWP = true;
338 if(tt == 0x24)
339 CWP++;
340 else if(0x80 <= tt && tt <= 0xbf)
341 CWP += (CANSAVE + 2);
342 else if(0xc0 <= tt && tt <= 0xff)
343 CWP--;
344 else
345 changedCWP = false;
346
347 if(changedCWP)
348 {
349 CWP = (CWP + NWindows) % NWindows;
350 tc->setMiscRegWithEffect(MISCREG_CWP, CWP);
351 }
352 }
353
354 #if FULL_SYSTEM
355
356 void SparcFault::invoke(ThreadContext * tc)
357 {
358 FaultBase::invoke(tc);
359 countStat()++;
360
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);
365
366 if (skipFaultingInstruction()) {
367 // traps... skip faulting instruction.
368 tc->setMiscReg(AlphaISA::IPR_EXC_ADDR,
369 tc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4);
370 }
371
372 if (!tc->inPalMode())
373 AlphaISA::swap_palshadow(&(tc->regs), true);
374
375 tc->regs.pc = tc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect();
376 tc->regs.npc = tc->regs.pc + sizeof(MachInst);*/
377 }
378
379 #endif
380
381 #if !FULL_SYSTEM
382
383 void TrapInstruction::invoke(ThreadContext * tc)
384 {
385 // Should be handled in ISA.
386 }
387
388 void SpillNNormal::invoke(ThreadContext *tc)
389 {
390 doNormalFault(tc, trapType());
391
392 Process *p = tc->getProcessPtr();
393
394 //This will only work in faults from a SparcLiveProcess
395 SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
396 assert(lp);
397
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));
403 }
404
405 void FillNNormal::invoke(ThreadContext *tc)
406 {
407 doNormalFault(tc, trapType());
408
409 Process * p = tc->getProcessPtr();
410
411 //This will only work in faults from a SparcLiveProcess
412 SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
413 assert(lp);
414
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));
420 }
421
422 void PageTableFault::invoke(ThreadContext *tc)
423 {
424 Process *p = tc->getProcessPtr();
425
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);
429
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.");
437 } else {
438 FaultBase::invoke(tc);
439 }
440 }
441
442 #endif
443
444 } // namespace SparcISA
445