ev5.cc revision 190
1/* $Id$ */
2
3#include "targetarch/alpha_memory.hh"
4#include "sim/annotation.hh"
5#ifdef DEBUG
6#include "sim/debug.hh"
7#endif
8#include "cpu/exec_context.hh"
9#include "sim/sim_events.hh"
10#include "targetarch/isa_traits.hh"
11#include "base/remote_gdb.hh"
12#include "base/kgdb.h"	// for ALPHA_KENTRY_IF
13#include "targetarch/osfpal.hh"
14
15#ifdef FULL_SYSTEM
16
17#ifndef SYSTEM_EV5
18#error This code is only valid for EV5 systems
19#endif
20
21////////////////////////////////////////////////////////////////////////
22//
23//
24//
25void
26AlphaISA::swap_palshadow(RegFile *regs, bool use_shadow)
27{
28    if (regs->pal_shadow == use_shadow)
29        panic("swap_palshadow: wrong PAL shadow state");
30
31    regs->pal_shadow = use_shadow;
32
33    for (int i = 0; i < NumIntRegs; i++) {
34        if (reg_redir[i]) {
35            IntReg temp = regs->intRegFile[i];
36            regs->intRegFile[i] = regs->palregs[i];
37            regs->palregs[i] = temp;
38        }
39    }
40}
41
42////////////////////////////////////////////////////////////////////////
43//
44//  Machine dependent functions
45//
46void
47AlphaISA::initCPU(RegFile *regs)
48{
49    initIPRs(regs);
50    // CPU comes up with PAL regs enabled
51    swap_palshadow(regs, true);
52
53    regs->pc = regs->ipr[IPR_PAL_BASE] + fault_addr[Reset_Fault];
54    regs->npc = regs->pc + sizeof(MachInst);
55}
56
57void
58m5_exit()
59{
60    static SimExitEvent event("m5_exit instruction encountered");
61}
62
63////////////////////////////////////////////////////////////////////////
64//
65// alpha exceptions - value equals trap address, update with MD_FAULT_TYPE
66//
67Addr
68AlphaISA::fault_addr[Num_Faults] = {
69    0x0000,	/* No_Fault */
70    0x0001,	/* Reset_Fault */
71    0x0401,	/* Machine_Check_Fault */
72    0x0501,	/* Arithmetic_Fault */
73    0x0101,	/* Interrupt_Fault */
74    0x0201,	/* Ndtb_Miss_Fault */
75    0x0281,	/* Pdtb_Miss_Fault */
76    0x0301,	/* Alignment_Fault */
77    0x0381,	/* Dtb_Fault_Fault */
78    0x0381,	/* Dtb_Acv_Fault */
79    0x0181,	/* Itb_Miss_Fault */
80    0x0181,	/* Itb_Fault_Fault */
81    0x0081,	/* Itb_Acv_Fault */
82    0x0481,	/* Unimplemented_Opcode_Fault */
83    0x0581,	/* Fen_Fault */
84    0x2001,	/* Pal_Fault */
85    0x0501,	/* Integer_Overflow_Fault: maps to Arithmetic_Fault */
86};
87
88const int AlphaISA::reg_redir[AlphaISA::NumIntRegs] = {
89    /*  0 */ 0, 0, 0, 0, 0, 0, 0, 0,
90    /*  8 */ 1, 1, 1, 1, 1, 1, 1, 0,
91    /* 16 */ 0, 0, 0, 0, 0, 0, 0, 0,
92    /* 24 */ 0, 1, 0, 0, 0, 0, 0, 0 };
93
94////////////////////////////////////////////////////////////////////////
95//
96//
97//
98void
99AlphaISA::initIPRs(RegFile *regs)
100{
101    uint64_t *ipr = regs->ipr;
102
103    bzero((char *)ipr, NumInternalProcRegs * sizeof(InternalProcReg));
104    ipr[IPR_PAL_BASE] = PAL_BASE;
105    ipr[IPR_MCSR] = 0x6;
106}
107
108
109void
110ExecContext::ev5_trap(Fault fault)
111{
112    assert(!misspeculating());
113    kernelStats.fault(fault);
114
115    if (fault == Arithmetic_Fault)
116        panic("Arithmetic traps are unimplemented!");
117
118    AlphaISA::InternalProcReg *ipr = regs.ipr;
119
120    // exception restart address
121    if (fault != Interrupt_Fault || !PC_PAL(regs.pc))
122        ipr[AlphaISA::IPR_EXC_ADDR] = regs.pc;
123
124    if (fault == Pal_Fault || fault == Arithmetic_Fault /* ||
125        fault == Interrupt_Fault && !PC_PAL(regs.pc) */) {
126        // traps...  skip faulting instruction
127        ipr[AlphaISA::IPR_EXC_ADDR] += 4;
128    }
129
130    if (!PC_PAL(regs.pc))
131        AlphaISA::swap_palshadow(&regs, true);
132
133    regs.pc = ipr[AlphaISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
134    regs.npc = regs.pc + sizeof(MachInst);
135
136    Annotate::Ev5Trap(this, fault);
137}
138
139
140void
141AlphaISA::intr_post(RegFile *regs, Fault fault, Addr pc)
142{
143    InternalProcReg *ipr = regs->ipr;
144    bool use_pc = (fault == No_Fault);
145
146    if (fault == Arithmetic_Fault)
147        panic("arithmetic faults NYI...");
148
149    // compute exception restart address
150    if (use_pc || fault == Pal_Fault || fault == Arithmetic_Fault) {
151        // traps...  skip faulting instruction
152        ipr[IPR_EXC_ADDR] = regs->pc + 4;
153    } else {
154        // fault, post fault at excepting instruction
155        ipr[IPR_EXC_ADDR] = regs->pc;
156    }
157
158    // jump to expection address (PAL PC bit set here as well...)
159    if (!use_pc)
160        regs->npc = ipr[IPR_PAL_BASE] + fault_addr[fault];
161    else
162        regs->npc = ipr[IPR_PAL_BASE] + pc;
163
164    // that's it! (orders of magnitude less painful than x86)
165}
166
167bool AlphaISA::check_interrupts = false;
168
169Fault
170ExecContext::hwrei()
171{
172    uint64_t *ipr = regs.ipr;
173
174    if (!PC_PAL(regs.pc))
175        return Unimplemented_Opcode_Fault;
176
177    kernelStats.hwrei();
178
179    regs.npc = ipr[AlphaISA::IPR_EXC_ADDR];
180
181    if (!misspeculating()) {
182        if ((ipr[AlphaISA::IPR_EXC_ADDR] & 1) == 0)
183            AlphaISA::swap_palshadow(&regs, false);
184
185        AlphaISA::check_interrupts = true;
186    }
187
188    // FIXME: XXX check for interrupts? XXX
189    return No_Fault;
190}
191
192uint64_t
193ExecContext::readIpr(int idx, Fault &fault)
194{
195    uint64_t *ipr = regs.ipr;
196    uint64_t retval = 0;	// return value, default 0
197
198    switch (idx) {
199      case AlphaISA::IPR_PALtemp0:
200      case AlphaISA::IPR_PALtemp1:
201      case AlphaISA::IPR_PALtemp2:
202      case AlphaISA::IPR_PALtemp3:
203      case AlphaISA::IPR_PALtemp4:
204      case AlphaISA::IPR_PALtemp5:
205      case AlphaISA::IPR_PALtemp6:
206      case AlphaISA::IPR_PALtemp7:
207      case AlphaISA::IPR_PALtemp8:
208      case AlphaISA::IPR_PALtemp9:
209      case AlphaISA::IPR_PALtemp10:
210      case AlphaISA::IPR_PALtemp11:
211      case AlphaISA::IPR_PALtemp12:
212      case AlphaISA::IPR_PALtemp13:
213      case AlphaISA::IPR_PALtemp14:
214      case AlphaISA::IPR_PALtemp15:
215      case AlphaISA::IPR_PALtemp16:
216      case AlphaISA::IPR_PALtemp17:
217      case AlphaISA::IPR_PALtemp18:
218      case AlphaISA::IPR_PALtemp19:
219      case AlphaISA::IPR_PALtemp20:
220      case AlphaISA::IPR_PALtemp21:
221      case AlphaISA::IPR_PALtemp22:
222      case AlphaISA::IPR_PALtemp23:
223      case AlphaISA::IPR_PAL_BASE:
224
225      case AlphaISA::IPR_IVPTBR:
226      case AlphaISA::IPR_DC_MODE:
227      case AlphaISA::IPR_MAF_MODE:
228      case AlphaISA::IPR_ISR:
229      case AlphaISA::IPR_EXC_ADDR:
230      case AlphaISA::IPR_IC_PERR_STAT:
231      case AlphaISA::IPR_DC_PERR_STAT:
232      case AlphaISA::IPR_MCSR:
233      case AlphaISA::IPR_ASTRR:
234      case AlphaISA::IPR_ASTER:
235      case AlphaISA::IPR_SIRR:
236      case AlphaISA::IPR_ICSR:
237      case AlphaISA::IPR_ICM:
238      case AlphaISA::IPR_DTB_CM:
239      case AlphaISA::IPR_IPLR:
240      case AlphaISA::IPR_INTID:
241      case AlphaISA::IPR_PMCTR:
242        // no side-effect
243        retval = ipr[idx];
244        break;
245
246      case AlphaISA::IPR_VA:
247        // SFX: unlocks interrupt status registers
248        retval = ipr[idx];
249        regs.intrlock = false;
250        break;
251
252      case AlphaISA::IPR_VA_FORM:
253      case AlphaISA::IPR_MM_STAT:
254      case AlphaISA::IPR_IFAULT_VA_FORM:
255      case AlphaISA::IPR_EXC_MASK:
256      case AlphaISA::IPR_EXC_SUM:
257        retval = ipr[idx];
258        break;
259
260      case AlphaISA::IPR_DTB_PTE:
261        {
262            AlphaISA::PTE &pte = dtb->index();
263
264            retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32;
265            retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8;
266            retval |= ((u_int64_t)pte.xwe & ULL(0xf)) << 12;
267            retval |= ((u_int64_t)pte.fonr & ULL(0x1)) << 1;
268            retval |= ((u_int64_t)pte.fonw & ULL(0x1))<< 2;
269            retval |= ((u_int64_t)pte.asma & ULL(0x1)) << 4;
270            retval |= ((u_int64_t)pte.asn & ULL(0x7f)) << 57;
271        }
272        break;
273
274        // write only registers
275      case AlphaISA::IPR_HWINT_CLR:
276      case AlphaISA::IPR_SL_XMIT:
277      case AlphaISA::IPR_DC_FLUSH:
278      case AlphaISA::IPR_IC_FLUSH:
279      case AlphaISA::IPR_ALT_MODE:
280      case AlphaISA::IPR_DTB_IA:
281      case AlphaISA::IPR_DTB_IAP:
282      case AlphaISA::IPR_ITB_IA:
283      case AlphaISA::IPR_ITB_IAP:
284        fault = Unimplemented_Opcode_Fault;
285        break;
286
287      default:
288        // invalid IPR
289        fault = Unimplemented_Opcode_Fault;
290        break;
291    }
292
293    return retval;
294}
295
296#ifdef DEBUG
297// Cause the simulator to break when changing to the following IPL
298int break_ipl = -1;
299#endif
300
301Fault
302ExecContext::setIpr(int idx, uint64_t val)
303{
304    uint64_t *ipr = regs.ipr;
305
306    if (misspeculating())
307        return No_Fault;
308
309    switch (idx) {
310      case AlphaISA::IPR_PALtemp0:
311      case AlphaISA::IPR_PALtemp1:
312      case AlphaISA::IPR_PALtemp2:
313      case AlphaISA::IPR_PALtemp3:
314      case AlphaISA::IPR_PALtemp4:
315      case AlphaISA::IPR_PALtemp5:
316      case AlphaISA::IPR_PALtemp6:
317      case AlphaISA::IPR_PALtemp7:
318      case AlphaISA::IPR_PALtemp8:
319      case AlphaISA::IPR_PALtemp9:
320      case AlphaISA::IPR_PALtemp10:
321      case AlphaISA::IPR_PALtemp11:
322      case AlphaISA::IPR_PALtemp12:
323      case AlphaISA::IPR_PALtemp13:
324      case AlphaISA::IPR_PALtemp14:
325      case AlphaISA::IPR_PALtemp15:
326      case AlphaISA::IPR_PALtemp16:
327      case AlphaISA::IPR_PALtemp17:
328      case AlphaISA::IPR_PALtemp18:
329      case AlphaISA::IPR_PALtemp19:
330      case AlphaISA::IPR_PALtemp20:
331      case AlphaISA::IPR_PALtemp21:
332      case AlphaISA::IPR_PALtemp22:
333      case AlphaISA::IPR_PAL_BASE:
334      case AlphaISA::IPR_IC_PERR_STAT:
335      case AlphaISA::IPR_DC_PERR_STAT:
336      case AlphaISA::IPR_CC_CTL:
337      case AlphaISA::IPR_CC:
338      case AlphaISA::IPR_PMCTR:
339        // write entire quad w/ no side-effect
340        ipr[idx] = val;
341        break;
342
343      case AlphaISA::IPR_PALtemp23:
344        // write entire quad w/ no side-effect
345        ipr[idx] = val;
346        kernelStats.context(ipr[idx]);
347        Annotate::Context(this);
348        break;
349
350      case AlphaISA::IPR_DTB_PTE:
351        // write entire quad w/ no side-effect, tag is forthcoming
352        ipr[idx] = val;
353        break;
354
355      case AlphaISA::IPR_EXC_ADDR:
356        // second least significant bit in PC is always zero
357        ipr[idx] = val & ~2;
358        break;
359
360      case AlphaISA::IPR_ASTRR:
361      case AlphaISA::IPR_ASTER:
362        // only write least significant four bits - privilege mask
363        ipr[idx] = val & 0xf;
364        break;
365
366      case AlphaISA::IPR_IPLR:
367#ifdef DEBUG
368        if (break_ipl != -1 && break_ipl == (val & 0x1f))
369            debug_break();
370#endif
371
372        // only write least significant five bits - interrupt level
373        ipr[idx] = val & 0x1f;
374        kernelStats.swpipl(ipr[idx]);
375        Annotate::IPL(this, val & 0x1f);
376        break;
377
378      case AlphaISA::IPR_DTB_CM:
379        Annotate::ChangeMode(this, (val & 0x18) != 0);
380        kernelStats.mode((val & 0x18) != 0);
381
382      case AlphaISA::IPR_ICM:
383        // only write two mode bits - processor mode
384        ipr[idx] = val & 0x18;
385        break;
386
387      case AlphaISA::IPR_ALT_MODE:
388        // only write two mode bits - processor mode
389        ipr[idx] = val & 0x18;
390        break;
391
392      case AlphaISA::IPR_MCSR:
393        // more here after optimization...
394        ipr[idx] = val;
395        break;
396
397      case AlphaISA::IPR_SIRR:
398        // only write software interrupt mask
399        ipr[idx] = val & 0x7fff0;
400        break;
401
402      case AlphaISA::IPR_ICSR:
403        ipr[idx] = val & ULL(0xffffff0300);
404        break;
405
406      case AlphaISA::IPR_IVPTBR:
407      case AlphaISA::IPR_MVPTBR:
408        ipr[idx] = val & ULL(0xffffffffc0000000);
409        break;
410
411      case AlphaISA::IPR_DC_TEST_CTL:
412        ipr[idx] = val & 0x1ffb;
413        break;
414
415      case AlphaISA::IPR_DC_MODE:
416      case AlphaISA::IPR_MAF_MODE:
417        ipr[idx] = val & 0x3f;
418        break;
419
420      case AlphaISA::IPR_ITB_ASN:
421        ipr[idx] = val & 0x7f0;
422        break;
423
424      case AlphaISA::IPR_DTB_ASN:
425        ipr[idx] = val & ULL(0xfe00000000000000);
426        break;
427
428      case AlphaISA::IPR_EXC_SUM:
429      case AlphaISA::IPR_EXC_MASK:
430        // any write to this register clears it
431        ipr[idx] = 0;
432        break;
433
434      case AlphaISA::IPR_INTID:
435      case AlphaISA::IPR_SL_RCV:
436      case AlphaISA::IPR_MM_STAT:
437      case AlphaISA::IPR_ITB_PTE_TEMP:
438      case AlphaISA::IPR_DTB_PTE_TEMP:
439        // read-only registers
440        return Unimplemented_Opcode_Fault;
441
442      case AlphaISA::IPR_HWINT_CLR:
443      case AlphaISA::IPR_SL_XMIT:
444      case AlphaISA::IPR_DC_FLUSH:
445      case AlphaISA::IPR_IC_FLUSH:
446        // the following are write only
447        ipr[idx] = val;
448        break;
449
450      case AlphaISA::IPR_DTB_IA:
451        // really a control write
452        ipr[idx] = 0;
453
454        dtb->flushAll();
455        break;
456
457      case AlphaISA::IPR_DTB_IAP:
458        // really a control write
459        ipr[idx] = 0;
460
461        dtb->flushProcesses();
462        break;
463
464      case AlphaISA::IPR_DTB_IS:
465        // really a control write
466        ipr[idx] = val;
467
468        dtb->flushAddr(val, DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
469        break;
470
471      case AlphaISA::IPR_DTB_TAG: {
472          struct AlphaISA::PTE pte;
473
474          // FIXME: granularity hints NYI...
475          if (DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0)
476              panic("PTE GH field != 0");
477
478          // write entire quad
479          ipr[idx] = val;
480
481          // construct PTE for new entry
482          pte.ppn = DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]);
483          pte.xre = DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]);
484          pte.xwe = DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]);
485          pte.fonr = DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]);
486          pte.fonw = DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]);
487          pte.asma = DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]);
488          pte.asn = DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]);
489
490          // insert new TAG/PTE value into data TLB
491          dtb->insert(val, pte);
492      }
493        break;
494
495      case AlphaISA::IPR_ITB_PTE: {
496          struct AlphaISA::PTE pte;
497
498          // FIXME: granularity hints NYI...
499          if (ITB_PTE_GH(val) != 0)
500              panic("PTE GH field != 0");
501
502          // write entire quad
503          ipr[idx] = val;
504
505          // construct PTE for new entry
506          pte.ppn = ITB_PTE_PPN(val);
507          pte.xre = ITB_PTE_XRE(val);
508          pte.xwe = 0;
509          pte.fonr = ITB_PTE_FONR(val);
510          pte.fonw = ITB_PTE_FONW(val);
511          pte.asma = ITB_PTE_ASMA(val);
512          pte.asn = ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]);
513
514          // insert new TAG/PTE value into data TLB
515          itb->insert(ipr[AlphaISA::IPR_ITB_TAG], pte);
516      }
517        break;
518
519      case AlphaISA::IPR_ITB_IA:
520        // really a control write
521        ipr[idx] = 0;
522
523        itb->flushAll();
524        break;
525
526      case AlphaISA::IPR_ITB_IAP:
527        // really a control write
528        ipr[idx] = 0;
529
530        itb->flushProcesses();
531        break;
532
533      case AlphaISA::IPR_ITB_IS:
534        // really a control write
535        ipr[idx] = val;
536
537        itb->flushAddr(val, ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
538        break;
539
540      default:
541        // invalid IPR
542        return Unimplemented_Opcode_Fault;
543    }
544
545    // no error...
546    return No_Fault;
547}
548
549/**
550 * Check for special simulator handling of specific PAL calls.
551 * If return value is false, actual PAL call will be suppressed.
552 */
553bool
554ExecContext::simPalCheck(int palFunc)
555{
556    kernelStats.callpal(palFunc);
557
558    switch (palFunc) {
559      case PAL::halt:
560        if (!misspeculating()) {
561            setStatus(Halted);
562            if (--System::numSystemsRunning == 0)
563                new SimExitEvent("all cpus halted");
564        }
565        break;
566
567      case PAL::bpt:
568      case PAL::bugchk:
569        if (system->breakpoint())
570            return false;
571        break;
572    }
573
574    return true;
575}
576
577#endif // FULL_SYSTEM
578