ua2005.cc revision 4103
12623SN/A/*
22623SN/A * Copyright (c) 2006 The Regents of The University of Michigan
32623SN/A * All rights reserved.
42623SN/A *
52623SN/A * Redistribution and use in source and binary forms, with or without
62623SN/A * modification, are permitted provided that the following conditions are
72623SN/A * met: redistributions of source code must retain the above copyright
82623SN/A * notice, this list of conditions and the following disclaimer;
92623SN/A * redistributions in binary form must reproduce the above copyright
102623SN/A * notice, this list of conditions and the following disclaimer in the
112623SN/A * documentation and/or other materials provided with the distribution;
122623SN/A * neither the name of the copyright holders nor the names of its
132623SN/A * contributors may be used to endorse or promote products derived from
142623SN/A * this software without specific prior written permission.
152623SN/A *
162623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu */
282665Ssaidi@eecs.umich.edu
292623SN/A#include "arch/sparc/miscregfile.hh"
302623SN/A#include "base/bitfield.hh"
312623SN/A#include "base/trace.hh"
322623SN/A#include "cpu/base.hh"
332623SN/A#include "cpu/thread_context.hh"
342623SN/A
352623SN/Ausing namespace SparcISA;
362623SN/A
372623SN/A
382623SN/Avoid
392623SN/AMiscRegFile::checkSoftInt(ThreadContext *tc)
402623SN/A{
412623SN/A    // If PIL < 14, copy over the tm and sm bits
422623SN/A    if (pil < 14 && softint & 0x10000)
432623SN/A        tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,16);
442623SN/A    else
452623SN/A        tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,16);
462623SN/A    if (pil < 14 && softint & 0x1)
472623SN/A        tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,0);
482623SN/A    else
492623SN/A        tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,0);
502623SN/A
512623SN/A    // Copy over any of the other bits that are set
522623SN/A    for (int bit = 15; bit > 0; --bit) {
532623SN/A        if (1 << bit & softint && bit > pil)
542623SN/A            tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,bit);
552623SN/A        else
562623SN/A            tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,bit);
572623SN/A    }
582623SN/A}
592623SN/A
602623SN/A
612623SN/Avoid
622623SN/AMiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
632623SN/A                                ThreadContext *tc)
642623SN/A{
652623SN/A    int64_t time;
662623SN/A    switch (miscReg) {
672839Sktlim@umich.edu        /* Full system only ASRs */
682798Sktlim@umich.edu      case MISCREG_SOFTINT:
692867Sktlim@umich.edu        setReg(miscReg, val);;
702867Sktlim@umich.edu        checkSoftInt(tc);
712623SN/A        break;
722623SN/A      case MISCREG_SOFTINT_CLR:
732623SN/A        return setRegWithEffect(MISCREG_SOFTINT, ~val & softint, tc);
742623SN/A      case MISCREG_SOFTINT_SET:
752623SN/A        return setRegWithEffect(MISCREG_SOFTINT, val | softint, tc);
762623SN/A
772948Ssaidi@eecs.umich.edu      case MISCREG_TICK_CMPR:
782623SN/A        if (tickCompare == NULL)
792623SN/A            tickCompare = new TickCompareEvent(this, tc);
802623SN/A        setReg(miscReg, val);
812948Ssaidi@eecs.umich.edu        if ((tick_cmpr & ~mask(63)) && tickCompare->scheduled())
823401Sktlim@umich.edu            tickCompare->deschedule();
832623SN/A        time = (tick_cmpr & mask(63)) - (tick & mask(63));
842623SN/A        if (!(tick_cmpr & ~mask(63)) && time > 0) {
852623SN/A            if (tickCompare->scheduled())
862623SN/A                tickCompare->deschedule();
873349Sbinkertn@umich.edu            tickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
882623SN/A        }
893349Sbinkertn@umich.edu        panic("writing to TICK compare register %#X\n", val);
902623SN/A        break;
912623SN/A
922623SN/A      case MISCREG_STICK_CMPR:
932623SN/A        if (sTickCompare == NULL)
942623SN/A            sTickCompare = new STickCompareEvent(this, tc);
953192Srdreslin@umich.edu        setReg(miscReg, val);
962948Ssaidi@eecs.umich.edu        if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
972948Ssaidi@eecs.umich.edu            sTickCompare->deschedule();
982948Ssaidi@eecs.umich.edu        time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
993349Sbinkertn@umich.edu            tc->getCpuPtr()->instCount();
1002948Ssaidi@eecs.umich.edu        if (!(stick_cmpr & ~mask(63)) && time > 0) {
1012948Ssaidi@eecs.umich.edu            if (sTickCompare->scheduled())
1022948Ssaidi@eecs.umich.edu                sTickCompare->deschedule();
1032948Ssaidi@eecs.umich.edu            sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1) + curTick);
1042948Ssaidi@eecs.umich.edu        }
1053349Sbinkertn@umich.edu        DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val);
1062948Ssaidi@eecs.umich.edu        break;
1072948Ssaidi@eecs.umich.edu
1082623SN/A      case MISCREG_PSTATE:
1092623SN/A        setReg(miscReg, val);
1102623SN/A
1112623SN/A      case MISCREG_PIL:
1122623SN/A        setReg(miscReg, val);
1132623SN/A        checkSoftInt(tc);
1142948Ssaidi@eecs.umich.edu        break;
1152948Ssaidi@eecs.umich.edu
1162623SN/A      case MISCREG_HVER:
1172623SN/A        panic("Shouldn't be writing HVER\n");
1182623SN/A
1192623SN/A      case MISCREG_HINTP:
1203349Sbinkertn@umich.edu        setReg(miscReg, val);
1212623SN/A        if (hintp)
1222657Ssaidi@eecs.umich.edu            tc->getCpuPtr()->post_interrupt(IT_HINTP,0);
1232948Ssaidi@eecs.umich.edu        else
1242948Ssaidi@eecs.umich.edu            tc->getCpuPtr()->clear_interrupt(IT_HINTP,0);
1252948Ssaidi@eecs.umich.edu        break;
1262948Ssaidi@eecs.umich.edu
1272948Ssaidi@eecs.umich.edu      case MISCREG_HTBA:
1282948Ssaidi@eecs.umich.edu        // clear lower 7 bits on writes.
1292948Ssaidi@eecs.umich.edu        setReg(miscReg, val & ULL(~0x7FFF));
1302948Ssaidi@eecs.umich.edu        break;
1312948Ssaidi@eecs.umich.edu
1322948Ssaidi@eecs.umich.edu      case MISCREG_QUEUE_CPU_MONDO_HEAD:
1332948Ssaidi@eecs.umich.edu      case MISCREG_QUEUE_CPU_MONDO_TAIL:
1342948Ssaidi@eecs.umich.edu        setReg(miscReg, val);
1352623SN/A        if (cpu_mondo_head != cpu_mondo_tail)
1362623SN/A            tc->getCpuPtr()->post_interrupt(IT_CPU_MONDO,0);
1372623SN/A        else
1382623SN/A            tc->getCpuPtr()->clear_interrupt(IT_CPU_MONDO,0);
1392623SN/A        break;
1402623SN/A      case MISCREG_QUEUE_DEV_MONDO_HEAD:
1412948Ssaidi@eecs.umich.edu      case MISCREG_QUEUE_DEV_MONDO_TAIL:
1422948Ssaidi@eecs.umich.edu        setReg(miscReg, val);
1432623SN/A        if (dev_mondo_head != dev_mondo_tail)
1442623SN/A            tc->getCpuPtr()->post_interrupt(IT_DEV_MONDO,0);
1452623SN/A        else
1462623SN/A            tc->getCpuPtr()->clear_interrupt(IT_DEV_MONDO,0);
1473349Sbinkertn@umich.edu        break;
1482623SN/A      case MISCREG_QUEUE_RES_ERROR_HEAD:
1492657Ssaidi@eecs.umich.edu      case MISCREG_QUEUE_RES_ERROR_TAIL:
1502948Ssaidi@eecs.umich.edu        setReg(miscReg, val);
1512948Ssaidi@eecs.umich.edu        if (res_error_head != res_error_tail)
1522948Ssaidi@eecs.umich.edu            tc->getCpuPtr()->post_interrupt(IT_RES_ERROR,0);
1532948Ssaidi@eecs.umich.edu        else
1542948Ssaidi@eecs.umich.edu            tc->getCpuPtr()->clear_interrupt(IT_RES_ERROR,0);
1552948Ssaidi@eecs.umich.edu        break;
1562948Ssaidi@eecs.umich.edu      case MISCREG_QUEUE_NRES_ERROR_HEAD:
1572948Ssaidi@eecs.umich.edu      case MISCREG_QUEUE_NRES_ERROR_TAIL:
1582948Ssaidi@eecs.umich.edu        setReg(miscReg, val);
1592948Ssaidi@eecs.umich.edu        // This one doesn't have an interrupt to report to the guest OS
1602948Ssaidi@eecs.umich.edu        break;
1612623SN/A
1622623SN/A      case MISCREG_HSTICK_CMPR:
1632623SN/A        if (hSTickCompare == NULL)
1642623SN/A            hSTickCompare = new HSTickCompareEvent(this, tc);
1652623SN/A        setReg(miscReg, val);
1663349Sbinkertn@umich.edu        if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled())
1673349Sbinkertn@umich.edu            hSTickCompare->deschedule();
1682623SN/A        time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
1693401Sktlim@umich.edu            tc->getCpuPtr()->instCount();
1703401Sktlim@umich.edu        if (!(hstick_cmpr & ~mask(63)) && time > 0) {
1713170Sstever@eecs.umich.edu            if (hSTickCompare->scheduled())
1723222Sktlim@umich.edu                hSTickCompare->deschedule();
1733170Sstever@eecs.umich.edu            hSTickCompare->schedule(curTick + time * tc->getCpuPtr()->cycles(1));
1742623SN/A        }
1752623SN/A        DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val);
1762856Srdreslin@umich.edu        break;
1772856Srdreslin@umich.edu
1782623SN/A      case MISCREG_HPSTATE:
1792623SN/A        // T1000 spec says impl. dependent val must always be 1
1802623SN/A        setReg(miscReg, val | HPSTATE::id);
1812901Ssaidi@eecs.umich.edu#if FULL_SYSTEM
1822798Sktlim@umich.edu        if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv))
1832798Sktlim@umich.edu            tc->getCpuPtr()->post_interrupt(IT_TRAP_LEVEL_ZERO,0);
1842798Sktlim@umich.edu        else
1852623SN/A            tc->getCpuPtr()->clear_interrupt(IT_TRAP_LEVEL_ZERO,0);
1862623SN/A#endif
1872623SN/A        break;
1882623SN/A      case MISCREG_HTSTATE:
1892623SN/A      case MISCREG_STRAND_STS_REG:
1902623SN/A        setReg(miscReg, val);
1912623SN/A        break;
1922623SN/A
1932623SN/A      default:
1942623SN/A        panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg));
1952623SN/A    }
1962623SN/A}
1973349Sbinkertn@umich.edu
1983349Sbinkertn@umich.eduMiscReg
1992644Sstever@eecs.umich.eduMiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc)
2002798Sktlim@umich.edu{
2012839Sktlim@umich.edu    switch (miscReg) {
2022623SN/A        /* Privileged registers. */
2032623SN/A      case MISCREG_QUEUE_CPU_MONDO_HEAD:
2042623SN/A      case MISCREG_QUEUE_CPU_MONDO_TAIL:
205      case MISCREG_QUEUE_DEV_MONDO_HEAD:
206      case MISCREG_QUEUE_DEV_MONDO_TAIL:
207      case MISCREG_QUEUE_RES_ERROR_HEAD:
208      case MISCREG_QUEUE_RES_ERROR_TAIL:
209      case MISCREG_QUEUE_NRES_ERROR_HEAD:
210      case MISCREG_QUEUE_NRES_ERROR_TAIL:
211      case MISCREG_SOFTINT:
212      case MISCREG_TICK_CMPR:
213      case MISCREG_STICK_CMPR:
214      case MISCREG_PIL:
215      case MISCREG_HPSTATE:
216      case MISCREG_HINTP:
217      case MISCREG_HTSTATE:
218      case MISCREG_STRAND_STS_REG:
219      case MISCREG_HSTICK_CMPR:
220        return readReg(miscReg) ;
221
222      case MISCREG_HTBA:
223        return readReg(miscReg) & ULL(~0x7FFF);
224      case MISCREG_HVER:
225        return NWindows | MaxTL << 8 | MaxGL << 16;
226
227      default:
228        panic("Invalid read to FS misc register\n");
229    }
230}
231/*
232  In Niagra STICK==TICK so this isn't needed
233  case MISCREG_STICK:
234  SparcSystem *sys;
235  sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
236  assert(sys != NULL);
237  return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63)));
238*/
239
240
241
242void
243MiscRegFile::processTickCompare(ThreadContext *tc)
244{
245    panic("tick compare not implemented\n");
246}
247
248void
249MiscRegFile::processSTickCompare(ThreadContext *tc)
250{
251    // since our microcode instructions take two cycles we need to check if
252    // we're actually at the correct cycle or we need to wait a little while
253    // more
254    int ticks;
255    ticks = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
256        tc->getCpuPtr()->instCount();
257    assert(ticks >= 0 && "stick compare missed interrupt cycle");
258
259    if (ticks == 0) {
260        DPRINTF(Timer, "STick compare cycle reached at %#x\n",
261                (stick_cmpr & mask(63)));
262        if (!(tc->readMiscReg(MISCREG_STICK_CMPR) & (ULL(1) << 63))) {
263            setRegWithEffect(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc);
264        }
265    } else
266        sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick);
267}
268
269void
270MiscRegFile::processHSTickCompare(ThreadContext *tc)
271{
272    // since our microcode instructions take two cycles we need to check if
273    // we're actually at the correct cycle or we need to wait a little while
274    // more
275    int ticks;
276    ticks = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
277        tc->getCpuPtr()->instCount();
278    assert(ticks >= 0 && "hstick compare missed interrupt cycle");
279
280    if (ticks == 0) {
281        DPRINTF(Timer, "HSTick compare cycle reached at %#x\n",
282                (stick_cmpr & mask(63)));
283        if (!(tc->readMiscReg(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) {
284            setRegWithEffect(MISCREG_HINTP, 1, tc);
285        }
286        // Need to do something to cause interrupt to happen here !!! @todo
287    } else
288        hSTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick);
289}
290
291