interrupts.hh revision 14293
112802Sandreas.sandberg@arm.com/*
212802Sandreas.sandberg@arm.com * Copyright (c) 2012 ARM Limited
312802Sandreas.sandberg@arm.com * All rights reserved
412802Sandreas.sandberg@arm.com *
512802Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall
612802Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual
712802Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating
812802Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software
912802Sandreas.sandberg@arm.com * licensed hereunder.  You may use the software subject to the license
1012802Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated
1112802Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software,
1212802Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form.
1312802Sandreas.sandberg@arm.com *
1412802Sandreas.sandberg@arm.com * Copyright (c) 2007 The Hewlett-Packard Development Company
1512802Sandreas.sandberg@arm.com * All rights reserved.
1612802Sandreas.sandberg@arm.com *
1712802Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall
1812802Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual
1912802Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating
2012802Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software
2112802Sandreas.sandberg@arm.com * licensed hereunder.  You may use the software subject to the license
2212802Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated
2312802Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software,
2412802Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form.
2512802Sandreas.sandberg@arm.com *
2612802Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
2712802Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
2812802Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
2912802Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
3012802Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
3112802Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
3212802Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
3312802Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
3412802Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
3512802Sandreas.sandberg@arm.com * this software without specific prior written permission.
3612802Sandreas.sandberg@arm.com *
3712802Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3812802Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3912802Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
4012802Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
4112802Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4212802Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4312802Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4412802Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4512802Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4612802Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4712802Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4812802Sandreas.sandberg@arm.com *
4912802Sandreas.sandberg@arm.com * Authors: Gabe Black
5012802Sandreas.sandberg@arm.com *          Andreas Hansson
5112802Sandreas.sandberg@arm.com */
5212802Sandreas.sandberg@arm.com
5312802Sandreas.sandberg@arm.com#ifndef __ARCH_X86_INTERRUPTS_HH__
5412802Sandreas.sandberg@arm.com#define __ARCH_X86_INTERRUPTS_HH__
5512802Sandreas.sandberg@arm.com
5612802Sandreas.sandberg@arm.com#include "arch/x86/regs/apic.hh"
5712802Sandreas.sandberg@arm.com#include "arch/x86/faults.hh"
5812802Sandreas.sandberg@arm.com#include "arch/x86/intmessage.hh"
5912802Sandreas.sandberg@arm.com#include "base/bitfield.hh"
6012802Sandreas.sandberg@arm.com#include "cpu/thread_context.hh"
6112802Sandreas.sandberg@arm.com#include "dev/x86/intdev.hh"
6212802Sandreas.sandberg@arm.com#include "dev/io_device.hh"
6313784Sgabeblack@google.com#include "params/X86LocalApic.hh"
6413784Sgabeblack@google.com#include "sim/eventq.hh"
6512802Sandreas.sandberg@arm.com
6612802Sandreas.sandberg@arm.comclass ThreadContext;
6712802Sandreas.sandberg@arm.comclass BaseCPU;
6813784Sgabeblack@google.com
6912802Sandreas.sandberg@arm.comint divideFromConf(uint32_t conf);
7012802Sandreas.sandberg@arm.com
7113784Sgabeblack@google.comnamespace X86ISA {
7212802Sandreas.sandberg@arm.com
7312802Sandreas.sandberg@arm.comApicRegIndex decodeAddr(Addr paddr);
7412802Sandreas.sandberg@arm.com
7512802Sandreas.sandberg@arm.comclass Interrupts : public PioDevice, IntDevice
7612823Srmk35@cl.cam.ac.uk{
7712802Sandreas.sandberg@arm.com  protected:
7812823Srmk35@cl.cam.ac.uk    // Storage for the APIC registers
7912823Srmk35@cl.cam.ac.uk    uint32_t regs[NUM_APIC_REGS];
8012802Sandreas.sandberg@arm.com
8112802Sandreas.sandberg@arm.com    BitUnion32(LVTEntry)
8212802Sandreas.sandberg@arm.com        Bitfield<7, 0> vector;
8312802Sandreas.sandberg@arm.com        Bitfield<10, 8> deliveryMode;
8412802Sandreas.sandberg@arm.com        Bitfield<12> status;
8512802Sandreas.sandberg@arm.com        Bitfield<13> polarity;
8612802Sandreas.sandberg@arm.com        Bitfield<14> remoteIRR;
8712802Sandreas.sandberg@arm.com        Bitfield<15> trigger;
8812802Sandreas.sandberg@arm.com        Bitfield<16> masked;
8912802Sandreas.sandberg@arm.com        Bitfield<17> periodic;
9012802Sandreas.sandberg@arm.com    EndBitUnion(LVTEntry)
9112802Sandreas.sandberg@arm.com
9212802Sandreas.sandberg@arm.com    /*
9312802Sandreas.sandberg@arm.com     * Timing related stuff.
9412802Sandreas.sandberg@arm.com     */
9512802Sandreas.sandberg@arm.com    EventFunctionWrapper apicTimerEvent;
9612802Sandreas.sandberg@arm.com    void processApicTimerEvent();
9712802Sandreas.sandberg@arm.com
9812802Sandreas.sandberg@arm.com    /*
9912802Sandreas.sandberg@arm.com     * A set of variables to keep track of interrupts that don't go through
10012802Sandreas.sandberg@arm.com     * the IRR.
10112802Sandreas.sandberg@arm.com     */
10212823Srmk35@cl.cam.ac.uk    bool pendingSmi;
10312802Sandreas.sandberg@arm.com    uint8_t smiVector;
10412802Sandreas.sandberg@arm.com    bool pendingNmi;
10512802Sandreas.sandberg@arm.com    uint8_t nmiVector;
10612802Sandreas.sandberg@arm.com    bool pendingExtInt;
10712802Sandreas.sandberg@arm.com    uint8_t extIntVector;
10812802Sandreas.sandberg@arm.com    bool pendingInit;
10912802Sandreas.sandberg@arm.com    uint8_t initVector;
11012802Sandreas.sandberg@arm.com    bool pendingStartup;
11112802Sandreas.sandberg@arm.com    uint8_t startupVector;
11212802Sandreas.sandberg@arm.com    bool startedUp;
11312802Sandreas.sandberg@arm.com
11412802Sandreas.sandberg@arm.com    // This is a quick check whether any of the above (except ExtInt) are set.
11512802Sandreas.sandberg@arm.com    bool pendingUnmaskableInt;
11612802Sandreas.sandberg@arm.com
11712802Sandreas.sandberg@arm.com    // A count of how many IPIs are in flight.
11812802Sandreas.sandberg@arm.com    int pendingIPIs;
11912802Sandreas.sandberg@arm.com
12012802Sandreas.sandberg@arm.com    /*
12112802Sandreas.sandberg@arm.com     * IRR and ISR maintenance.
12212802Sandreas.sandberg@arm.com     */
12312802Sandreas.sandberg@arm.com    uint8_t IRRV;
12412802Sandreas.sandberg@arm.com    uint8_t ISRV;
12512802Sandreas.sandberg@arm.com
12612802Sandreas.sandberg@arm.com    int
12712802Sandreas.sandberg@arm.com    findRegArrayMSB(ApicRegIndex base)
12812802Sandreas.sandberg@arm.com    {
12912802Sandreas.sandberg@arm.com        int offset = 7;
13012802Sandreas.sandberg@arm.com        do {
13112802Sandreas.sandberg@arm.com            if (regs[base + offset] != 0) {
13212802Sandreas.sandberg@arm.com                return offset * 32 + findMsbSet(regs[base + offset]);
13312802Sandreas.sandberg@arm.com            }
13412802Sandreas.sandberg@arm.com        } while (offset--);
13512802Sandreas.sandberg@arm.com        return 0;
13612802Sandreas.sandberg@arm.com    }
13712802Sandreas.sandberg@arm.com
13812802Sandreas.sandberg@arm.com    void
13912802Sandreas.sandberg@arm.com    updateIRRV()
14012802Sandreas.sandberg@arm.com    {
14112802Sandreas.sandberg@arm.com        IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE);
14212802Sandreas.sandberg@arm.com    }
14312802Sandreas.sandberg@arm.com
14412802Sandreas.sandberg@arm.com    void
14512802Sandreas.sandberg@arm.com    updateISRV()
14612802Sandreas.sandberg@arm.com    {
14712802Sandreas.sandberg@arm.com        ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE);
14812802Sandreas.sandberg@arm.com    }
14912802Sandreas.sandberg@arm.com
15012802Sandreas.sandberg@arm.com    void
15112823Srmk35@cl.cam.ac.uk    setRegArrayBit(ApicRegIndex base, uint8_t vector)
15212802Sandreas.sandberg@arm.com    {
15312802Sandreas.sandberg@arm.com        regs[base + (vector / 32)] |= (1 << (vector % 32));
15412802Sandreas.sandberg@arm.com    }
15512802Sandreas.sandberg@arm.com
15612802Sandreas.sandberg@arm.com    void
15712802Sandreas.sandberg@arm.com    clearRegArrayBit(ApicRegIndex base, uint8_t vector)
15812802Sandreas.sandberg@arm.com    {
15912802Sandreas.sandberg@arm.com        regs[base + (vector / 32)] &= ~(1 << (vector % 32));
16012802Sandreas.sandberg@arm.com    }
16112802Sandreas.sandberg@arm.com
16212802Sandreas.sandberg@arm.com    bool
16312802Sandreas.sandberg@arm.com    getRegArrayBit(ApicRegIndex base, uint8_t vector)
16412802Sandreas.sandberg@arm.com    {
16512802Sandreas.sandberg@arm.com        return bits(regs[base + (vector / 32)], vector % 32);
16612802Sandreas.sandberg@arm.com    }
16712802Sandreas.sandberg@arm.com
16812802Sandreas.sandberg@arm.com    void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
16912802Sandreas.sandberg@arm.com
17012802Sandreas.sandberg@arm.com    BaseCPU *cpu;
17112802Sandreas.sandberg@arm.com
17212802Sandreas.sandberg@arm.com    int initialApicId;
17312802Sandreas.sandberg@arm.com
17412802Sandreas.sandberg@arm.com    // Port for receiving interrupts
17512802Sandreas.sandberg@arm.com    IntSlavePort intSlavePort;
17612802Sandreas.sandberg@arm.com
17712802Sandreas.sandberg@arm.com    Tick pioDelay;
17812802Sandreas.sandberg@arm.com    Addr pioAddr = MaxAddr;
17912802Sandreas.sandberg@arm.com
18012802Sandreas.sandberg@arm.com  public:
18112802Sandreas.sandberg@arm.com
18212802Sandreas.sandberg@arm.com    int getInitialApicId() { return initialApicId; }
18312802Sandreas.sandberg@arm.com
18412802Sandreas.sandberg@arm.com    /*
18512802Sandreas.sandberg@arm.com     * Params stuff.
18612802Sandreas.sandberg@arm.com     */
18712802Sandreas.sandberg@arm.com    typedef X86LocalApicParams Params;
18812802Sandreas.sandberg@arm.com
18912802Sandreas.sandberg@arm.com    void setCPU(BaseCPU * newCPU);
19012802Sandreas.sandberg@arm.com
19112802Sandreas.sandberg@arm.com    const Params *
19212802Sandreas.sandberg@arm.com    params() const
19312802Sandreas.sandberg@arm.com    {
19412802Sandreas.sandberg@arm.com        return dynamic_cast<const Params *>(_params);
19512802Sandreas.sandberg@arm.com    }
19612802Sandreas.sandberg@arm.com
19712802Sandreas.sandberg@arm.com    /*
19812802Sandreas.sandberg@arm.com     * Initialize this object by registering it with the IO APIC.
19912802Sandreas.sandberg@arm.com     */
20012802Sandreas.sandberg@arm.com    void init() override;
20112802Sandreas.sandberg@arm.com
20212802Sandreas.sandberg@arm.com    /*
20312802Sandreas.sandberg@arm.com     * Functions to interact with the interrupt port from IntDevice.
20412802Sandreas.sandberg@arm.com     */
20512802Sandreas.sandberg@arm.com    Tick read(PacketPtr pkt) override;
20612802Sandreas.sandberg@arm.com    Tick write(PacketPtr pkt) override;
20712802Sandreas.sandberg@arm.com    Tick recvMessage(PacketPtr pkt) override;
20812802Sandreas.sandberg@arm.com    Tick recvResponse(PacketPtr pkt) override;
209
210    bool
211    triggerTimerInterrupt()
212    {
213        LVTEntry entry = regs[APIC_LVT_TIMER];
214        if (!entry.masked)
215            requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger);
216        return entry.periodic;
217    }
218
219    AddrRangeList getAddrRanges() const override;
220    AddrRangeList getIntAddrRange() const override;
221
222    Port &getPort(const std::string &if_name,
223                  PortID idx=InvalidPortID) override
224    {
225        if (if_name == "int_master") {
226            return intMasterPort;
227        } else if (if_name == "int_slave") {
228            return intSlavePort;
229        }
230        return PioDevice::getPort(if_name, idx);
231    }
232
233    /*
234     * Functions to access and manipulate the APIC's registers.
235     */
236
237    uint32_t readReg(ApicRegIndex miscReg);
238    void setReg(ApicRegIndex reg, uint32_t val);
239    void
240    setRegNoEffect(ApicRegIndex reg, uint32_t val)
241    {
242        regs[reg] = val;
243    }
244
245    /*
246     * Constructor.
247     */
248
249    Interrupts(Params * p);
250
251    /*
252     * Functions for retrieving interrupts for the CPU to handle.
253     */
254
255    bool checkInterrupts(ThreadContext *tc) const;
256    /**
257     * Check if there are pending interrupts without ignoring the
258     * interrupts disabled flag.
259     *
260     * @return true if there are interrupts pending.
261     */
262    bool checkInterruptsRaw() const;
263    /**
264     * Check if there are pending unmaskable interrupts.
265     *
266     * @return true there are unmaskable interrupts pending.
267     */
268    bool hasPendingUnmaskable() const { return pendingUnmaskableInt; }
269    Fault getInterrupt(ThreadContext *tc);
270    void updateIntrInfo(ThreadContext *tc);
271
272    /*
273     * Serialization.
274     */
275    void serialize(CheckpointOut &cp) const override;
276    void unserialize(CheckpointIn &cp) override;
277
278    /*
279     * Old functions needed for compatability but which will be phased out
280     * eventually.
281     */
282    void
283    post(int int_num, int index)
284    {
285        panic("Interrupts::post unimplemented!\n");
286    }
287
288    void
289    clear(int int_num, int index)
290    {
291        panic("Interrupts::clear unimplemented!\n");
292    }
293
294    void
295    clearAll()
296    {
297        panic("Interrupts::clearAll unimplemented!\n");
298    }
299};
300
301} // namespace X86ISA
302
303#endif // __ARCH_X86_INTERRUPTS_HH__
304