faults.cc revision 3415
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
46using namespace std;
47
48namespace SparcISA
49{
50
51FaultName     InternalProcessorError::_name = "intprocerr";
52TrapType      InternalProcessorError::_trapType = 0x029;
53FaultPriority InternalProcessorError::_priority = 4;
54FaultStat     InternalProcessorError::_count;
55
56FaultName     MemAddressNotAligned::_name = "unalign";
57TrapType      MemAddressNotAligned::_trapType = 0x034;
58FaultPriority MemAddressNotAligned::_priority = 10;
59FaultStat     MemAddressNotAligned::_count;
60
61FaultName     PowerOnReset::_name = "pow_reset";
62TrapType      PowerOnReset::_trapType = 0x001;
63FaultPriority PowerOnReset::_priority = 0;
64FaultStat     PowerOnReset::_count;
65
66FaultName     WatchDogReset::_name = "watch_dog_reset";
67TrapType      WatchDogReset::_trapType = 0x002;
68FaultPriority WatchDogReset::_priority = 1;
69FaultStat     WatchDogReset::_count;
70
71FaultName     ExternallyInitiatedReset::_name = "extern_reset";
72TrapType      ExternallyInitiatedReset::_trapType = 0x003;
73FaultPriority ExternallyInitiatedReset::_priority = 1;
74FaultStat     ExternallyInitiatedReset::_count;
75
76FaultName     SoftwareInitiatedReset::_name = "software_reset";
77TrapType      SoftwareInitiatedReset::_trapType = 0x004;
78FaultPriority SoftwareInitiatedReset::_priority = 1;
79FaultStat     SoftwareInitiatedReset::_count;
80
81FaultName     REDStateException::_name = "red_counte";
82TrapType      REDStateException::_trapType = 0x005;
83FaultPriority REDStateException::_priority = 1;
84FaultStat     REDStateException::_count;
85
86FaultName     InstructionAccessException::_name = "inst_access";
87TrapType      InstructionAccessException::_trapType = 0x008;
88FaultPriority InstructionAccessException::_priority = 5;
89FaultStat     InstructionAccessException::_count;
90
91FaultName     InstructionAccessMMUMiss::_name = "inst_mmu";
92TrapType      InstructionAccessMMUMiss::_trapType = 0x009;
93FaultPriority InstructionAccessMMUMiss::_priority = 2;
94FaultStat     InstructionAccessMMUMiss::_count;
95
96FaultName     InstructionAccessError::_name = "inst_error";
97TrapType      InstructionAccessError::_trapType = 0x00A;
98FaultPriority InstructionAccessError::_priority = 3;
99FaultStat     InstructionAccessError::_count;
100
101FaultName     IllegalInstruction::_name = "illegal_inst";
102TrapType      IllegalInstruction::_trapType = 0x010;
103FaultPriority IllegalInstruction::_priority = 7;
104FaultStat     IllegalInstruction::_count;
105
106FaultName     PrivilegedOpcode::_name = "priv_opcode";
107TrapType      PrivilegedOpcode::_trapType = 0x011;
108FaultPriority PrivilegedOpcode::_priority = 6;
109FaultStat     PrivilegedOpcode::_count;
110
111FaultName     UnimplementedLDD::_name = "unimp_ldd";
112TrapType      UnimplementedLDD::_trapType = 0x012;
113FaultPriority UnimplementedLDD::_priority = 6;
114FaultStat     UnimplementedLDD::_count;
115
116FaultName     UnimplementedSTD::_name = "unimp_std";
117TrapType      UnimplementedSTD::_trapType = 0x013;
118FaultPriority UnimplementedSTD::_priority = 6;
119FaultStat     UnimplementedSTD::_count;
120
121FaultName     FpDisabled::_name = "fp_disabled";
122TrapType      FpDisabled::_trapType = 0x020;
123FaultPriority FpDisabled::_priority = 8;
124FaultStat     FpDisabled::_count;
125
126FaultName     FpExceptionIEEE754::_name = "fp_754";
127TrapType      FpExceptionIEEE754::_trapType = 0x021;
128FaultPriority FpExceptionIEEE754::_priority = 11;
129FaultStat     FpExceptionIEEE754::_count;
130
131FaultName     FpExceptionOther::_name = "fp_other";
132TrapType      FpExceptionOther::_trapType = 0x022;
133FaultPriority FpExceptionOther::_priority = 11;
134FaultStat     FpExceptionOther::_count;
135
136FaultName     TagOverflow::_name = "tag_overflow";
137TrapType      TagOverflow::_trapType = 0x023;
138FaultPriority TagOverflow::_priority = 14;
139FaultStat     TagOverflow::_count;
140
141FaultName     DivisionByZero::_name = "div_by_zero";
142TrapType      DivisionByZero::_trapType = 0x028;
143FaultPriority DivisionByZero::_priority = 15;
144FaultStat     DivisionByZero::_count;
145
146FaultName     DataAccessException::_name = "data_access";
147TrapType      DataAccessException::_trapType = 0x030;
148FaultPriority DataAccessException::_priority = 12;
149FaultStat     DataAccessException::_count;
150
151FaultName     DataAccessMMUMiss::_name = "data_mmu";
152TrapType      DataAccessMMUMiss::_trapType = 0x031;
153FaultPriority DataAccessMMUMiss::_priority = 12;
154FaultStat     DataAccessMMUMiss::_count;
155
156FaultName     DataAccessError::_name = "data_error";
157TrapType      DataAccessError::_trapType = 0x032;
158FaultPriority DataAccessError::_priority = 12;
159FaultStat     DataAccessError::_count;
160
161FaultName     DataAccessProtection::_name = "data_protection";
162TrapType      DataAccessProtection::_trapType = 0x033;
163FaultPriority DataAccessProtection::_priority = 12;
164FaultStat     DataAccessProtection::_count;
165
166FaultName     LDDFMemAddressNotAligned::_name = "unalign_lddf";
167TrapType      LDDFMemAddressNotAligned::_trapType = 0x035;
168FaultPriority LDDFMemAddressNotAligned::_priority = 10;
169FaultStat     LDDFMemAddressNotAligned::_count;
170
171FaultName     STDFMemAddressNotAligned::_name = "unalign_stdf";
172TrapType      STDFMemAddressNotAligned::_trapType = 0x036;
173FaultPriority STDFMemAddressNotAligned::_priority = 10;
174FaultStat     STDFMemAddressNotAligned::_count;
175
176FaultName     PrivilegedAction::_name = "priv_action";
177TrapType      PrivilegedAction::_trapType = 0x037;
178FaultPriority PrivilegedAction::_priority = 11;
179FaultStat     PrivilegedAction::_count;
180
181FaultName     LDQFMemAddressNotAligned::_name = "unalign_ldqf";
182TrapType      LDQFMemAddressNotAligned::_trapType = 0x038;
183FaultPriority LDQFMemAddressNotAligned::_priority = 10;
184FaultStat     LDQFMemAddressNotAligned::_count;
185
186FaultName     STQFMemAddressNotAligned::_name = "unalign_stqf";
187TrapType      STQFMemAddressNotAligned::_trapType = 0x039;
188FaultPriority STQFMemAddressNotAligned::_priority = 10;
189FaultStat     STQFMemAddressNotAligned::_count;
190
191FaultName     AsyncDataError::_name = "async_data";
192TrapType      AsyncDataError::_trapType = 0x040;
193FaultPriority AsyncDataError::_priority = 2;
194FaultStat     AsyncDataError::_count;
195
196FaultName     CleanWindow::_name = "clean_win";
197TrapType      CleanWindow::_trapType = 0x024;
198FaultPriority CleanWindow::_priority = 10;
199FaultStat     CleanWindow::_count;
200
201//The enumerated faults
202
203FaultName     InterruptLevelN::_name = "interrupt_n";
204TrapType      InterruptLevelN::_baseTrapType = 0x041;
205FaultStat     InterruptLevelN::_count;
206
207FaultName     SpillNNormal::_name = "spill_n_normal";
208TrapType      SpillNNormal::_baseTrapType = 0x080;
209FaultPriority SpillNNormal::_priority = 9;
210FaultStat     SpillNNormal::_count;
211
212FaultName     SpillNOther::_name = "spill_n_other";
213TrapType      SpillNOther::_baseTrapType = 0x0A0;
214FaultPriority SpillNOther::_priority = 9;
215FaultStat     SpillNOther::_count;
216
217FaultName     FillNNormal::_name = "fill_n_normal";
218TrapType      FillNNormal::_baseTrapType = 0x0C0;
219FaultPriority FillNNormal::_priority = 9;
220FaultStat     FillNNormal::_count;
221
222FaultName     FillNOther::_name = "fill_n_other";
223TrapType      FillNOther::_baseTrapType = 0x0E0;
224FaultPriority FillNOther::_priority = 9;
225FaultStat     FillNOther::_count;
226
227FaultName     TrapInstruction::_name = "trap_inst_n";
228TrapType      TrapInstruction::_baseTrapType = 0x100;
229FaultPriority TrapInstruction::_priority = 16;
230FaultStat     TrapInstruction::_count;
231
232#if !FULL_SYSTEM
233FaultName PageTableFault::_name = "page_table_fault";
234TrapType PageTableFault::_trapType = 0x0000;
235FaultPriority PageTableFault::_priority = 0;
236FaultStat 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
246void 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    {
340        warn("Incrementing the CWP by 1\n");
341        CWP++;
342    }
343    else if(0x80 <= tt && tt <= 0xbf)
344    {
345        warn("Incrementing the CWP by %d\n", CANSAVE + 2);
346        CWP += (CANSAVE + 2);
347    }
348    else if(0xc0 <= tt && tt <= 0xff)
349    {
350        warn("Decrementing the CWP by 1\n");
351        CWP--;
352    }
353    else
354        changedCWP = false;
355    if(changedCWP)
356    {
357        CWP = (CWP + NWindows) % NWindows;
358        tc->setMiscRegWithEffect(MISCREG_CWP, CWP);
359    }
360}
361
362#if FULL_SYSTEM
363
364void SparcFault::invoke(ThreadContext * tc)
365{
366    FaultBase::invoke(tc);
367    countStat()++;
368
369    //Use the SPARC trap state machine
370    /*// exception restart address
371    if (setRestartAddress() || !tc->inPalMode())
372        tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, tc->regs.pc);
373
374    if (skipFaultingInstruction()) {
375        // traps...  skip faulting instruction.
376        tc->setMiscReg(AlphaISA::IPR_EXC_ADDR,
377                   tc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4);
378    }
379
380    if (!tc->inPalMode())
381        AlphaISA::swap_palshadow(&(tc->regs), true);
382
383    tc->regs.pc = tc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect();
384    tc->regs.npc = tc->regs.pc + sizeof(MachInst);*/
385}
386
387#endif
388
389#if !FULL_SYSTEM
390
391void TrapInstruction::invoke(ThreadContext * tc)
392{
393    // Should be handled in ISA.
394}
395
396void SpillNNormal::invoke(ThreadContext *tc)
397{
398    warn("I'm in a spill trap\n");
399    doNormalFault(tc, trapType());
400
401    Process *p = tc->getProcessPtr();
402
403    //This will only work in faults from a SparcLiveProcess
404    SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
405    assert(lp);
406
407    //Then adjust the PC and NPC
408    Addr spillStart = lp->readSpillStart();
409    tc->setPC(spillStart);
410    tc->setNextPC(spillStart + sizeof(MachInst));
411    tc->setNextNPC(spillStart + 2*sizeof(MachInst));
412}
413
414void FillNNormal::invoke(ThreadContext *tc)
415{
416    warn("I'm in a fill trap\n");
417    doNormalFault(tc, trapType());
418
419    Process * p = tc->getProcessPtr();
420
421    //This will only work in faults from a SparcLiveProcess
422    SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
423    assert(lp);
424
425    //The adjust the PC and NPC
426    Addr fillStart = lp->readFillStart();
427    tc->setPC(fillStart);
428    tc->setNextPC(fillStart + sizeof(MachInst));
429    tc->setNextNPC(fillStart + 2*sizeof(MachInst));
430}
431
432void PageTableFault::invoke(ThreadContext *tc)
433{
434    Process *p = tc->getProcessPtr();
435
436    // address is higher than the stack region or in the current stack region
437    if (vaddr > p->stack_base || vaddr > p->stack_min)
438        FaultBase::invoke(tc);
439
440    // We've accessed the next page
441    if (vaddr > p->stack_min - PageBytes) {
442        p->stack_min -= PageBytes;
443        if (p->stack_base - p->stack_min > 8*1024*1024)
444            fatal("Over max stack size for one thread\n");
445        p->pTable->allocate(p->stack_min, PageBytes);
446        warn("Increasing stack size by one page.");
447    } else {
448        FaultBase::invoke(tc);
449    }
450}
451
452#endif
453
454} // namespace SparcISA
455
456