faults.cc revision 3523
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 "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"
41#if !FULL_SYSTEM
42#include "arch/sparc/process.hh"
43#include "mem/page_table.hh"
44#include "sim/process.hh"
45#endif
46
47using namespace std;
48
49namespace SparcISA
50{
51
52FaultName     InternalProcessorError::_name = "intprocerr";
53TrapType      InternalProcessorError::_trapType = 0x029;
54FaultPriority InternalProcessorError::_priority = 4;
55FaultStat     InternalProcessorError::_count;
56
57FaultName     MemAddressNotAligned::_name = "unalign";
58TrapType      MemAddressNotAligned::_trapType = 0x034;
59FaultPriority MemAddressNotAligned::_priority = 10;
60FaultStat     MemAddressNotAligned::_count;
61
62FaultName     PowerOnReset::_name = "pow_reset";
63TrapType      PowerOnReset::_trapType = 0x001;
64FaultPriority PowerOnReset::_priority = 0;
65FaultStat     PowerOnReset::_count;
66
67FaultName     WatchDogReset::_name = "watch_dog_reset";
68TrapType      WatchDogReset::_trapType = 0x002;
69FaultPriority WatchDogReset::_priority = 1;
70FaultStat     WatchDogReset::_count;
71
72FaultName     ExternallyInitiatedReset::_name = "extern_reset";
73TrapType      ExternallyInitiatedReset::_trapType = 0x003;
74FaultPriority ExternallyInitiatedReset::_priority = 1;
75FaultStat     ExternallyInitiatedReset::_count;
76
77FaultName     SoftwareInitiatedReset::_name = "software_reset";
78TrapType      SoftwareInitiatedReset::_trapType = 0x004;
79FaultPriority SoftwareInitiatedReset::_priority = 1;
80FaultStat     SoftwareInitiatedReset::_count;
81
82FaultName     REDStateException::_name = "red_counte";
83TrapType      REDStateException::_trapType = 0x005;
84FaultPriority REDStateException::_priority = 1;
85FaultStat     REDStateException::_count;
86
87FaultName     InstructionAccessException::_name = "inst_access";
88TrapType      InstructionAccessException::_trapType = 0x008;
89FaultPriority InstructionAccessException::_priority = 5;
90FaultStat     InstructionAccessException::_count;
91
92FaultName     InstructionAccessMMUMiss::_name = "inst_mmu";
93TrapType      InstructionAccessMMUMiss::_trapType = 0x009;
94FaultPriority InstructionAccessMMUMiss::_priority = 2;
95FaultStat     InstructionAccessMMUMiss::_count;
96
97FaultName     InstructionAccessError::_name = "inst_error";
98TrapType      InstructionAccessError::_trapType = 0x00A;
99FaultPriority InstructionAccessError::_priority = 3;
100FaultStat     InstructionAccessError::_count;
101
102FaultName     IllegalInstruction::_name = "illegal_inst";
103TrapType      IllegalInstruction::_trapType = 0x010;
104FaultPriority IllegalInstruction::_priority = 7;
105FaultStat     IllegalInstruction::_count;
106
107FaultName     PrivilegedOpcode::_name = "priv_opcode";
108TrapType      PrivilegedOpcode::_trapType = 0x011;
109FaultPriority PrivilegedOpcode::_priority = 6;
110FaultStat     PrivilegedOpcode::_count;
111
112FaultName     UnimplementedLDD::_name = "unimp_ldd";
113TrapType      UnimplementedLDD::_trapType = 0x012;
114FaultPriority UnimplementedLDD::_priority = 6;
115FaultStat     UnimplementedLDD::_count;
116
117FaultName     UnimplementedSTD::_name = "unimp_std";
118TrapType      UnimplementedSTD::_trapType = 0x013;
119FaultPriority UnimplementedSTD::_priority = 6;
120FaultStat     UnimplementedSTD::_count;
121
122FaultName     FpDisabled::_name = "fp_disabled";
123TrapType      FpDisabled::_trapType = 0x020;
124FaultPriority FpDisabled::_priority = 8;
125FaultStat     FpDisabled::_count;
126
127FaultName     FpExceptionIEEE754::_name = "fp_754";
128TrapType      FpExceptionIEEE754::_trapType = 0x021;
129FaultPriority FpExceptionIEEE754::_priority = 11;
130FaultStat     FpExceptionIEEE754::_count;
131
132FaultName     FpExceptionOther::_name = "fp_other";
133TrapType      FpExceptionOther::_trapType = 0x022;
134FaultPriority FpExceptionOther::_priority = 11;
135FaultStat     FpExceptionOther::_count;
136
137FaultName     TagOverflow::_name = "tag_overflow";
138TrapType      TagOverflow::_trapType = 0x023;
139FaultPriority TagOverflow::_priority = 14;
140FaultStat     TagOverflow::_count;
141
142FaultName     DivisionByZero::_name = "div_by_zero";
143TrapType      DivisionByZero::_trapType = 0x028;
144FaultPriority DivisionByZero::_priority = 15;
145FaultStat     DivisionByZero::_count;
146
147FaultName     DataAccessException::_name = "data_access";
148TrapType      DataAccessException::_trapType = 0x030;
149FaultPriority DataAccessException::_priority = 12;
150FaultStat     DataAccessException::_count;
151
152FaultName     DataAccessMMUMiss::_name = "data_mmu";
153TrapType      DataAccessMMUMiss::_trapType = 0x031;
154FaultPriority DataAccessMMUMiss::_priority = 12;
155FaultStat     DataAccessMMUMiss::_count;
156
157FaultName     DataAccessError::_name = "data_error";
158TrapType      DataAccessError::_trapType = 0x032;
159FaultPriority DataAccessError::_priority = 12;
160FaultStat     DataAccessError::_count;
161
162FaultName     DataAccessProtection::_name = "data_protection";
163TrapType      DataAccessProtection::_trapType = 0x033;
164FaultPriority DataAccessProtection::_priority = 12;
165FaultStat     DataAccessProtection::_count;
166
167FaultName     LDDFMemAddressNotAligned::_name = "unalign_lddf";
168TrapType      LDDFMemAddressNotAligned::_trapType = 0x035;
169FaultPriority LDDFMemAddressNotAligned::_priority = 10;
170FaultStat     LDDFMemAddressNotAligned::_count;
171
172FaultName     STDFMemAddressNotAligned::_name = "unalign_stdf";
173TrapType      STDFMemAddressNotAligned::_trapType = 0x036;
174FaultPriority STDFMemAddressNotAligned::_priority = 10;
175FaultStat     STDFMemAddressNotAligned::_count;
176
177FaultName     PrivilegedAction::_name = "priv_action";
178TrapType      PrivilegedAction::_trapType = 0x037;
179FaultPriority PrivilegedAction::_priority = 11;
180FaultStat     PrivilegedAction::_count;
181
182FaultName     LDQFMemAddressNotAligned::_name = "unalign_ldqf";
183TrapType      LDQFMemAddressNotAligned::_trapType = 0x038;
184FaultPriority LDQFMemAddressNotAligned::_priority = 10;
185FaultStat     LDQFMemAddressNotAligned::_count;
186
187FaultName     STQFMemAddressNotAligned::_name = "unalign_stqf";
188TrapType      STQFMemAddressNotAligned::_trapType = 0x039;
189FaultPriority STQFMemAddressNotAligned::_priority = 10;
190FaultStat     STQFMemAddressNotAligned::_count;
191
192FaultName     AsyncDataError::_name = "async_data";
193TrapType      AsyncDataError::_trapType = 0x040;
194FaultPriority AsyncDataError::_priority = 2;
195FaultStat     AsyncDataError::_count;
196
197FaultName     CleanWindow::_name = "clean_win";
198TrapType      CleanWindow::_trapType = 0x024;
199FaultPriority CleanWindow::_priority = 10;
200FaultStat     CleanWindow::_count;
201
202//The enumerated faults
203
204FaultName     InterruptLevelN::_name = "interrupt_n";
205TrapType      InterruptLevelN::_baseTrapType = 0x041;
206FaultStat     InterruptLevelN::_count;
207
208FaultName     SpillNNormal::_name = "spill_n_normal";
209TrapType      SpillNNormal::_baseTrapType = 0x080;
210FaultPriority SpillNNormal::_priority = 9;
211FaultStat     SpillNNormal::_count;
212
213FaultName     SpillNOther::_name = "spill_n_other";
214TrapType      SpillNOther::_baseTrapType = 0x0A0;
215FaultPriority SpillNOther::_priority = 9;
216FaultStat     SpillNOther::_count;
217
218FaultName     FillNNormal::_name = "fill_n_normal";
219TrapType      FillNNormal::_baseTrapType = 0x0C0;
220FaultPriority FillNNormal::_priority = 9;
221FaultStat     FillNNormal::_count;
222
223FaultName     FillNOther::_name = "fill_n_other";
224TrapType      FillNOther::_baseTrapType = 0x0E0;
225FaultPriority FillNOther::_priority = 9;
226FaultStat     FillNOther::_count;
227
228FaultName     TrapInstruction::_name = "trap_inst_n";
229TrapType      TrapInstruction::_baseTrapType = 0x100;
230FaultPriority TrapInstruction::_priority = 16;
231FaultStat     TrapInstruction::_count;
232
233#if !FULL_SYSTEM
234FaultName PageTableFault::_name = "page_table_fault";
235TrapType PageTableFault::_trapType = 0x0000;
236FaultPriority PageTableFault::_priority = 0;
237FaultStat PageTableFault::_count;
238#endif
239
240/**
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
244 * privileged level.
245 */
246
247void doNormalFault(ThreadContext *tc, TrapType tt)
248{
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();
260
261    //Increment the trap level
262    TL++;
263    tc->setMiscReg(MISCREG_TL, TL);
264
265    //Save off state
266
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);
277
278    //Write back TSTATE
279    tc->setMiscReg(MISCREG_TSTATE, TSTATE);
280
281    //set TPC to PC
282    tc->setMiscReg(MISCREG_TPC, PC);
283    //set TNPC to NPC
284    tc->setMiscReg(MISCREG_TNPC, NPC);
285
286    //set HTSTATE.hpstate to hpstate
287    tc->setMiscReg(MISCREG_HTSTATE, HPSTATE);
288
289    //TT = trap type;
290    tc->setMiscReg(MISCREG_TT, tt);
291
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));
295    else
296        tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxPGL));
297
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
302    PSTATE |= (1 << 4);
303    //PSTATE.am = 0
304    PSTATE &= ~(1 << 3);
305    if(1/*We're delivering the trap in priveleged mode*/)
306    {
307        //PSTATE.priv = 1
308        PSTATE |= (1 << 2);
309        //PSTATE.cle = PSTATE.tle
310        replaceBits(PSTATE, 9, 9, PSTATE >> 8);
311    }
312    else
313    {
314        //PSTATE.priv = 0
315        PSTATE &= ~(1 << 2);
316        //PSTATE.cle = 0
317        PSTATE &= ~(1 << 9);
318    }
319    //PSTATE.ie = 0
320    PSTATE &= ~(1 << 1);
321    //PSTATE.tle is unchanged
322    //PSTATE.tct = 0
323    //XXX Where exactly is this field?
324    tc->setMiscReg(MISCREG_PSTATE, PSTATE);
325
326    if(0/*We're delivering the trap in hyperprivileged mode*/)
327    {
328        //HPSTATE.red = 0
329        HPSTATE &= ~(1 << 5);
330        //HPSTATE.hpriv = 1
331        HPSTATE |= (1 << 2);
332        //HPSTATE.ibe = 0
333        HPSTATE &= ~(1 << 10);
334        //HPSTATE.tlz is unchanged
335        tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
336    }
337
338    bool changedCWP = true;
339    if(tt == 0x24)
340        CWP++;
341    else if(0x80 <= tt && tt <= 0xbf)
342        CWP += (CANSAVE + 2);
343    else if(0xc0 <= tt && tt <= 0xff)
344        CWP--;
345    else
346        changedCWP = false;
347
348    if(changedCWP)
349    {
350        CWP = (CWP + NWindows) % NWindows;
351        tc->setMiscRegWithEffect(MISCREG_CWP, CWP);
352    }
353}
354
355#if FULL_SYSTEM
356
357void SparcFault::invoke(ThreadContext * tc)
358{
359    FaultBase::invoke(tc);
360    countStat()++;
361
362    //Use the SPARC trap state machine
363}
364
365void PowerOnReset::invoke(ThreadContext * tc)
366{
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.
370    /*
371    tl = MaxTL;
372    gl = MaxGL;
373
374    tickFields.counter = 0; //The TICK register is unreadable bya
375    tickFields.npt = 1; //The TICK register is unreadable by by !priv
376
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
383
384    tt[tl] = _trapType;
385    pstate = 0; // fields 0 but pef
386    pstateFields.pef = 1;
387
388    hpstate = 0;
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
395    */
396}
397
398#endif
399
400#if !FULL_SYSTEM
401
402void TrapInstruction::invoke(ThreadContext * tc)
403{
404    // Should be handled in ISA.
405}
406
407void SpillNNormal::invoke(ThreadContext *tc)
408{
409    doNormalFault(tc, trapType());
410
411    Process *p = tc->getProcessPtr();
412
413    //This will only work in faults from a SparcLiveProcess
414    SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
415    assert(lp);
416
417    //Then adjust the PC and NPC
418    Addr spillStart = lp->readSpillStart();
419    tc->setPC(spillStart);
420    tc->setNextPC(spillStart + sizeof(MachInst));
421    tc->setNextNPC(spillStart + 2*sizeof(MachInst));
422}
423
424void FillNNormal::invoke(ThreadContext *tc)
425{
426    doNormalFault(tc, trapType());
427
428    Process * p = tc->getProcessPtr();
429
430    //This will only work in faults from a SparcLiveProcess
431    SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
432    assert(lp);
433
434    //The adjust the PC and NPC
435    Addr fillStart = lp->readFillStart();
436    tc->setPC(fillStart);
437    tc->setNextPC(fillStart + sizeof(MachInst));
438    tc->setNextNPC(fillStart + 2*sizeof(MachInst));
439}
440
441void PageTableFault::invoke(ThreadContext *tc)
442{
443    Process *p = tc->getProcessPtr();
444
445    // address is higher than the stack region or in the current stack region
446    if (vaddr > p->stack_base || vaddr > p->stack_min)
447        FaultBase::invoke(tc);
448
449    // We've accessed the next page
450    if (vaddr > p->stack_min - PageBytes) {
451        p->stack_min -= PageBytes;
452        if (p->stack_base - p->stack_min > 8*1024*1024)
453            fatal("Over max stack size for one thread\n");
454        p->pTable->allocate(p->stack_min, PageBytes);
455        warn("Increasing stack size by one page.");
456    } else {
457        FaultBase::invoke(tc);
458    }
459}
460
461#endif
462
463} // namespace SparcISA
464
465