ev5.cc revision 7447:3fc243687abb
1/*
2 * Copyright (c) 2002-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: Steve Reinhardt
29 *          Nathan Binkert
30 */
31
32#include "arch/alpha/faults.hh"
33#include "arch/alpha/isa_traits.hh"
34#include "arch/alpha/kernel_stats.hh"
35#include "arch/alpha/osfpal.hh"
36#include "arch/alpha/tlb.hh"
37#include "base/cp_annotate.hh"
38#include "base/debug.hh"
39#include "base/stats/events.hh"
40#include "config/full_system.hh"
41#include "cpu/base.hh"
42#include "cpu/simple_thread.hh"
43#include "cpu/thread_context.hh"
44#include "sim/sim_exit.hh"
45
46namespace AlphaISA {
47
48#if FULL_SYSTEM
49
50////////////////////////////////////////////////////////////////////////
51//
52//  Machine dependent functions
53//
54void
55initCPU(ThreadContext *tc, int cpuId)
56{
57    initIPRs(tc, cpuId);
58
59    tc->setIntReg(16, cpuId);
60    tc->setIntReg(0, cpuId);
61
62    AlphaFault *reset = new ResetFault;
63
64    tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect());
65    tc->setNextPC(tc->readPC() + sizeof(MachInst));
66
67    delete reset;
68}
69
70
71template <class CPU>
72void
73processInterrupts(CPU *cpu)
74{
75    //Check if there are any outstanding interrupts
76    //Handle the interrupts
77    int ipl = 0;
78    int summary = 0;
79
80    if (cpu->readMiscRegNoEffect(IPR_ASTRR))
81        panic("asynchronous traps not implemented\n");
82
83    if (cpu->readMiscRegNoEffect(IPR_SIRR)) {
84        for (int i = INTLEVEL_SOFTWARE_MIN;
85             i < INTLEVEL_SOFTWARE_MAX; i++) {
86            if (cpu->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) {
87                // See table 4-19 of the 21164 hardware reference
88                ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
89                summary |= (ULL(1) << i);
90            }
91        }
92    }
93
94    uint64_t interrupts = cpu->intr_status();
95
96    if (interrupts) {
97        for (int i = INTLEVEL_EXTERNAL_MIN;
98             i < INTLEVEL_EXTERNAL_MAX; i++) {
99            if (interrupts & (ULL(1) << i)) {
100                // See table 4-19 of the 21164 hardware reference
101                ipl = i;
102                summary |= (ULL(1) << i);
103            }
104        }
105    }
106
107    if (ipl && ipl > cpu->readMiscRegNoEffect(IPR_IPLR)) {
108        cpu->setMiscRegNoEffect(IPR_ISR, summary);
109        cpu->setMiscRegNoEffect(IPR_INTID, ipl);
110        cpu->trap(new InterruptFault);
111        DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
112                cpu->readMiscRegNoEffect(IPR_IPLR), ipl, summary);
113    }
114
115}
116
117template <class CPU>
118void
119zeroRegisters(CPU *cpu)
120{
121    // Insure ISA semantics
122    // (no longer very clean due to the change in setIntReg() in the
123    // cpu model.  Consider changing later.)
124    cpu->thread->setIntReg(ZeroReg, 0);
125    cpu->thread->setFloatReg(ZeroReg, 0.0);
126}
127
128#endif
129
130////////////////////////////////////////////////////////////////////////
131//
132//
133//
134void
135initIPRs(ThreadContext *tc, int cpuId)
136{
137    for (int i = 0; i < NumInternalProcRegs; ++i) {
138        tc->setMiscRegNoEffect(i, 0);
139    }
140
141    tc->setMiscRegNoEffect(IPR_PAL_BASE, PalBase);
142    tc->setMiscRegNoEffect(IPR_MCSR, 0x6);
143    tc->setMiscRegNoEffect(IPR_PALtemp16, cpuId);
144}
145
146MiscReg
147ISA::readIpr(int idx, ThreadContext *tc)
148{
149    uint64_t retval = 0;        // return value, default 0
150
151    switch (idx) {
152      case IPR_PALtemp0:
153      case IPR_PALtemp1:
154      case IPR_PALtemp2:
155      case IPR_PALtemp3:
156      case IPR_PALtemp4:
157      case IPR_PALtemp5:
158      case IPR_PALtemp6:
159      case IPR_PALtemp7:
160      case IPR_PALtemp8:
161      case IPR_PALtemp9:
162      case IPR_PALtemp10:
163      case IPR_PALtemp11:
164      case IPR_PALtemp12:
165      case IPR_PALtemp13:
166      case IPR_PALtemp14:
167      case IPR_PALtemp15:
168      case IPR_PALtemp16:
169      case IPR_PALtemp17:
170      case IPR_PALtemp18:
171      case IPR_PALtemp19:
172      case IPR_PALtemp20:
173      case IPR_PALtemp21:
174      case IPR_PALtemp22:
175      case IPR_PALtemp23:
176      case IPR_PAL_BASE:
177
178      case IPR_IVPTBR:
179      case IPR_DC_MODE:
180      case IPR_MAF_MODE:
181      case IPR_ISR:
182      case IPR_EXC_ADDR:
183      case IPR_IC_PERR_STAT:
184      case IPR_DC_PERR_STAT:
185      case IPR_MCSR:
186      case IPR_ASTRR:
187      case IPR_ASTER:
188      case IPR_SIRR:
189      case IPR_ICSR:
190      case IPR_ICM:
191      case IPR_DTB_CM:
192      case IPR_IPLR:
193      case IPR_INTID:
194      case IPR_PMCTR:
195        // no side-effect
196        retval = ipr[idx];
197        break;
198
199      case IPR_CC:
200        retval |= ipr[idx] & ULL(0xffffffff00000000);
201        retval |= tc->getCpuPtr()->curCycle()  & ULL(0x00000000ffffffff);
202        break;
203
204      case IPR_VA:
205        retval = ipr[idx];
206        break;
207
208      case IPR_VA_FORM:
209      case IPR_MM_STAT:
210      case IPR_IFAULT_VA_FORM:
211      case IPR_EXC_MASK:
212      case IPR_EXC_SUM:
213        retval = ipr[idx];
214        break;
215
216      case IPR_DTB_PTE:
217        {
218            TlbEntry &entry
219                = tc->getDTBPtr()->index(!tc->misspeculating());
220
221            retval |= ((uint64_t)entry.ppn & ULL(0x7ffffff)) << 32;
222            retval |= ((uint64_t)entry.xre & ULL(0xf)) << 8;
223            retval |= ((uint64_t)entry.xwe & ULL(0xf)) << 12;
224            retval |= ((uint64_t)entry.fonr & ULL(0x1)) << 1;
225            retval |= ((uint64_t)entry.fonw & ULL(0x1))<< 2;
226            retval |= ((uint64_t)entry.asma & ULL(0x1)) << 4;
227            retval |= ((uint64_t)entry.asn & ULL(0x7f)) << 57;
228        }
229        break;
230
231        // write only registers
232      case IPR_HWINT_CLR:
233      case IPR_SL_XMIT:
234      case IPR_DC_FLUSH:
235      case IPR_IC_FLUSH:
236      case IPR_ALT_MODE:
237      case IPR_DTB_IA:
238      case IPR_DTB_IAP:
239      case IPR_ITB_IA:
240      case IPR_ITB_IAP:
241        panic("Tried to read write only register %d\n", idx);
242        break;
243
244      default:
245        // invalid IPR
246        panic("Tried to read from invalid ipr %d\n", idx);
247        break;
248    }
249
250    return retval;
251}
252
253#ifdef DEBUG
254// Cause the simulator to break when changing to the following IPL
255int break_ipl = -1;
256#endif
257
258void
259ISA::setIpr(int idx, uint64_t val, ThreadContext *tc)
260{
261    uint64_t old;
262
263    if (tc->misspeculating())
264        return;
265
266    switch (idx) {
267      case IPR_PALtemp0:
268      case IPR_PALtemp1:
269      case IPR_PALtemp2:
270      case IPR_PALtemp3:
271      case IPR_PALtemp4:
272      case IPR_PALtemp5:
273      case IPR_PALtemp6:
274      case IPR_PALtemp7:
275      case IPR_PALtemp8:
276      case IPR_PALtemp9:
277      case IPR_PALtemp10:
278      case IPR_PALtemp11:
279      case IPR_PALtemp12:
280      case IPR_PALtemp13:
281      case IPR_PALtemp14:
282      case IPR_PALtemp15:
283      case IPR_PALtemp16:
284      case IPR_PALtemp17:
285      case IPR_PALtemp18:
286      case IPR_PALtemp19:
287      case IPR_PALtemp20:
288      case IPR_PALtemp21:
289      case IPR_PALtemp22:
290      case IPR_PAL_BASE:
291      case IPR_IC_PERR_STAT:
292      case IPR_DC_PERR_STAT:
293      case IPR_PMCTR:
294        // write entire quad w/ no side-effect
295        ipr[idx] = val;
296        break;
297
298      case IPR_CC_CTL:
299        // This IPR resets the cycle counter.  We assume this only
300        // happens once... let's verify that.
301        assert(ipr[idx] == 0);
302        ipr[idx] = 1;
303        break;
304
305      case IPR_CC:
306        // This IPR only writes the upper 64 bits.  It's ok to write
307        // all 64 here since we mask out the lower 32 in rpcc (see
308        // isa_desc).
309        ipr[idx] = val;
310        break;
311
312      case IPR_PALtemp23:
313        // write entire quad w/ no side-effect
314        old = ipr[idx];
315        ipr[idx] = val;
316#if FULL_SYSTEM
317        if (tc->getKernelStats())
318            tc->getKernelStats()->context(old, val, tc);
319#endif
320        break;
321
322      case IPR_DTB_PTE:
323        // write entire quad w/ no side-effect, tag is forthcoming
324        ipr[idx] = val;
325        break;
326
327      case IPR_EXC_ADDR:
328        // second least significant bit in PC is always zero
329        ipr[idx] = val & ~2;
330        break;
331
332      case IPR_ASTRR:
333      case IPR_ASTER:
334        // only write least significant four bits - privilege mask
335        ipr[idx] = val & 0xf;
336        break;
337
338      case IPR_IPLR:
339#ifdef DEBUG
340        if (break_ipl != -1 && break_ipl == (int)(val & 0x1f))
341            debug_break();
342#endif
343
344        // only write least significant five bits - interrupt level
345        ipr[idx] = val & 0x1f;
346#if FULL_SYSTEM
347        if (tc->getKernelStats())
348            tc->getKernelStats()->swpipl(ipr[idx]);
349#endif
350        break;
351
352      case IPR_DTB_CM:
353#if FULL_SYSTEM
354        if (val & 0x18) {
355            if (tc->getKernelStats())
356                tc->getKernelStats()->mode(Kernel::user, tc);
357        } else {
358            if (tc->getKernelStats())
359                tc->getKernelStats()->mode(Kernel::kernel, tc);
360        }
361#endif
362
363      case IPR_ICM:
364        // only write two mode bits - processor mode
365        ipr[idx] = val & 0x18;
366        break;
367
368      case IPR_ALT_MODE:
369        // only write two mode bits - processor mode
370        ipr[idx] = val & 0x18;
371        break;
372
373      case IPR_MCSR:
374        // more here after optimization...
375        ipr[idx] = val;
376        break;
377
378      case IPR_SIRR:
379        // only write software interrupt mask
380        ipr[idx] = val & 0x7fff0;
381        break;
382
383      case IPR_ICSR:
384        ipr[idx] = val & ULL(0xffffff0300);
385        break;
386
387      case IPR_IVPTBR:
388      case IPR_MVPTBR:
389        ipr[idx] = val & ULL(0xffffffffc0000000);
390        break;
391
392      case IPR_DC_TEST_CTL:
393        ipr[idx] = val & 0x1ffb;
394        break;
395
396      case IPR_DC_MODE:
397      case IPR_MAF_MODE:
398        ipr[idx] = val & 0x3f;
399        break;
400
401      case IPR_ITB_ASN:
402        ipr[idx] = val & 0x7f0;
403        break;
404
405      case IPR_DTB_ASN:
406        ipr[idx] = val & ULL(0xfe00000000000000);
407        break;
408
409      case IPR_EXC_SUM:
410      case IPR_EXC_MASK:
411        // any write to this register clears it
412        ipr[idx] = 0;
413        break;
414
415      case IPR_INTID:
416      case IPR_SL_RCV:
417      case IPR_MM_STAT:
418      case IPR_ITB_PTE_TEMP:
419      case IPR_DTB_PTE_TEMP:
420        // read-only registers
421        panic("Tried to write read only ipr %d\n", idx);
422
423      case IPR_HWINT_CLR:
424      case IPR_SL_XMIT:
425      case IPR_DC_FLUSH:
426      case IPR_IC_FLUSH:
427        // the following are write only
428        ipr[idx] = val;
429        break;
430
431      case IPR_DTB_IA:
432        // really a control write
433        ipr[idx] = 0;
434
435        tc->getDTBPtr()->flushAll();
436        break;
437
438      case IPR_DTB_IAP:
439        // really a control write
440        ipr[idx] = 0;
441
442        tc->getDTBPtr()->flushProcesses();
443        break;
444
445      case IPR_DTB_IS:
446        // really a control write
447        ipr[idx] = val;
448
449        tc->getDTBPtr()->flushAddr(val, DTB_ASN_ASN(ipr[IPR_DTB_ASN]));
450        break;
451
452      case IPR_DTB_TAG: {
453          struct TlbEntry entry;
454
455          // FIXME: granularity hints NYI...
456          if (DTB_PTE_GH(ipr[IPR_DTB_PTE]) != 0)
457              panic("PTE GH field != 0");
458
459          // write entire quad
460          ipr[idx] = val;
461
462          // construct PTE for new entry
463          entry.ppn = DTB_PTE_PPN(ipr[IPR_DTB_PTE]);
464          entry.xre = DTB_PTE_XRE(ipr[IPR_DTB_PTE]);
465          entry.xwe = DTB_PTE_XWE(ipr[IPR_DTB_PTE]);
466          entry.fonr = DTB_PTE_FONR(ipr[IPR_DTB_PTE]);
467          entry.fonw = DTB_PTE_FONW(ipr[IPR_DTB_PTE]);
468          entry.asma = DTB_PTE_ASMA(ipr[IPR_DTB_PTE]);
469          entry.asn = DTB_ASN_ASN(ipr[IPR_DTB_ASN]);
470
471          // insert new TAG/PTE value into data TLB
472          tc->getDTBPtr()->insert(val, entry);
473      }
474        break;
475
476      case IPR_ITB_PTE: {
477          struct TlbEntry entry;
478
479          // FIXME: granularity hints NYI...
480          if (ITB_PTE_GH(val) != 0)
481              panic("PTE GH field != 0");
482
483          // write entire quad
484          ipr[idx] = val;
485
486          // construct PTE for new entry
487          entry.ppn = ITB_PTE_PPN(val);
488          entry.xre = ITB_PTE_XRE(val);
489          entry.xwe = 0;
490          entry.fonr = ITB_PTE_FONR(val);
491          entry.fonw = ITB_PTE_FONW(val);
492          entry.asma = ITB_PTE_ASMA(val);
493          entry.asn = ITB_ASN_ASN(ipr[IPR_ITB_ASN]);
494
495          // insert new TAG/PTE value into data TLB
496          tc->getITBPtr()->insert(ipr[IPR_ITB_TAG], entry);
497      }
498        break;
499
500      case IPR_ITB_IA:
501        // really a control write
502        ipr[idx] = 0;
503
504        tc->getITBPtr()->flushAll();
505        break;
506
507      case IPR_ITB_IAP:
508        // really a control write
509        ipr[idx] = 0;
510
511        tc->getITBPtr()->flushProcesses();
512        break;
513
514      case IPR_ITB_IS:
515        // really a control write
516        ipr[idx] = val;
517
518        tc->getITBPtr()->flushAddr(val, ITB_ASN_ASN(ipr[IPR_ITB_ASN]));
519        break;
520
521      default:
522        // invalid IPR
523        panic("Tried to write to invalid ipr %d\n", idx);
524    }
525
526    // no error...
527}
528
529void
530copyIprs(ThreadContext *src, ThreadContext *dest)
531{
532    for (int i = 0; i < NumInternalProcRegs; ++i)
533        dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
534}
535
536} // namespace AlphaISA
537
538#if FULL_SYSTEM
539
540using namespace AlphaISA;
541
542Fault
543SimpleThread::hwrei()
544{
545    if (!(readPC() & 0x3))
546        return new UnimplementedOpcodeFault;
547
548    setNextPC(readMiscRegNoEffect(IPR_EXC_ADDR));
549
550    CPA::cpa()->swAutoBegin(tc, readNextPC());
551
552    if (!misspeculating()) {
553        if (kernelStats)
554            kernelStats->hwrei();
555    }
556
557    // FIXME: XXX check for interrupts? XXX
558    return NoFault;
559}
560
561/**
562 * Check for special simulator handling of specific PAL calls.
563 * If return value is false, actual PAL call will be suppressed.
564 */
565bool
566SimpleThread::simPalCheck(int palFunc)
567{
568    if (kernelStats)
569        kernelStats->callpal(palFunc, tc);
570
571    switch (palFunc) {
572      case PAL::halt:
573        halt();
574        if (--System::numSystemsRunning == 0)
575            exitSimLoop("all cpus halted");
576        break;
577
578      case PAL::bpt:
579      case PAL::bugchk:
580        if (system->breakpoint())
581            return false;
582        break;
583    }
584
585    return true;
586}
587
588#endif // FULL_SYSTEM
589