interrupts.hh revision 10112:1a2f64842044
12330SN/A/*
22330SN/A * Copyright (c) 2012 ARM Limited
32330SN/A * All rights reserved
42330SN/A *
52330SN/A * The license below extends only to copyright in the software and shall
62330SN/A * not be construed as granting a license to any other intellectual
72330SN/A * property including but not limited to intellectual property relating
82330SN/A * to a hardware implementation of the functionality of the software
92330SN/A * licensed hereunder.  You may use the software subject to the license
102330SN/A * terms below provided that you ensure that this notice is replicated
112330SN/A * unmodified and in its entirety in all distributions of the software,
122330SN/A * modified or unmodified, in source code or in binary form.
132330SN/A *
142330SN/A * Copyright (c) 2007 The Hewlett-Packard Development Company
152330SN/A * All rights reserved.
162330SN/A *
172330SN/A * The license below extends only to copyright in the software and shall
182330SN/A * not be construed as granting a license to any other intellectual
192330SN/A * property including but not limited to intellectual property relating
202330SN/A * to a hardware implementation of the functionality of the software
212330SN/A * licensed hereunder.  You may use the software subject to the license
222330SN/A * terms below provided that you ensure that this notice is replicated
232330SN/A * unmodified and in its entirety in all distributions of the software,
242330SN/A * modified or unmodified, in source code or in binary form.
252330SN/A *
262330SN/A * Redistribution and use in source and binary forms, with or without
272689Sktlim@umich.edu * modification, are permitted provided that the following conditions are
282689Sktlim@umich.edu * met: redistributions of source code must retain the above copyright
292330SN/A * notice, this list of conditions and the following disclaimer;
302292SN/A * redistributions in binary form must reproduce the above copyright
312292SN/A * notice, this list of conditions and the following disclaimer in the
322292SN/A * documentation and/or other materials provided with the distribution;
332292SN/A * neither the name of the copyright holders nor the names of its
342980Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
352362SN/A * this software without specific prior written permission.
362680Sktlim@umich.edu *
372292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
382678Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
392683Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
402683Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
412678Sktlim@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
422678Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
432292SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
442292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
452292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
462292SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
472330SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
482330SN/A *
492330SN/A * Authors: Gabe Black
502292SN/A *          Andreas Hansson
512292SN/A */
523402Sktlim@umich.edu
532862Sktlim@umich.edu#ifndef __ARCH_X86_INTERRUPTS_HH__
543402Sktlim@umich.edu#define __ARCH_X86_INTERRUPTS_HH__
552862Sktlim@umich.edu
562330SN/A#include "arch/x86/regs/apic.hh"
572330SN/A#include "arch/x86/faults.hh"
582330SN/A#include "arch/x86/intmessage.hh"
592330SN/A#include "base/bitfield.hh"
602330SN/A#include "cpu/thread_context.hh"
612330SN/A#include "dev/x86/intdev.hh"
622292SN/A#include "dev/io_device.hh"
632683Sktlim@umich.edu#include "params/X86LocalApic.hh"
642683Sktlim@umich.edu#include "sim/eventq.hh"
652292SN/A
663402Sktlim@umich.educlass ThreadContext;
672292SN/Aclass BaseCPU;
683402Sktlim@umich.edu
693402Sktlim@umich.eduint divideFromConf(uint32_t conf);
702292SN/A
712683Sktlim@umich.edunamespace X86ISA {
722862Sktlim@umich.edu
732862Sktlim@umich.eduApicRegIndex decodeAddr(Addr paddr);
742862Sktlim@umich.edu
752862Sktlim@umich.educlass Interrupts : public BasicPioDevice, IntDevice
762683Sktlim@umich.edu{
772683Sktlim@umich.edu  protected:
782683Sktlim@umich.edu    // Storage for the APIC registers
792683Sktlim@umich.edu    uint32_t regs[NUM_APIC_REGS];
802683Sktlim@umich.edu
812683Sktlim@umich.edu    BitUnion32(LVTEntry)
822683Sktlim@umich.edu        Bitfield<7, 0> vector;
832683Sktlim@umich.edu        Bitfield<10, 8> deliveryMode;
842683Sktlim@umich.edu        Bitfield<12> status;
852683Sktlim@umich.edu        Bitfield<13> polarity;
862683Sktlim@umich.edu        Bitfield<14> remoteIRR;
872683Sktlim@umich.edu        Bitfield<15> trigger;
882683Sktlim@umich.edu        Bitfield<16> masked;
892683Sktlim@umich.edu        Bitfield<17> periodic;
902683Sktlim@umich.edu    EndBitUnion(LVTEntry)
912683Sktlim@umich.edu
922683Sktlim@umich.edu    /*
932683Sktlim@umich.edu     * Timing related stuff.
942683Sktlim@umich.edu     */
952683Sktlim@umich.edu    class ApicTimerEvent : public Event
962683Sktlim@umich.edu    {
972683Sktlim@umich.edu      private:
982683Sktlim@umich.edu        Interrupts *localApic;
992690Sktlim@umich.edu      public:
1002690Sktlim@umich.edu        ApicTimerEvent(Interrupts *_localApic) :
1012683Sktlim@umich.edu            Event(), localApic(_localApic)
1022683Sktlim@umich.edu        {}
1032690Sktlim@umich.edu
1042690Sktlim@umich.edu        void process()
1052683Sktlim@umich.edu        {
1062683Sktlim@umich.edu            assert(localApic);
1072683Sktlim@umich.edu            if (localApic->triggerTimerInterrupt()) {
1082683Sktlim@umich.edu                localApic->setReg(APIC_INITIAL_COUNT,
1093402Sktlim@umich.edu                        localApic->readReg(APIC_INITIAL_COUNT));
1102683Sktlim@umich.edu            }
1112683Sktlim@umich.edu        }
1122683Sktlim@umich.edu    };
1132683Sktlim@umich.edu
1142683Sktlim@umich.edu    ApicTimerEvent apicTimerEvent;
1152678Sktlim@umich.edu
1162292SN/A    /*
1172683Sktlim@umich.edu     * A set of variables to keep track of interrupts that don't go through
1182683Sktlim@umich.edu     * the IRR.
1192292SN/A     */
1202683Sktlim@umich.edu    bool pendingSmi;
1212683Sktlim@umich.edu    uint8_t smiVector;
1222683Sktlim@umich.edu    bool pendingNmi;
1232683Sktlim@umich.edu    uint8_t nmiVector;
1242683Sktlim@umich.edu    bool pendingExtInt;
1252683Sktlim@umich.edu    uint8_t extIntVector;
1262683Sktlim@umich.edu    bool pendingInit;
1272683Sktlim@umich.edu    uint8_t initVector;
1282683Sktlim@umich.edu    bool pendingStartup;
1292683Sktlim@umich.edu    uint8_t startupVector;
1302683Sktlim@umich.edu    bool startedUp;
1312683Sktlim@umich.edu
1322683Sktlim@umich.edu    // This is a quick check whether any of the above (except ExtInt) are set.
1332683Sktlim@umich.edu    bool pendingUnmaskableInt;
1342683Sktlim@umich.edu
1352683Sktlim@umich.edu    // A count of how many IPIs are in flight.
1362683Sktlim@umich.edu    int pendingIPIs;
1372683Sktlim@umich.edu
1382683Sktlim@umich.edu    /*
1392683Sktlim@umich.edu     * IRR and ISR maintenance.
1402683Sktlim@umich.edu     */
1412683Sktlim@umich.edu    uint8_t IRRV;
1422683Sktlim@umich.edu    uint8_t ISRV;
1432683Sktlim@umich.edu
1442683Sktlim@umich.edu    int
1452683Sktlim@umich.edu    findRegArrayMSB(ApicRegIndex base)
1462683Sktlim@umich.edu    {
1472683Sktlim@umich.edu        int offset = 7;
1482683Sktlim@umich.edu        do {
1492683Sktlim@umich.edu            if (regs[base + offset] != 0) {
1502683Sktlim@umich.edu                return offset * 32 + findMsbSet(regs[base + offset]);
1512683Sktlim@umich.edu            }
1522683Sktlim@umich.edu        } while (offset--);
1532683Sktlim@umich.edu        return 0;
1542683Sktlim@umich.edu    }
1552683Sktlim@umich.edu
1562683Sktlim@umich.edu    void
1573402Sktlim@umich.edu    updateIRRV()
1583402Sktlim@umich.edu    {
1593402Sktlim@umich.edu        IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE);
1602683Sktlim@umich.edu    }
1612683Sktlim@umich.edu
1622292SN/A    void
1632292SN/A    updateISRV()
1642292SN/A    {
1652292SN/A        ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE);
1662292SN/A    }
1672690Sktlim@umich.edu
1682683Sktlim@umich.edu    void
1692683Sktlim@umich.edu    setRegArrayBit(ApicRegIndex base, uint8_t vector)
1702292SN/A    {
1712683Sktlim@umich.edu        regs[base + (vector / 32)] |= (1 << (vector % 32));
1722683Sktlim@umich.edu    }
1732292SN/A
1742292SN/A    void
1752683Sktlim@umich.edu    clearRegArrayBit(ApicRegIndex base, uint8_t vector)
1762292SN/A    {
1772292SN/A        regs[base + (vector / 32)] &= ~(1 << (vector % 32));
1782292SN/A    }
1792292SN/A
1802292SN/A    bool
1812330SN/A    getRegArrayBit(ApicRegIndex base, uint8_t vector)
1822683Sktlim@umich.edu    {
1832683Sktlim@umich.edu        return bits(regs[base + (vector / 32)], vector % 5);
1842683Sktlim@umich.edu    }
1852683Sktlim@umich.edu
1862683Sktlim@umich.edu    void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
1872683Sktlim@umich.edu
1882683Sktlim@umich.edu    BaseCPU *cpu;
1892683Sktlim@umich.edu
1902292SN/A    int initialApicId;
1912678Sktlim@umich.edu
1922678Sktlim@umich.edu    // Port for receiving interrupts
1932292SN/A    IntSlavePort intSlavePort;
1942292SN/A
1952292SN/A  public:
1962292SN/A
1972292SN/A    int getInitialApicId() { return initialApicId; }
1982292SN/A
1992330SN/A    /*
2002330SN/A     * Params stuff.
2012330SN/A     */
2022683Sktlim@umich.edu    typedef X86LocalApicParams Params;
2032683Sktlim@umich.edu
2042683Sktlim@umich.edu    void setCPU(BaseCPU * newCPU);
2052683Sktlim@umich.edu
2062292SN/A    const Params *
2073276Sgblack@eecs.umich.edu    params() const
2083276Sgblack@eecs.umich.edu    {
2093276Sgblack@eecs.umich.edu        return dynamic_cast<const Params *>(_params);
2103276Sgblack@eecs.umich.edu    }
2113276Sgblack@eecs.umich.edu
2123276Sgblack@eecs.umich.edu    /*
2133276Sgblack@eecs.umich.edu     * Initialize this object by registering it with the IO APIC.
2143276Sgblack@eecs.umich.edu     */
2153276Sgblack@eecs.umich.edu    void init();
2163276Sgblack@eecs.umich.edu
2172690Sktlim@umich.edu    /*
2182292SN/A     * Functions to interact with the interrupt port from IntDevice.
2192292SN/A     */
2202292SN/A    Tick read(PacketPtr pkt);
2212292SN/A    Tick write(PacketPtr pkt);
2222292SN/A    Tick recvMessage(PacketPtr pkt);
2232292SN/A    Tick recvResponse(PacketPtr pkt);
2242292SN/A
2252292SN/A    bool
2262292SN/A    triggerTimerInterrupt()
2272292SN/A    {
2282292SN/A        LVTEntry entry = regs[APIC_LVT_TIMER];
2292292SN/A        if (!entry.masked)
2302292SN/A            requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger);
2312292SN/A        return entry.periodic;
2322292SN/A    }
2332292SN/A
2342292SN/A    AddrRangeList getIntAddrRange() const;
2352292SN/A
2362292SN/A    BaseMasterPort &getMasterPort(const std::string &if_name,
2372292SN/A                                  PortID idx = InvalidPortID)
2382292SN/A    {
2392292SN/A        if (if_name == "int_master") {
2402292SN/A            return intMasterPort;
2412292SN/A        }
2422292SN/A        return BasicPioDevice::getMasterPort(if_name, idx);
243    }
244
245    BaseSlavePort &getSlavePort(const std::string &if_name,
246                                PortID idx = InvalidPortID)
247    {
248        if (if_name == "int_slave") {
249            return intSlavePort;
250        }
251        return BasicPioDevice::getSlavePort(if_name, idx);
252    }
253
254    /*
255     * Functions to access and manipulate the APIC's registers.
256     */
257
258    uint32_t readReg(ApicRegIndex miscReg);
259    void setReg(ApicRegIndex reg, uint32_t val);
260    void
261    setRegNoEffect(ApicRegIndex reg, uint32_t val)
262    {
263        regs[reg] = val;
264    }
265
266    /*
267     * Constructor.
268     */
269
270    Interrupts(Params * p);
271
272    /*
273     * Functions for retrieving interrupts for the CPU to handle.
274     */
275
276    bool checkInterrupts(ThreadContext *tc) const;
277    /**
278     * Check if there are pending interrupts without ignoring the
279     * interrupts disabled flag.
280     *
281     * @return true if there are interrupts pending.
282     */
283    bool checkInterruptsRaw() const;
284    /**
285     * Check if there are pending unmaskable interrupts.
286     *
287     * @return true there are unmaskable interrupts pending.
288     */
289    bool hasPendingUnmaskable() const { return pendingUnmaskableInt; }
290    Fault getInterrupt(ThreadContext *tc);
291    void updateIntrInfo(ThreadContext *tc);
292
293    /*
294     * Serialization.
295     */
296
297    virtual void serialize(std::ostream &os);
298    virtual void unserialize(Checkpoint *cp, const std::string &section);
299
300    /*
301     * Old functions needed for compatability but which will be phased out
302     * eventually.
303     */
304    void
305    post(int int_num, int index)
306    {
307        panic("Interrupts::post unimplemented!\n");
308    }
309
310    void
311    clear(int int_num, int index)
312    {
313        panic("Interrupts::clear unimplemented!\n");
314    }
315
316    void
317    clearAll()
318    {
319        panic("Interrupts::clearAll unimplemented!\n");
320    }
321};
322
323} // namespace X86ISA
324
325#endif // __ARCH_X86_INTERRUPTS_HH__
326