interrupts.hh revision 8232
11689SN/A/*
21689SN/A * Copyright (c) 2006 The Regents of The University of Michigan
31689SN/A * All rights reserved.
41689SN/A *
51689SN/A * Redistribution and use in source and binary forms, with or without
61689SN/A * modification, are permitted provided that the following conditions are
71689SN/A * met: redistributions of source code must retain the above copyright
81689SN/A * notice, this list of conditions and the following disclaimer;
91689SN/A * redistributions in binary form must reproduce the above copyright
101689SN/A * notice, this list of conditions and the following disclaimer in the
111689SN/A * documentation and/or other materials provided with the distribution;
121689SN/A * neither the name of the copyright holders nor the names of its
131689SN/A * contributors may be used to endorse or promote products derived from
141689SN/A * this software without specific prior written permission.
151689SN/A *
161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt
291689SN/A *          Kevin Lim
301689SN/A */
311060SN/A
321061SN/A#ifndef __ARCH_ALPHA_INTERRUPT_HH__
331061SN/A#define __ARCH_ALPHA_INTERRUPT_HH__
341061SN/A
351060SN/A#include "arch/alpha/faults.hh"
361755SN/A#include "arch/alpha/isa_traits.hh"
371755SN/A#include "base/compiler.hh"
381060SN/A#include "base/trace.hh"
391060SN/A#include "cpu/thread_context.hh"
401060SN/A#include "debug/Flow.hh"
411461SN/A#include "debug/Interrupt.hh"
421060SN/A#include "params/AlphaInterrupts.hh"
431060SN/A#include "sim/sim_object.hh"
441060SN/A
451060SN/Anamespace AlphaISA {
461060SN/A
471060SN/Aclass Interrupts : public SimObject
481060SN/A{
491060SN/A  private:
501060SN/A    bool newInfoSet;
511060SN/A    int newIpl;
521061SN/A    int newSummary;
531060SN/A    BaseCPU * cpu;
541060SN/A
551060SN/A  protected:
561061SN/A    uint64_t interrupts[NumInterruptLevels];
571061SN/A    uint64_t intstatus;
581061SN/A
591061SN/A  public:
601060SN/A    typedef AlphaInterruptsParams Params;
611060SN/A
621060SN/A    const Params *
631060SN/A    params() const
641060SN/A    {
651060SN/A        return dynamic_cast<const Params *>(_params);
662107SN/A    }
671060SN/A
681060SN/A    Interrupts(Params * p) : SimObject(p), cpu(NULL)
691060SN/A    {
701060SN/A        memset(interrupts, 0, sizeof(interrupts));
711060SN/A        intstatus = 0;
721060SN/A        newInfoSet = false;
731060SN/A    }
741060SN/A
751060SN/A    void
761060SN/A    setCPU(BaseCPU * _cpu)
771060SN/A    {
781060SN/A        cpu = _cpu;
791060SN/A    }
801060SN/A
811060SN/A    void
821060SN/A    post(int int_num, int index)
831060SN/A    {
841060SN/A        DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
851060SN/A
861060SN/A        if (int_num < 0 || int_num >= NumInterruptLevels)
871062SN/A            panic("int_num out of bounds\n");
881062SN/A
891060SN/A        if (index < 0 || index >= (int)sizeof(uint64_t) * 8)
901060SN/A            panic("int_num out of bounds\n");
911060SN/A
921060SN/A        interrupts[int_num] |= 1 << index;
931060SN/A        intstatus |= (ULL(1) << int_num);
941060SN/A    }
951060SN/A
961060SN/A    void
971060SN/A    clear(int int_num, int index)
981060SN/A    {
991060SN/A        DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
1001060SN/A
1011060SN/A        if (int_num < 0 || int_num >= NumInterruptLevels)
1021060SN/A            panic("int_num out of bounds\n");
1031060SN/A
1041060SN/A        if (index < 0 || index >= (int)sizeof(uint64_t) * 8)
1051060SN/A            panic("int_num out of bounds\n");
1061060SN/A
1071060SN/A        interrupts[int_num] &= ~(1 << index);
1081060SN/A        if (interrupts[int_num] == 0)
1091060SN/A            intstatus &= ~(ULL(1) << int_num);
1101060SN/A    }
1111060SN/A
1121060SN/A    void
1131060SN/A    clearAll()
1141060SN/A    {
1151060SN/A        DPRINTF(Interrupt, "Interrupts all cleared\n");
1161060SN/A
1171060SN/A        memset(interrupts, 0, sizeof(interrupts));
1181061SN/A        intstatus = 0;
1191061SN/A    }
1201061SN/A
1211061SN/A    void
1221061SN/A    serialize(std::ostream &os)
1231061SN/A    {
1241061SN/A        SERIALIZE_ARRAY(interrupts, NumInterruptLevels);
1251061SN/A        SERIALIZE_SCALAR(intstatus);
1261060SN/A    }
1271060SN/A
1281060SN/A    void
1291060SN/A    unserialize(Checkpoint *cp, const std::string &section)
1301060SN/A    {
1311060SN/A        UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
1321060SN/A        UNSERIALIZE_SCALAR(intstatus);
1331060SN/A    }
1341060SN/A
1351060SN/A    bool
1361060SN/A    checkInterrupts(ThreadContext *tc) const
1371060SN/A    {
1381060SN/A        return (intstatus != 0) && !(tc->pcState().pc() & 0x3);
1391060SN/A    }
1401060SN/A
1411060SN/A    Fault
1421060SN/A    getInterrupt(ThreadContext *tc)
1431060SN/A    {
1441060SN/A        uint64_t ipl = 0;
1451060SN/A        uint64_t summary = 0;
1461060SN/A
1471060SN/A        if (tc->readMiscRegNoEffect(IPR_ASTRR))
1481060SN/A            panic("asynchronous traps not implemented\n");
1491060SN/A
1501060SN/A        if (tc->readMiscRegNoEffect(IPR_SIRR)) {
1511060SN/A            for (uint64_t i = INTLEVEL_SOFTWARE_MIN;
1521060SN/A                 i < INTLEVEL_SOFTWARE_MAX; i++) {
1531060SN/A                if (tc->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) {
1541060SN/A                    // See table 4-19 of 21164 hardware reference
1551061SN/A                    ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
1561060SN/A                    summary |= (ULL(1) << i);
1571060SN/A                }
1581060SN/A            }
1591060SN/A        }
1601060SN/A
1611060SN/A        uint64_t interrupts = intstatus;
1621060SN/A        if (interrupts) {
1631060SN/A            for (uint64_t i = INTLEVEL_EXTERNAL_MIN;
1641060SN/A                 i < INTLEVEL_EXTERNAL_MAX; i++) {
1651060SN/A                if (interrupts & (ULL(1) << i)) {
1661060SN/A                    // See table 4-19 of 21164 hardware reference
1671060SN/A                    ipl = i;
1681060SN/A                    summary |= (ULL(1) << i);
1691060SN/A                }
1701060SN/A            }
1711060SN/A        }
1721060SN/A
1731060SN/A        if (ipl && ipl > tc->readMiscRegNoEffect(IPR_IPLR)) {
1741060SN/A            newIpl = ipl;
1751060SN/A            newSummary = summary;
1761060SN/A            newInfoSet = true;
1771060SN/A            DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
1781060SN/A                    tc->readMiscRegNoEffect(IPR_IPLR), ipl, summary);
1791060SN/A
1801060SN/A            return new InterruptFault;
1811060SN/A        } else {
1821060SN/A            return NoFault;
1831060SN/A        }
1841060SN/A    }
1851060SN/A
1861060SN/A    void
1871061SN/A    updateIntrInfo(ThreadContext *tc)
1881060SN/A    {
1891060SN/A        assert(newInfoSet);
1901060SN/A        tc->setMiscRegNoEffect(IPR_ISR, newSummary);
1911060SN/A        tc->setMiscRegNoEffect(IPR_INTID, newIpl);
1921060SN/A        newInfoSet = false;
1931060SN/A    }
1941060SN/A};
1951060SN/A
1961060SN/A} // namespace AlphaISA
1971060SN/A
1981060SN/A#endif // __ARCH_ALPHA_INTERRUPT_HH__
1991060SN/A
2001060SN/A