interrupts.hh revision 8746:42d3554b1c35
16313Sgblack@eecs.umich.edu/*
212529Sgiacomo.travaglini@arm.com * Copyright (c) 2007 The Hewlett-Packard Development Company
37093Sgblack@eecs.umich.edu * All rights reserved.
47093Sgblack@eecs.umich.edu *
57093Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall
67093Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual
77093Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating
87093Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software
97093Sgblack@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
107093Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
117093Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
127093Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form.
137093Sgblack@eecs.umich.edu *
146313Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
156313Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
166313Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
176313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
186313Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
196313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
206313Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
216313Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
226313Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
236313Sgblack@eecs.umich.edu * this software without specific prior written permission.
246313Sgblack@eecs.umich.edu *
256313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
266313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
276313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
286313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
296313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
306313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
316313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
326313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
336313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
346313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
356313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
366313Sgblack@eecs.umich.edu *
376313Sgblack@eecs.umich.edu * Authors: Gabe Black
386313Sgblack@eecs.umich.edu */
396313Sgblack@eecs.umich.edu
406313Sgblack@eecs.umich.edu#ifndef __ARCH_X86_INTERRUPTS_HH__
416313Sgblack@eecs.umich.edu#define __ARCH_X86_INTERRUPTS_HH__
426313Sgblack@eecs.umich.edu
436313Sgblack@eecs.umich.edu#include "arch/x86/regs/apic.hh"
447404SAli.Saidi@ARM.com#include "arch/x86/faults.hh"
456313Sgblack@eecs.umich.edu#include "arch/x86/intmessage.hh"
4610461SAndreas.Sandberg@ARM.com#include "base/bitfield.hh"
4712479SCurtis.Dunham@arm.com#include "config/full_system.hh"
486333Sgblack@eecs.umich.edu#include "cpu/thread_context.hh"
4910037SARM gem5 Developers#include "dev/x86/intdev.hh"
507404SAli.Saidi@ARM.com#include "dev/io_device.hh"
516313Sgblack@eecs.umich.edu#include "params/X86LocalApic.hh"
5212109SRekai.GonzalezAlberquilla@arm.com#include "sim/eventq.hh"
538232Snate@binkert.org
5412109SRekai.GonzalezAlberquilla@arm.comclass ThreadContext;
559384SAndreas.Sandberg@arm.comclass BaseCPU;
5611165SRekai.GonzalezAlberquilla@arm.com
576313Sgblack@eecs.umich.edunamespace X86ISA {
589384SAndreas.Sandberg@arm.com
5910461SAndreas.Sandberg@ARM.comclass Interrupts : public BasicPioDevice, IntDev
606333Sgblack@eecs.umich.edu{
616313Sgblack@eecs.umich.edu  protected:
626313Sgblack@eecs.umich.edu    // Storage for the APIC registers
636313Sgblack@eecs.umich.edu    uint32_t regs[NUM_APIC_REGS];
646313Sgblack@eecs.umich.edu
656313Sgblack@eecs.umich.edu    BitUnion32(LVTEntry)
669384SAndreas.Sandberg@arm.com        Bitfield<7, 0> vector;
676313Sgblack@eecs.umich.edu        Bitfield<10, 8> deliveryMode;
686313Sgblack@eecs.umich.edu        Bitfield<12> status;
6910037SARM gem5 Developers        Bitfield<13> polarity;
7010037SARM gem5 Developers        Bitfield<14> remoteIRR;
7110037SARM gem5 Developers        Bitfield<15> trigger;
7211165SRekai.GonzalezAlberquilla@arm.com        Bitfield<16> masked;
7311165SRekai.GonzalezAlberquilla@arm.com        Bitfield<17> periodic;
7412109SRekai.GonzalezAlberquilla@arm.com    EndBitUnion(LVTEntry)
7511165SRekai.GonzalezAlberquilla@arm.com
7610461SAndreas.Sandberg@ARM.com    /*
7710461SAndreas.Sandberg@ARM.com     * Timing related stuff.
7810461SAndreas.Sandberg@ARM.com     */
7910461SAndreas.Sandberg@ARM.com    Tick latency;
8010461SAndreas.Sandberg@ARM.com    Tick clock;
8110461SAndreas.Sandberg@ARM.com
8210844Sandreas.sandberg@arm.com    class ApicTimerEvent : public Event
8310844Sandreas.sandberg@arm.com    {
8410844Sandreas.sandberg@arm.com      private:
8513531Sjairo.balart@metempsy.com        Interrupts *localApic;
8613531Sjairo.balart@metempsy.com      public:
8713531Sjairo.balart@metempsy.com        ApicTimerEvent(Interrupts *_localApic) :
8810037SARM gem5 Developers            Event(), localApic(_localApic)
8911771SCurtis.Dunham@arm.com        {}
9010037SARM gem5 Developers
9110037SARM gem5 Developers        void process()
9210037SARM gem5 Developers        {
9313173Sgiacomo.travaglini@arm.com            assert(localApic);
9410037SARM gem5 Developers            if (localApic->triggerTimerInterrupt()) {
9513531Sjairo.balart@metempsy.com                localApic->setReg(APIC_INITIAL_COUNT,
9613114Sgiacomo.travaglini@arm.com                        localApic->readReg(APIC_INITIAL_COUNT));
9710037SARM gem5 Developers            }
9812714Sgiacomo.travaglini@arm.com        }
9912714Sgiacomo.travaglini@arm.com    };
10012714Sgiacomo.travaglini@arm.com
10112714Sgiacomo.travaglini@arm.com    ApicTimerEvent apicTimerEvent;
10212714Sgiacomo.travaglini@arm.com
10312714Sgiacomo.travaglini@arm.com    /*
10412478SCurtis.Dunham@arm.com     * A set of variables to keep track of interrupts that don't go through
10510037SARM gem5 Developers     * the IRR.
10612477SCurtis.Dunham@arm.com     */
10712477SCurtis.Dunham@arm.com    bool pendingSmi;
10812478SCurtis.Dunham@arm.com    uint8_t smiVector;
10912478SCurtis.Dunham@arm.com    bool pendingNmi;
11012478SCurtis.Dunham@arm.com    uint8_t nmiVector;
11112478SCurtis.Dunham@arm.com    bool pendingExtInt;
11212478SCurtis.Dunham@arm.com    uint8_t extIntVector;
11312478SCurtis.Dunham@arm.com    bool pendingInit;
11412478SCurtis.Dunham@arm.com    uint8_t initVector;
11512478SCurtis.Dunham@arm.com    bool pendingStartup;
11612478SCurtis.Dunham@arm.com    uint8_t startupVector;
11712478SCurtis.Dunham@arm.com    bool startedUp;
11812478SCurtis.Dunham@arm.com
11912478SCurtis.Dunham@arm.com    // This is a quick check whether any of the above (except ExtInt) are set.
12012478SCurtis.Dunham@arm.com    bool pendingUnmaskableInt;
12112478SCurtis.Dunham@arm.com
12212478SCurtis.Dunham@arm.com    // A count of how many IPIs are in flight.
12312478SCurtis.Dunham@arm.com    int pendingIPIs;
12410037SARM gem5 Developers
12510037SARM gem5 Developers    /*
12612477SCurtis.Dunham@arm.com     * IRR and ISR maintenance.
12712479SCurtis.Dunham@arm.com     */
12812477SCurtis.Dunham@arm.com    uint8_t IRRV;
12912477SCurtis.Dunham@arm.com    uint8_t ISRV;
13012477SCurtis.Dunham@arm.com
13112479SCurtis.Dunham@arm.com    int
13212477SCurtis.Dunham@arm.com    findRegArrayMSB(ApicRegIndex base)
13312477SCurtis.Dunham@arm.com    {
13412477SCurtis.Dunham@arm.com        int offset = 7;
13512477SCurtis.Dunham@arm.com        do {
13612477SCurtis.Dunham@arm.com            if (regs[base + offset] != 0) {
13712477SCurtis.Dunham@arm.com                return offset * 32 + findMsbSet(regs[base + offset]);
13812477SCurtis.Dunham@arm.com            }
13912478SCurtis.Dunham@arm.com        } while (offset--);
14012478SCurtis.Dunham@arm.com        return 0;
14112478SCurtis.Dunham@arm.com    }
14212478SCurtis.Dunham@arm.com
14312478SCurtis.Dunham@arm.com    void
14412478SCurtis.Dunham@arm.com    updateIRRV()
14512478SCurtis.Dunham@arm.com    {
14612478SCurtis.Dunham@arm.com        IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE);
14712478SCurtis.Dunham@arm.com    }
14812478SCurtis.Dunham@arm.com
14912478SCurtis.Dunham@arm.com    void
15012478SCurtis.Dunham@arm.com    updateISRV()
15112478SCurtis.Dunham@arm.com    {
15212478SCurtis.Dunham@arm.com        ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE);
15312478SCurtis.Dunham@arm.com    }
15412478SCurtis.Dunham@arm.com
15512479SCurtis.Dunham@arm.com    void
15612479SCurtis.Dunham@arm.com    setRegArrayBit(ApicRegIndex base, uint8_t vector)
15712479SCurtis.Dunham@arm.com    {
15812479SCurtis.Dunham@arm.com        regs[base + (vector / 32)] |= (1 << (vector % 32));
15912479SCurtis.Dunham@arm.com    }
16012479SCurtis.Dunham@arm.com
16112479SCurtis.Dunham@arm.com    void
16212479SCurtis.Dunham@arm.com    clearRegArrayBit(ApicRegIndex base, uint8_t vector)
16312479SCurtis.Dunham@arm.com    {
16412479SCurtis.Dunham@arm.com        regs[base + (vector / 32)] &= ~(1 << (vector % 32));
16512479SCurtis.Dunham@arm.com    }
16612479SCurtis.Dunham@arm.com
16712479SCurtis.Dunham@arm.com    bool
16812479SCurtis.Dunham@arm.com    getRegArrayBit(ApicRegIndex base, uint8_t vector)
16912479SCurtis.Dunham@arm.com    {
17012479SCurtis.Dunham@arm.com        return bits(regs[base + (vector / 32)], vector % 5);
17112479SCurtis.Dunham@arm.com    }
17212479SCurtis.Dunham@arm.com
17312479SCurtis.Dunham@arm.com    void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
17412479SCurtis.Dunham@arm.com
17512479SCurtis.Dunham@arm.com    BaseCPU *cpu;
17612479SCurtis.Dunham@arm.com
17712479SCurtis.Dunham@arm.com    int initialApicId;
17812479SCurtis.Dunham@arm.com
17912479SCurtis.Dunham@arm.com  public:
18012479SCurtis.Dunham@arm.com
18112479SCurtis.Dunham@arm.com    int getInitialApicId() { return initialApicId; }
18212479SCurtis.Dunham@arm.com
18312479SCurtis.Dunham@arm.com    /*
18412479SCurtis.Dunham@arm.com     * Params stuff.
18512479SCurtis.Dunham@arm.com     */
18612479SCurtis.Dunham@arm.com    typedef X86LocalApicParams Params;
18712479SCurtis.Dunham@arm.com
18812479SCurtis.Dunham@arm.com    void setCPU(BaseCPU * newCPU);
18912479SCurtis.Dunham@arm.com
19012479SCurtis.Dunham@arm.com    void
19112479SCurtis.Dunham@arm.com    setClock(Tick newClock)
19212479SCurtis.Dunham@arm.com    {
19312479SCurtis.Dunham@arm.com        clock = newClock;
19412479SCurtis.Dunham@arm.com    }
19512479SCurtis.Dunham@arm.com
19612479SCurtis.Dunham@arm.com    const Params *
19712479SCurtis.Dunham@arm.com    params() const
19812479SCurtis.Dunham@arm.com    {
19912479SCurtis.Dunham@arm.com        return dynamic_cast<const Params *>(_params);
20012479SCurtis.Dunham@arm.com    }
20112479SCurtis.Dunham@arm.com
20212479SCurtis.Dunham@arm.com    /*
20312479SCurtis.Dunham@arm.com     * Initialize this object by registering it with the IO APIC.
20412479SCurtis.Dunham@arm.com     */
20512479SCurtis.Dunham@arm.com    void init();
20612479SCurtis.Dunham@arm.com
20712479SCurtis.Dunham@arm.com    /*
20812479SCurtis.Dunham@arm.com     * Functions to interact with the interrupt port from IntDev.
20912479SCurtis.Dunham@arm.com     */
21012479SCurtis.Dunham@arm.com    Tick read(PacketPtr pkt);
21112479SCurtis.Dunham@arm.com    Tick write(PacketPtr pkt);
21212479SCurtis.Dunham@arm.com    Tick recvMessage(PacketPtr pkt);
21312668Sgiacomo.travaglini@arm.com    Tick recvResponse(PacketPtr pkt);
21412668Sgiacomo.travaglini@arm.com
21512668Sgiacomo.travaglini@arm.com    bool
21612668Sgiacomo.travaglini@arm.com    triggerTimerInterrupt()
21712668Sgiacomo.travaglini@arm.com    {
21812479SCurtis.Dunham@arm.com        LVTEntry entry = regs[APIC_LVT_TIMER];
21912479SCurtis.Dunham@arm.com        if (!entry.masked)
22012479SCurtis.Dunham@arm.com            requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger);
22112479SCurtis.Dunham@arm.com        return entry.periodic;
22212479SCurtis.Dunham@arm.com    }
22312479SCurtis.Dunham@arm.com
22412479SCurtis.Dunham@arm.com    void addressRanges(AddrRangeList &range_list);
22512479SCurtis.Dunham@arm.com    void getIntAddrRange(AddrRangeList &range_list);
22612479SCurtis.Dunham@arm.com
22712479SCurtis.Dunham@arm.com    Port *getPort(const std::string &if_name, int idx = -1)
22812479SCurtis.Dunham@arm.com    {
22912479SCurtis.Dunham@arm.com        if (if_name == "int_port")
23012479SCurtis.Dunham@arm.com            return intPort;
23112668Sgiacomo.travaglini@arm.com        return BasicPioDevice::getPort(if_name, idx);
23212668Sgiacomo.travaglini@arm.com    }
23312668Sgiacomo.travaglini@arm.com
23412668Sgiacomo.travaglini@arm.com    /*
23512668Sgiacomo.travaglini@arm.com     * Functions to access and manipulate the APIC's registers.
23613395Sgiacomo.travaglini@arm.com     */
23713395Sgiacomo.travaglini@arm.com
23813395Sgiacomo.travaglini@arm.com    uint32_t readReg(ApicRegIndex miscReg);
23913395Sgiacomo.travaglini@arm.com    void setReg(ApicRegIndex reg, uint32_t val);
24013395Sgiacomo.travaglini@arm.com    void
24112479SCurtis.Dunham@arm.com    setRegNoEffect(ApicRegIndex reg, uint32_t val)
24212479SCurtis.Dunham@arm.com    {
24312479SCurtis.Dunham@arm.com        regs[reg] = val;
24412479SCurtis.Dunham@arm.com    }
24512479SCurtis.Dunham@arm.com
24612479SCurtis.Dunham@arm.com    /*
24712479SCurtis.Dunham@arm.com     * Constructor.
24812479SCurtis.Dunham@arm.com     */
24912479SCurtis.Dunham@arm.com
25012479SCurtis.Dunham@arm.com    Interrupts(Params * p);
25112479SCurtis.Dunham@arm.com
25212479SCurtis.Dunham@arm.com    /*
25312479SCurtis.Dunham@arm.com     * Functions for retrieving interrupts for the CPU to handle.
25412479SCurtis.Dunham@arm.com     */
25512479SCurtis.Dunham@arm.com
25612479SCurtis.Dunham@arm.com    bool checkInterrupts(ThreadContext *tc) const;
25712479SCurtis.Dunham@arm.com    Fault getInterrupt(ThreadContext *tc);
25812479SCurtis.Dunham@arm.com    void updateIntrInfo(ThreadContext *tc);
25912479SCurtis.Dunham@arm.com
26012479SCurtis.Dunham@arm.com    /*
26112479SCurtis.Dunham@arm.com     * Serialization.
26212479SCurtis.Dunham@arm.com     */
26312479SCurtis.Dunham@arm.com
26412479SCurtis.Dunham@arm.com    virtual void serialize(std::ostream &os);
26512479SCurtis.Dunham@arm.com    virtual void unserialize(Checkpoint *cp, const std::string &section);
26612479SCurtis.Dunham@arm.com
26712479SCurtis.Dunham@arm.com    /*
26812479SCurtis.Dunham@arm.com     * Old functions needed for compatability but which will be phased out
26912479SCurtis.Dunham@arm.com     * eventually.
27012479SCurtis.Dunham@arm.com     */
27112479SCurtis.Dunham@arm.com    void
27212479SCurtis.Dunham@arm.com    post(int int_num, int index)
27312479SCurtis.Dunham@arm.com    {
27412479SCurtis.Dunham@arm.com        panic("Interrupts::post unimplemented!\n");
27512479SCurtis.Dunham@arm.com    }
27612479SCurtis.Dunham@arm.com
27712479SCurtis.Dunham@arm.com    void
27812479SCurtis.Dunham@arm.com    clear(int int_num, int index)
27912479SCurtis.Dunham@arm.com    {
28012479SCurtis.Dunham@arm.com        panic("Interrupts::clear unimplemented!\n");
28112479SCurtis.Dunham@arm.com    }
28212479SCurtis.Dunham@arm.com
28312479SCurtis.Dunham@arm.com    void
28412479SCurtis.Dunham@arm.com    clearAll()
28512479SCurtis.Dunham@arm.com    {
28612479SCurtis.Dunham@arm.com        panic("Interrupts::clearAll unimplemented!\n");
28712479SCurtis.Dunham@arm.com    }
28812479SCurtis.Dunham@arm.com};
28912479SCurtis.Dunham@arm.com
29012479SCurtis.Dunham@arm.com} // namespace X86ISA
29112479SCurtis.Dunham@arm.com
29212479SCurtis.Dunham@arm.com#endif // __ARCH_X86_INTERRUPTS_HH__
29312479SCurtis.Dunham@arm.com