13537Sgblack@eecs.umich.edu/*
23537Sgblack@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan
33537Sgblack@eecs.umich.edu * All rights reserved.
43537Sgblack@eecs.umich.edu *
53537Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
63537Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
73537Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
83537Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
93537Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
103537Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
113537Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
123537Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
133537Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
143537Sgblack@eecs.umich.edu * this software without specific prior written permission.
153537Sgblack@eecs.umich.edu *
163537Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173537Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183537Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193537Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203537Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213537Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223537Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233537Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243537Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253537Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263537Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274103Ssaidi@eecs.umich.edu *
284103Ssaidi@eecs.umich.edu * Authors: Ali Saidi
294103Ssaidi@eecs.umich.edu *          Lisa Hsu
303537Sgblack@eecs.umich.edu */
313537Sgblack@eecs.umich.edu
323537Sgblack@eecs.umich.edu#ifndef __ARCH_SPARC_INTERRUPT_HH__
333537Sgblack@eecs.umich.edu#define __ARCH_SPARC_INTERRUPT_HH__
343537Sgblack@eecs.umich.edu
353537Sgblack@eecs.umich.edu#include "arch/sparc/faults.hh"
364103Ssaidi@eecs.umich.edu#include "arch/sparc/isa_traits.hh"
376335Sgblack@eecs.umich.edu#include "arch/sparc/registers.hh"
383827Shsul@eecs.umich.edu#include "cpu/thread_context.hh"
398232Snate@binkert.org#include "debug/Interrupt.hh"
405647Sgblack@eecs.umich.edu#include "params/SparcInterrupts.hh"
415647Sgblack@eecs.umich.edu#include "sim/sim_object.hh"
423827Shsul@eecs.umich.edu
433537Sgblack@eecs.umich.edunamespace SparcISA
443537Sgblack@eecs.umich.edu{
453894Shsul@eecs.umich.edu
4613912Sgabeblack@google.comenum InterruptTypes
4713912Sgabeblack@google.com{
4813912Sgabeblack@google.com    IT_TRAP_LEVEL_ZERO,
4913912Sgabeblack@google.com    IT_HINTP,
5013912Sgabeblack@google.com    IT_INT_VEC,
5113912Sgabeblack@google.com    IT_CPU_MONDO,
5213912Sgabeblack@google.com    IT_DEV_MONDO,
5313912Sgabeblack@google.com    IT_RES_ERROR,
5413912Sgabeblack@google.com    IT_SOFT_INT,
5513912Sgabeblack@google.com    NumInterruptTypes
5613912Sgabeblack@google.com};
5713912Sgabeblack@google.com
585647Sgblack@eecs.umich.educlass Interrupts : public SimObject
594009Ssaidi@eecs.umich.edu{
605810Sgblack@eecs.umich.edu  private:
615810Sgblack@eecs.umich.edu    BaseCPU * cpu;
624009Ssaidi@eecs.umich.edu
634103Ssaidi@eecs.umich.edu    uint64_t interrupts[NumInterruptTypes];
644103Ssaidi@eecs.umich.edu    uint64_t intStatus;
654009Ssaidi@eecs.umich.edu
664009Ssaidi@eecs.umich.edu  public:
675810Sgblack@eecs.umich.edu
685810Sgblack@eecs.umich.edu    void
695810Sgblack@eecs.umich.edu    setCPU(BaseCPU * _cpu)
705810Sgblack@eecs.umich.edu    {
715810Sgblack@eecs.umich.edu        cpu = _cpu;
725810Sgblack@eecs.umich.edu    }
735810Sgblack@eecs.umich.edu
745647Sgblack@eecs.umich.edu    typedef SparcInterruptsParams Params;
755647Sgblack@eecs.umich.edu
765647Sgblack@eecs.umich.edu    const Params *
775647Sgblack@eecs.umich.edu    params() const
785647Sgblack@eecs.umich.edu    {
795647Sgblack@eecs.umich.edu        return dynamic_cast<const Params *>(_params);
805647Sgblack@eecs.umich.edu    }
815647Sgblack@eecs.umich.edu
825810Sgblack@eecs.umich.edu    Interrupts(Params * p) : SimObject(p), cpu(NULL)
834009Ssaidi@eecs.umich.edu    {
845704Snate@binkert.org        clearAll();
854009Ssaidi@eecs.umich.edu    }
864009Ssaidi@eecs.umich.edu
875704Snate@binkert.org    int
885704Snate@binkert.org    InterruptLevel(uint64_t softint)
894009Ssaidi@eecs.umich.edu    {
904103Ssaidi@eecs.umich.edu        if (softint & 0x10000 || softint & 0x1)
914103Ssaidi@eecs.umich.edu            return 14;
924103Ssaidi@eecs.umich.edu
934103Ssaidi@eecs.umich.edu        int level = 15;
944103Ssaidi@eecs.umich.edu        while (level > 0 && !(1 << level & softint))
954103Ssaidi@eecs.umich.edu            level--;
964103Ssaidi@eecs.umich.edu        if (1 << level & softint)
974103Ssaidi@eecs.umich.edu            return level;
984103Ssaidi@eecs.umich.edu        return 0;
994009Ssaidi@eecs.umich.edu    }
1004009Ssaidi@eecs.umich.edu
1015704Snate@binkert.org    void
1025704Snate@binkert.org    post(int int_num, int index)
1033537Sgblack@eecs.umich.edu    {
1044103Ssaidi@eecs.umich.edu        DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
1054103Ssaidi@eecs.umich.edu        assert(int_num >= 0 && int_num < NumInterruptTypes);
1064103Ssaidi@eecs.umich.edu        assert(index >= 0 && index < 64);
1073827Shsul@eecs.umich.edu
1084103Ssaidi@eecs.umich.edu        interrupts[int_num] |= ULL(1) << index;
1094103Ssaidi@eecs.umich.edu        intStatus |= ULL(1) << int_num;
1104009Ssaidi@eecs.umich.edu    }
1113894Shsul@eecs.umich.edu
1125704Snate@binkert.org    void
1135704Snate@binkert.org    clear(int int_num, int index)
1144009Ssaidi@eecs.umich.edu    {
1154103Ssaidi@eecs.umich.edu        DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
1164103Ssaidi@eecs.umich.edu        assert(int_num >= 0 && int_num < NumInterruptTypes);
1174103Ssaidi@eecs.umich.edu        assert(index >= 0 && index < 64);
1183537Sgblack@eecs.umich.edu
1194103Ssaidi@eecs.umich.edu        interrupts[int_num] &= ~(ULL(1) << index);
1204103Ssaidi@eecs.umich.edu        if (!interrupts[int_num])
1214103Ssaidi@eecs.umich.edu            intStatus &= ~(ULL(1) << int_num);
1224009Ssaidi@eecs.umich.edu    }
1233827Shsul@eecs.umich.edu
1245704Snate@binkert.org    void
1255704Snate@binkert.org    clearAll()
1264009Ssaidi@eecs.umich.edu    {
1274103Ssaidi@eecs.umich.edu        for (int i = 0; i < NumInterruptTypes; ++i) {
1284103Ssaidi@eecs.umich.edu            interrupts[i] = 0;
1294103Ssaidi@eecs.umich.edu        }
1304103Ssaidi@eecs.umich.edu        intStatus = 0;
1314009Ssaidi@eecs.umich.edu    }
1323537Sgblack@eecs.umich.edu
1335704Snate@binkert.org    bool
1345704Snate@binkert.org    checkInterrupts(ThreadContext *tc) const
1354009Ssaidi@eecs.umich.edu    {
13611566Smitch.hayenga@arm.com        if (!intStatus)
13711566Smitch.hayenga@arm.com            return false;
13811566Smitch.hayenga@arm.com
13911566Smitch.hayenga@arm.com        HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
14011566Smitch.hayenga@arm.com        PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
14111566Smitch.hayenga@arm.com
14211566Smitch.hayenga@arm.com        // THESE ARE IN ORDER OF PRIORITY
14311566Smitch.hayenga@arm.com        // since there are early returns, and the highest
14411566Smitch.hayenga@arm.com        // priority interrupts should get serviced,
14511566Smitch.hayenga@arm.com        // it is v. important that new interrupts are inserted
14611566Smitch.hayenga@arm.com        // in the right order of processing
14711566Smitch.hayenga@arm.com        if (hpstate.hpriv) {
14811566Smitch.hayenga@arm.com            if (pstate.ie) {
14911566Smitch.hayenga@arm.com                if (interrupts[IT_HINTP]) {
15011566Smitch.hayenga@arm.com                    // This will be cleaned by a HINTP write
15111566Smitch.hayenga@arm.com                    return true;
15211566Smitch.hayenga@arm.com                }
15311566Smitch.hayenga@arm.com                if (interrupts[IT_INT_VEC]) {
15411566Smitch.hayenga@arm.com                    // this will be cleared by an ASI read (or write)
15511566Smitch.hayenga@arm.com                    return true;
15611566Smitch.hayenga@arm.com                }
15711566Smitch.hayenga@arm.com            }
15811566Smitch.hayenga@arm.com        } else {
15911566Smitch.hayenga@arm.com            if (interrupts[IT_TRAP_LEVEL_ZERO]) {
16011566Smitch.hayenga@arm.com                    // this is cleared by deasserting HPSTATE::tlz
16111566Smitch.hayenga@arm.com                return true;
16211566Smitch.hayenga@arm.com            }
16311566Smitch.hayenga@arm.com            // HStick matches always happen in priv mode (ie doesn't matter)
16411566Smitch.hayenga@arm.com            if (interrupts[IT_HINTP]) {
16511566Smitch.hayenga@arm.com                return true;
16611566Smitch.hayenga@arm.com            }
16711566Smitch.hayenga@arm.com            if (interrupts[IT_INT_VEC]) {
16811566Smitch.hayenga@arm.com                // this will be cleared by an ASI read (or write)
16911566Smitch.hayenga@arm.com                return true;
17011566Smitch.hayenga@arm.com            }
17111566Smitch.hayenga@arm.com            if (pstate.ie) {
17211566Smitch.hayenga@arm.com                if (interrupts[IT_CPU_MONDO]) {
17311566Smitch.hayenga@arm.com                    return true;
17411566Smitch.hayenga@arm.com                }
17511566Smitch.hayenga@arm.com                if (interrupts[IT_DEV_MONDO]) {
17611566Smitch.hayenga@arm.com                    return true;
17711566Smitch.hayenga@arm.com                }
17811566Smitch.hayenga@arm.com                if (interrupts[IT_SOFT_INT]) {
17911566Smitch.hayenga@arm.com                    return true;
18011566Smitch.hayenga@arm.com                }
18111566Smitch.hayenga@arm.com
18211566Smitch.hayenga@arm.com                if (interrupts[IT_RES_ERROR]) {
18311566Smitch.hayenga@arm.com                    return true;
18411566Smitch.hayenga@arm.com                }
18511566Smitch.hayenga@arm.com            } // !hpriv && pstate.ie
18611566Smitch.hayenga@arm.com        }  // !hpriv
18711566Smitch.hayenga@arm.com
18811566Smitch.hayenga@arm.com        return false;
1894009Ssaidi@eecs.umich.edu    }
1903537Sgblack@eecs.umich.edu
1915704Snate@binkert.org    Fault
1925704Snate@binkert.org    getInterrupt(ThreadContext *tc)
1934009Ssaidi@eecs.umich.edu    {
19411566Smitch.hayenga@arm.com        assert(checkInterrupts(tc));
19511566Smitch.hayenga@arm.com
1968829Sgblack@eecs.umich.edu        HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
1978829Sgblack@eecs.umich.edu        PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
1983827Shsul@eecs.umich.edu
1994009Ssaidi@eecs.umich.edu        // THESE ARE IN ORDER OF PRIORITY
2004009Ssaidi@eecs.umich.edu        // since there are early returns, and the highest
2014009Ssaidi@eecs.umich.edu        // priority interrupts should get serviced,
2024009Ssaidi@eecs.umich.edu        // it is v. important that new interrupts are inserted
2034009Ssaidi@eecs.umich.edu        // in the right order of processing
2048829Sgblack@eecs.umich.edu        if (hpstate.hpriv) {
2058829Sgblack@eecs.umich.edu            if (pstate.ie) {
2064103Ssaidi@eecs.umich.edu                if (interrupts[IT_HINTP]) {
2074103Ssaidi@eecs.umich.edu                    // This will be cleaned by a HINTP write
20810474Sandreas.hansson@arm.com                    return std::make_shared<HstickMatch>();
2093894Shsul@eecs.umich.edu                }
2104103Ssaidi@eecs.umich.edu                if (interrupts[IT_INT_VEC]) {
2114103Ssaidi@eecs.umich.edu                    // this will be cleared by an ASI read (or write)
21210474Sandreas.hansson@arm.com                    return std::make_shared<InterruptVector>();
2134009Ssaidi@eecs.umich.edu                }
2144103Ssaidi@eecs.umich.edu            }
2154103Ssaidi@eecs.umich.edu        } else {
2164103Ssaidi@eecs.umich.edu            if (interrupts[IT_TRAP_LEVEL_ZERO]) {
2174103Ssaidi@eecs.umich.edu                    // this is cleared by deasserting HPSTATE::tlz
21810474Sandreas.hansson@arm.com                return std::make_shared<TrapLevelZero>();
2194103Ssaidi@eecs.umich.edu            }
2204103Ssaidi@eecs.umich.edu            // HStick matches always happen in priv mode (ie doesn't matter)
2214103Ssaidi@eecs.umich.edu            if (interrupts[IT_HINTP]) {
22210474Sandreas.hansson@arm.com                return std::make_shared<HstickMatch>();
2234103Ssaidi@eecs.umich.edu            }
2244103Ssaidi@eecs.umich.edu            if (interrupts[IT_INT_VEC]) {
2254103Ssaidi@eecs.umich.edu                // this will be cleared by an ASI read (or write)
22610474Sandreas.hansson@arm.com                return std::make_shared<InterruptVector>();
2274103Ssaidi@eecs.umich.edu            }
2288829Sgblack@eecs.umich.edu            if (pstate.ie) {
2294103Ssaidi@eecs.umich.edu                if (interrupts[IT_CPU_MONDO]) {
23010474Sandreas.hansson@arm.com                    return std::make_shared<CpuMondo>();
2314103Ssaidi@eecs.umich.edu                }
2324103Ssaidi@eecs.umich.edu                if (interrupts[IT_DEV_MONDO]) {
23310474Sandreas.hansson@arm.com                    return std::make_shared<DevMondo>();
2344103Ssaidi@eecs.umich.edu                }
2354103Ssaidi@eecs.umich.edu                if (interrupts[IT_SOFT_INT]) {
2365704Snate@binkert.org                    int level = InterruptLevel(interrupts[IT_SOFT_INT]);
23710474Sandreas.hansson@arm.com                    return std::make_shared<InterruptLevelN>(level);
2384009Ssaidi@eecs.umich.edu                }
2394009Ssaidi@eecs.umich.edu
2404103Ssaidi@eecs.umich.edu                if (interrupts[IT_RES_ERROR]) {
24110474Sandreas.hansson@arm.com                    return std::make_shared<ResumableError>();
2423894Shsul@eecs.umich.edu                }
2438829Sgblack@eecs.umich.edu            } // !hpriv && pstate.ie
2444103Ssaidi@eecs.umich.edu        }  // !hpriv
2454009Ssaidi@eecs.umich.edu        return NoFault;
2464009Ssaidi@eecs.umich.edu    }
2473537Sgblack@eecs.umich.edu
2485704Snate@binkert.org    void
2495704Snate@binkert.org    updateIntrInfo(ThreadContext *tc)
2507741Sgblack@eecs.umich.edu    {}
2513654Shsul@eecs.umich.edu
2525704Snate@binkert.org    uint64_t
2535704Snate@binkert.org    get_vec(int int_num)
2544103Ssaidi@eecs.umich.edu    {
2554103Ssaidi@eecs.umich.edu        assert(int_num >= 0 && int_num < NumInterruptTypes);
2564103Ssaidi@eecs.umich.edu        return interrupts[int_num];
2574103Ssaidi@eecs.umich.edu    }
2584103Ssaidi@eecs.umich.edu
2595704Snate@binkert.org    void
26011168Sandreas.hansson@arm.com    serialize(CheckpointOut &cp) const override
2614009Ssaidi@eecs.umich.edu    {
2624103Ssaidi@eecs.umich.edu        SERIALIZE_ARRAY(interrupts,NumInterruptTypes);
2634103Ssaidi@eecs.umich.edu        SERIALIZE_SCALAR(intStatus);
2644009Ssaidi@eecs.umich.edu    }
2653537Sgblack@eecs.umich.edu
2665704Snate@binkert.org    void
26711168Sandreas.hansson@arm.com    unserialize(CheckpointIn &cp) override
2684009Ssaidi@eecs.umich.edu    {
2694103Ssaidi@eecs.umich.edu        UNSERIALIZE_ARRAY(interrupts,NumInterruptTypes);
2704103Ssaidi@eecs.umich.edu        UNSERIALIZE_SCALAR(intStatus);
2714009Ssaidi@eecs.umich.edu    }
2724009Ssaidi@eecs.umich.edu};
2734009Ssaidi@eecs.umich.edu} // namespace SPARC_ISA
2743537Sgblack@eecs.umich.edu
2753537Sgblack@eecs.umich.edu#endif // __ARCH_SPARC_INTERRUPT_HH__
276