interrupts.hh revision 6066
19883Sandreas@sandberg.pp.se/*
29883Sandreas@sandberg.pp.se * Copyright (c) 2007 The Hewlett-Packard Development Company
39883Sandreas@sandberg.pp.se * All rights reserved.
49883Sandreas@sandberg.pp.se *
59883Sandreas@sandberg.pp.se * Redistribution and use of this software in source and binary forms,
69883Sandreas@sandberg.pp.se * with or without modification, are permitted provided that the
79883Sandreas@sandberg.pp.se * following conditions are met:
89883Sandreas@sandberg.pp.se *
99883Sandreas@sandberg.pp.se * The software must be used only for Non-Commercial Use which means any
109883Sandreas@sandberg.pp.se * use which is NOT directed to receiving any direct monetary
119883Sandreas@sandberg.pp.se * compensation for, or commercial advantage from such use.  Illustrative
129883Sandreas@sandberg.pp.se * examples of non-commercial use are academic research, personal study,
139883Sandreas@sandberg.pp.se * teaching, education and corporate research & development.
149883Sandreas@sandberg.pp.se * Illustrative examples of commercial use are distributing products for
159883Sandreas@sandberg.pp.se * commercial advantage and providing services using the software for
169883Sandreas@sandberg.pp.se * commercial advantage.
179883Sandreas@sandberg.pp.se *
189883Sandreas@sandberg.pp.se * If you wish to use this software or functionality therein that may be
199883Sandreas@sandberg.pp.se * covered by patents for commercial use, please contact:
209883Sandreas@sandberg.pp.se *     Director of Intellectual Property Licensing
219883Sandreas@sandberg.pp.se *     Office of Strategy and Technology
229883Sandreas@sandberg.pp.se *     Hewlett-Packard Company
239883Sandreas@sandberg.pp.se *     1501 Page Mill Road
249883Sandreas@sandberg.pp.se *     Palo Alto, California  94304
259883Sandreas@sandberg.pp.se *
269883Sandreas@sandberg.pp.se * Redistributions of source code must retain the above copyright notice,
279883Sandreas@sandberg.pp.se * this list of conditions and the following disclaimer.  Redistributions
289883Sandreas@sandberg.pp.se * in binary form must reproduce the above copyright notice, this list of
299883Sandreas@sandberg.pp.se * conditions and the following disclaimer in the documentation and/or
309883Sandreas@sandberg.pp.se * other materials provided with the distribution.  Neither the name of
3111793Sbrandon.potter@amd.com * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
3211793Sbrandon.potter@amd.com * contributors may be used to endorse or promote products derived from
339883Sandreas@sandberg.pp.se * this software without specific prior written permission.  No right of
349883Sandreas@sandberg.pp.se * sublicense is granted herewith.  Derivatives of the software and
359883Sandreas@sandberg.pp.se * output created using the software may be prepared, but only for
369883Sandreas@sandberg.pp.se * Non-Commercial Uses.  Derivatives of the software may be shared with
379883Sandreas@sandberg.pp.se * others provided: (i) the others agree to abide by the list of
389883Sandreas@sandberg.pp.se * conditions herein which includes the Non-Commercial Use restrictions;
3911793Sbrandon.potter@amd.com * and (ii) such Derivatives of the software include the above copyright
4011793Sbrandon.potter@amd.com * notice to acknowledge the contribution from this software where
419883Sandreas@sandberg.pp.se * applicable, this list of conditions and the disclaimer below.
429883Sandreas@sandberg.pp.se *
439883Sandreas@sandberg.pp.se * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
449883Sandreas@sandberg.pp.se * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
459883Sandreas@sandberg.pp.se * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
469883Sandreas@sandberg.pp.se * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
479883Sandreas@sandberg.pp.se * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
489883Sandreas@sandberg.pp.se * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
499883Sandreas@sandberg.pp.se * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
509883Sandreas@sandberg.pp.se * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
519883Sandreas@sandberg.pp.se * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
529883Sandreas@sandberg.pp.se * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
539883Sandreas@sandberg.pp.se * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
549883Sandreas@sandberg.pp.se *
559883Sandreas@sandberg.pp.se * Authors: Gabe Black
569883Sandreas@sandberg.pp.se */
579886Sandreas@sandberg.pp.se
589886Sandreas@sandberg.pp.se#ifndef __ARCH_X86_INTERRUPTS_HH__
599886Sandreas@sandberg.pp.se#define __ARCH_X86_INTERRUPTS_HH__
609886Sandreas@sandberg.pp.se
619886Sandreas@sandberg.pp.se#include "arch/x86/apicregs.hh"
629886Sandreas@sandberg.pp.se#include "arch/x86/faults.hh"
639886Sandreas@sandberg.pp.se#include "arch/x86/intmessage.hh"
649886Sandreas@sandberg.pp.se#include "base/bitfield.hh"
659886Sandreas@sandberg.pp.se#include "cpu/thread_context.hh"
669886Sandreas@sandberg.pp.se#include "dev/io_device.hh"
679886Sandreas@sandberg.pp.se#include "dev/x86/intdev.hh"
689886Sandreas@sandberg.pp.se#include "params/X86LocalApic.hh"
699886Sandreas@sandberg.pp.se#include "sim/eventq.hh"
709886Sandreas@sandberg.pp.se
719890Sandreas@sandberg.pp.seclass ThreadContext;
729890Sandreas@sandberg.pp.seclass BaseCPU;
739890Sandreas@sandberg.pp.se
749890Sandreas@sandberg.pp.senamespace X86ISA {
759890Sandreas@sandberg.pp.se
769890Sandreas@sandberg.pp.seclass Interrupts : public BasicPioDevice, IntDev
779890Sandreas@sandberg.pp.se{
789890Sandreas@sandberg.pp.se  protected:
799890Sandreas@sandberg.pp.se    // Storage for the APIC registers
809890Sandreas@sandberg.pp.se    uint32_t regs[NUM_APIC_REGS];
819890Sandreas@sandberg.pp.se
829890Sandreas@sandberg.pp.se    BitUnion32(LVTEntry)
839890Sandreas@sandberg.pp.se        Bitfield<7, 0> vector;
849890Sandreas@sandberg.pp.se        Bitfield<10, 8> deliveryMode;
859890Sandreas@sandberg.pp.se        Bitfield<12> status;
869890Sandreas@sandberg.pp.se        Bitfield<13> polarity;
879890Sandreas@sandberg.pp.se        Bitfield<14> remoteIRR;
889890Sandreas@sandberg.pp.se        Bitfield<15> trigger;
899890Sandreas@sandberg.pp.se        Bitfield<16> masked;
909890Sandreas@sandberg.pp.se        Bitfield<17> periodic;
919890Sandreas@sandberg.pp.se    EndBitUnion(LVTEntry)
929890Sandreas@sandberg.pp.se
939890Sandreas@sandberg.pp.se    /*
949890Sandreas@sandberg.pp.se     * Timing related stuff.
959890Sandreas@sandberg.pp.se     */
969890Sandreas@sandberg.pp.se    Tick latency;
979890Sandreas@sandberg.pp.se    Tick clock;
989890Sandreas@sandberg.pp.se
999890Sandreas@sandberg.pp.se    class ApicTimerEvent : public Event
1009890Sandreas@sandberg.pp.se    {
1019890Sandreas@sandberg.pp.se      private:
1029890Sandreas@sandberg.pp.se        Interrupts *localApic;
1039886Sandreas@sandberg.pp.se      public:
1049883Sandreas@sandberg.pp.se        ApicTimerEvent(Interrupts *_localApic) :
1059883Sandreas@sandberg.pp.se            Event(), localApic(_localApic)
1069883Sandreas@sandberg.pp.se        {}
1079883Sandreas@sandberg.pp.se
1089883Sandreas@sandberg.pp.se        void process()
1099883Sandreas@sandberg.pp.se        {
1109883Sandreas@sandberg.pp.se            assert(localApic);
1119883Sandreas@sandberg.pp.se            if (localApic->triggerTimerInterrupt()) {
1129883Sandreas@sandberg.pp.se                localApic->setReg(APIC_INITIAL_COUNT,
1139883Sandreas@sandberg.pp.se                        localApic->readReg(APIC_INITIAL_COUNT));
1149883Sandreas@sandberg.pp.se            }
1159883Sandreas@sandberg.pp.se        }
1169883Sandreas@sandberg.pp.se    };
1179883Sandreas@sandberg.pp.se
1189883Sandreas@sandberg.pp.se    ApicTimerEvent apicTimerEvent;
1199883Sandreas@sandberg.pp.se
1209883Sandreas@sandberg.pp.se    /*
1219883Sandreas@sandberg.pp.se     * A set of variables to keep track of interrupts that don't go through
12211321Ssteve.reinhardt@amd.com     * the IRR.
1239883Sandreas@sandberg.pp.se     */
1249883Sandreas@sandberg.pp.se    bool pendingSmi;
1259883Sandreas@sandberg.pp.se    uint8_t smiVector;
1269883Sandreas@sandberg.pp.se    bool pendingNmi;
1279883Sandreas@sandberg.pp.se    uint8_t nmiVector;
1289883Sandreas@sandberg.pp.se    bool pendingExtInt;
1299883Sandreas@sandberg.pp.se    uint8_t extIntVector;
1309883Sandreas@sandberg.pp.se    bool pendingInit;
1319883Sandreas@sandberg.pp.se    uint8_t initVector;
1329883Sandreas@sandberg.pp.se    bool pendingStartup;
13311321Ssteve.reinhardt@amd.com    uint8_t startupVector;
1349883Sandreas@sandberg.pp.se    bool startedUp;
1359883Sandreas@sandberg.pp.se
1369883Sandreas@sandberg.pp.se    // This is a quick check whether any of the above (except ExtInt) are set.
1379883Sandreas@sandberg.pp.se    bool pendingUnmaskableInt;
1389883Sandreas@sandberg.pp.se
1399883Sandreas@sandberg.pp.se    /*
1409883Sandreas@sandberg.pp.se     * IRR and ISR maintenance.
1419883Sandreas@sandberg.pp.se     */
1429883Sandreas@sandberg.pp.se    uint8_t IRRV;
14311321Ssteve.reinhardt@amd.com    uint8_t ISRV;
1449883Sandreas@sandberg.pp.se
1459883Sandreas@sandberg.pp.se    int
1469883Sandreas@sandberg.pp.se    findRegArrayMSB(ApicRegIndex base)
1479883Sandreas@sandberg.pp.se    {
1489883Sandreas@sandberg.pp.se        int offset = 7;
1499883Sandreas@sandberg.pp.se        do {
1509883Sandreas@sandberg.pp.se            if (regs[base + offset] != 0) {
1519883Sandreas@sandberg.pp.se                return offset * 32 + findMsbSet(regs[base + offset]);
1529883Sandreas@sandberg.pp.se            }
1539883Sandreas@sandberg.pp.se        } while (offset--);
1549883Sandreas@sandberg.pp.se        return 0;
15511321Ssteve.reinhardt@amd.com    }
1569883Sandreas@sandberg.pp.se
1579883Sandreas@sandberg.pp.se    void
1589883Sandreas@sandberg.pp.se    updateIRRV()
1599883Sandreas@sandberg.pp.se    {
1609883Sandreas@sandberg.pp.se        IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE);
16111321Ssteve.reinhardt@amd.com    }
1629883Sandreas@sandberg.pp.se
1639883Sandreas@sandberg.pp.se    void
1649883Sandreas@sandberg.pp.se    updateISRV()
1659883Sandreas@sandberg.pp.se    {
1669883Sandreas@sandberg.pp.se        ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE);
1679883Sandreas@sandberg.pp.se    }
1689883Sandreas@sandberg.pp.se
1699883Sandreas@sandberg.pp.se    void
1709883Sandreas@sandberg.pp.se    setRegArrayBit(ApicRegIndex base, uint8_t vector)
1719883Sandreas@sandberg.pp.se    {
1729883Sandreas@sandberg.pp.se        regs[base + (vector % 32)] |= (1 << (vector >> 5));
1739883Sandreas@sandberg.pp.se    }
1749883Sandreas@sandberg.pp.se
1759883Sandreas@sandberg.pp.se    void
1769883Sandreas@sandberg.pp.se    clearRegArrayBit(ApicRegIndex base, uint8_t vector)
1779883Sandreas@sandberg.pp.se    {
1789883Sandreas@sandberg.pp.se        regs[base + (vector % 32)] &= ~(1 << (vector >> 5));
1799883Sandreas@sandberg.pp.se    }
1809883Sandreas@sandberg.pp.se
1819883Sandreas@sandberg.pp.se    bool
1829883Sandreas@sandberg.pp.se    getRegArrayBit(ApicRegIndex base, uint8_t vector)
1839883Sandreas@sandberg.pp.se    {
1849883Sandreas@sandberg.pp.se        return bits(regs[base + (vector % 32)], vector >> 5);
1859883Sandreas@sandberg.pp.se    }
1869883Sandreas@sandberg.pp.se
1879883Sandreas@sandberg.pp.se    void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
1889883Sandreas@sandberg.pp.se
1899883Sandreas@sandberg.pp.se    BaseCPU *cpu;
1909883Sandreas@sandberg.pp.se
1919883Sandreas@sandberg.pp.se  public:
1929883Sandreas@sandberg.pp.se    /*
1939883Sandreas@sandberg.pp.se     * Params stuff.
1949883Sandreas@sandberg.pp.se     */
1959883Sandreas@sandberg.pp.se    typedef X86LocalApicParams Params;
1969883Sandreas@sandberg.pp.se
1979883Sandreas@sandberg.pp.se    void setCPU(BaseCPU * newCPU);
1989883Sandreas@sandberg.pp.se
1999883Sandreas@sandberg.pp.se    void
2009883Sandreas@sandberg.pp.se    setClock(Tick newClock)
2019883Sandreas@sandberg.pp.se    {
2029883Sandreas@sandberg.pp.se        clock = newClock;
2039883Sandreas@sandberg.pp.se    }
2049883Sandreas@sandberg.pp.se
2059883Sandreas@sandberg.pp.se    const Params *
2069883Sandreas@sandberg.pp.se    params() const
2079883Sandreas@sandberg.pp.se    {
2089883Sandreas@sandberg.pp.se        return dynamic_cast<const Params *>(_params);
2099883Sandreas@sandberg.pp.se    }
2109883Sandreas@sandberg.pp.se
2119883Sandreas@sandberg.pp.se    /*
2129883Sandreas@sandberg.pp.se     * Functions to interact with the interrupt port from IntDev.
2139883Sandreas@sandberg.pp.se     */
2149883Sandreas@sandberg.pp.se    Tick read(PacketPtr pkt);
2159883Sandreas@sandberg.pp.se    Tick write(PacketPtr pkt);
2169883Sandreas@sandberg.pp.se    Tick recvMessage(PacketPtr pkt);
2179883Sandreas@sandberg.pp.se    Tick recvResponse(PacketPtr pkt);
2189883Sandreas@sandberg.pp.se
2199883Sandreas@sandberg.pp.se    bool
2209883Sandreas@sandberg.pp.se    triggerTimerInterrupt()
2219883Sandreas@sandberg.pp.se    {
2229883Sandreas@sandberg.pp.se        LVTEntry entry = regs[APIC_LVT_TIMER];
2239883Sandreas@sandberg.pp.se        if (!entry.masked)
2249883Sandreas@sandberg.pp.se            requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger);
2259883Sandreas@sandberg.pp.se        return entry.periodic;
2269883Sandreas@sandberg.pp.se    }
2279883Sandreas@sandberg.pp.se
2289883Sandreas@sandberg.pp.se    void addressRanges(AddrRangeList &range_list);
2299883Sandreas@sandberg.pp.se    void getIntAddrRange(AddrRangeList &range_list);
2309883Sandreas@sandberg.pp.se
2319883Sandreas@sandberg.pp.se    Port *getPort(const std::string &if_name, int idx = -1)
2329883Sandreas@sandberg.pp.se    {
2339883Sandreas@sandberg.pp.se        if (if_name == "int_port")
2349883Sandreas@sandberg.pp.se            return intPort;
2359883Sandreas@sandberg.pp.se        return BasicPioDevice::getPort(if_name, idx);
2369883Sandreas@sandberg.pp.se    }
2379883Sandreas@sandberg.pp.se
2389883Sandreas@sandberg.pp.se    /*
2399883Sandreas@sandberg.pp.se     * Functions to access and manipulate the APIC's registers.
2409883Sandreas@sandberg.pp.se     */
2419883Sandreas@sandberg.pp.se
2429883Sandreas@sandberg.pp.se    uint32_t readReg(ApicRegIndex miscReg);
2439883Sandreas@sandberg.pp.se    void setReg(ApicRegIndex reg, uint32_t val);
2449890Sandreas@sandberg.pp.se    void
2459883Sandreas@sandberg.pp.se    setRegNoEffect(ApicRegIndex reg, uint32_t val)
2469890Sandreas@sandberg.pp.se    {
2479890Sandreas@sandberg.pp.se        regs[reg] = val;
2489890Sandreas@sandberg.pp.se    }
2499890Sandreas@sandberg.pp.se
2509890Sandreas@sandberg.pp.se    /*
2519890Sandreas@sandberg.pp.se     * Constructor.
2529890Sandreas@sandberg.pp.se     */
2539890Sandreas@sandberg.pp.se
2549890Sandreas@sandberg.pp.se    Interrupts(Params * p);
2559890Sandreas@sandberg.pp.se
2569890Sandreas@sandberg.pp.se    /*
2579890Sandreas@sandberg.pp.se     * Functions for retrieving interrupts for the CPU to handle.
2589890Sandreas@sandberg.pp.se     */
2599890Sandreas@sandberg.pp.se
2609890Sandreas@sandberg.pp.se    bool checkInterrupts(ThreadContext *tc) const;
2619890Sandreas@sandberg.pp.se    Fault getInterrupt(ThreadContext *tc);
2629890Sandreas@sandberg.pp.se    void updateIntrInfo(ThreadContext *tc);
2639883Sandreas@sandberg.pp.se
2649890Sandreas@sandberg.pp.se    /*
2659890Sandreas@sandberg.pp.se     * Serialization.
2669890Sandreas@sandberg.pp.se     */
2679890Sandreas@sandberg.pp.se
2689890Sandreas@sandberg.pp.se    void
2699890Sandreas@sandberg.pp.se    serialize(std::ostream &os)
2709890Sandreas@sandberg.pp.se    {
2719890Sandreas@sandberg.pp.se        panic("Interrupts::serialize unimplemented!\n");
2729890Sandreas@sandberg.pp.se    }
2739890Sandreas@sandberg.pp.se
2749890Sandreas@sandberg.pp.se    void
2759890Sandreas@sandberg.pp.se    unserialize(Checkpoint *cp, const std::string &section)
2769890Sandreas@sandberg.pp.se    {
2779890Sandreas@sandberg.pp.se        panic("Interrupts::unserialize unimplemented!\n");
2789890Sandreas@sandberg.pp.se    }
2799890Sandreas@sandberg.pp.se
2809890Sandreas@sandberg.pp.se    /*
2819890Sandreas@sandberg.pp.se     * Old functions needed for compatability but which will be phased out
2829890Sandreas@sandberg.pp.se     * eventually.
2839890Sandreas@sandberg.pp.se     */
2849890Sandreas@sandberg.pp.se    void
2859883Sandreas@sandberg.pp.se    post(int int_num, int index)
2869883Sandreas@sandberg.pp.se    {
2879890Sandreas@sandberg.pp.se        panic("Interrupts::post unimplemented!\n");
2889883Sandreas@sandberg.pp.se    }
2899883Sandreas@sandberg.pp.se
2909883Sandreas@sandberg.pp.se    void
2919890Sandreas@sandberg.pp.se    clear(int int_num, int index)
2929890Sandreas@sandberg.pp.se    {
2939890Sandreas@sandberg.pp.se        panic("Interrupts::clear unimplemented!\n");
2949883Sandreas@sandberg.pp.se    }
2959890Sandreas@sandberg.pp.se
2969883Sandreas@sandberg.pp.se    void
2979890Sandreas@sandberg.pp.se    clearAll()
2989890Sandreas@sandberg.pp.se    {
2999883Sandreas@sandberg.pp.se        panic("Interrupts::clearAll unimplemented!\n");
3009883Sandreas@sandberg.pp.se    }
3019883Sandreas@sandberg.pp.se};
3029883Sandreas@sandberg.pp.se
3039883Sandreas@sandberg.pp.se} // namespace X86ISA
3049883Sandreas@sandberg.pp.se
3059883Sandreas@sandberg.pp.se#endif // __ARCH_X86_INTERRUPTS_HH__
3069883Sandreas@sandberg.pp.se