interrupts.hh revision 10541
12914Ssaidi@eecs.umich.edu/*
22914Ssaidi@eecs.umich.edu * Copyright (c) 2012 ARM Limited
32914Ssaidi@eecs.umich.edu * All rights reserved
42914Ssaidi@eecs.umich.edu *
52914Ssaidi@eecs.umich.edu * The license below extends only to copyright in the software and shall
62914Ssaidi@eecs.umich.edu * not be construed as granting a license to any other intellectual
72914Ssaidi@eecs.umich.edu * property including but not limited to intellectual property relating
82914Ssaidi@eecs.umich.edu * to a hardware implementation of the functionality of the software
92914Ssaidi@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
102914Ssaidi@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
112914Ssaidi@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
122914Ssaidi@eecs.umich.edu * modified or unmodified, in source code or in binary form.
132914Ssaidi@eecs.umich.edu *
142914Ssaidi@eecs.umich.edu * Copyright (c) 2007 The Hewlett-Packard Development Company
152914Ssaidi@eecs.umich.edu * All rights reserved.
162914Ssaidi@eecs.umich.edu *
172914Ssaidi@eecs.umich.edu * The license below extends only to copyright in the software and shall
182914Ssaidi@eecs.umich.edu * not be construed as granting a license to any other intellectual
192914Ssaidi@eecs.umich.edu * property including but not limited to intellectual property relating
202914Ssaidi@eecs.umich.edu * to a hardware implementation of the functionality of the software
212914Ssaidi@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
222914Ssaidi@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
232914Ssaidi@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
242914Ssaidi@eecs.umich.edu * modified or unmodified, in source code or in binary form.
252914Ssaidi@eecs.umich.edu *
262914Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
272914Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are
282914Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright
292914Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
302914Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
313091Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
323091Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution;
333091Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its
342914Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from
352914Ssaidi@eecs.umich.edu * this software without specific prior written permission.
363091Sstever@eecs.umich.edu *
373091Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
382914Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
392914Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
402914Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
412914Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
422914Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
432914Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
442914Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
453091Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
463091Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
473091Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
483091Sstever@eecs.umich.edu *
493091Sstever@eecs.umich.edu * Authors: Gabe Black
503091Sstever@eecs.umich.edu *          Andreas Hansson
513091Sstever@eecs.umich.edu */
523091Sstever@eecs.umich.edu
533091Sstever@eecs.umich.edu#ifndef __ARCH_X86_INTERRUPTS_HH__
543091Sstever@eecs.umich.edu#define __ARCH_X86_INTERRUPTS_HH__
553091Sstever@eecs.umich.edu
563091Sstever@eecs.umich.edu#include "arch/x86/regs/apic.hh"
573091Sstever@eecs.umich.edu#include "arch/x86/faults.hh"
582914Ssaidi@eecs.umich.edu#include "arch/x86/intmessage.hh"
592914Ssaidi@eecs.umich.edu#include "base/bitfield.hh"
602914Ssaidi@eecs.umich.edu#include "cpu/thread_context.hh"
614490Sstever@eecs.umich.edu#include "dev/x86/intdev.hh"
624490Sstever@eecs.umich.edu#include "dev/io_device.hh"
634490Sstever@eecs.umich.edu#include "params/X86LocalApic.hh"
644490Sstever@eecs.umich.edu#include "sim/eventq.hh"
654490Sstever@eecs.umich.edu
664490Sstever@eecs.umich.educlass ThreadContext;
674490Sstever@eecs.umich.educlass BaseCPU;
684490Sstever@eecs.umich.edu
694490Sstever@eecs.umich.eduint divideFromConf(uint32_t conf);
704490Sstever@eecs.umich.edu
714490Sstever@eecs.umich.edunamespace X86ISA {
724490Sstever@eecs.umich.edu
734490Sstever@eecs.umich.eduApicRegIndex decodeAddr(Addr paddr);
743090Sstever@eecs.umich.edu
753090Sstever@eecs.umich.educlass Interrupts : public BasicPioDevice, IntDevice
764490Sstever@eecs.umich.edu{
774490Sstever@eecs.umich.edu  protected:
784490Sstever@eecs.umich.edu    // Storage for the APIC registers
794490Sstever@eecs.umich.edu    uint32_t regs[NUM_APIC_REGS];
804490Sstever@eecs.umich.edu
813091Sstever@eecs.umich.edu    BitUnion32(LVTEntry)
822914Ssaidi@eecs.umich.edu        Bitfield<7, 0> vector;
833090Sstever@eecs.umich.edu        Bitfield<10, 8> deliveryMode;
843403Ssaidi@eecs.umich.edu        Bitfield<12> status;
853403Ssaidi@eecs.umich.edu        Bitfield<13> polarity;
863403Ssaidi@eecs.umich.edu        Bitfield<14> remoteIRR;
873403Ssaidi@eecs.umich.edu        Bitfield<15> trigger;
884490Sstever@eecs.umich.edu        Bitfield<16> masked;
894490Sstever@eecs.umich.edu        Bitfield<17> periodic;
902914Ssaidi@eecs.umich.edu    EndBitUnion(LVTEntry)
914490Sstever@eecs.umich.edu
922914Ssaidi@eecs.umich.edu    /*
932914Ssaidi@eecs.umich.edu     * Timing related stuff.
942914Ssaidi@eecs.umich.edu     */
952914Ssaidi@eecs.umich.edu    class ApicTimerEvent : public Event
962914Ssaidi@eecs.umich.edu    {
974490Sstever@eecs.umich.edu      private:
984490Sstever@eecs.umich.edu        Interrupts *localApic;
994490Sstever@eecs.umich.edu      public:
1004490Sstever@eecs.umich.edu        ApicTimerEvent(Interrupts *_localApic) :
1013403Ssaidi@eecs.umich.edu            Event(), localApic(_localApic)
1023403Ssaidi@eecs.umich.edu        {}
1033403Ssaidi@eecs.umich.edu
1043403Ssaidi@eecs.umich.edu        void process()
1053403Ssaidi@eecs.umich.edu        {
1062914Ssaidi@eecs.umich.edu            assert(localApic);
1072914Ssaidi@eecs.umich.edu            if (localApic->triggerTimerInterrupt()) {
1082914Ssaidi@eecs.umich.edu                localApic->setReg(APIC_INITIAL_COUNT,
1092914Ssaidi@eecs.umich.edu                        localApic->readReg(APIC_INITIAL_COUNT));
1102914Ssaidi@eecs.umich.edu            }
1113091Sstever@eecs.umich.edu        }
1123349Sbinkertn@umich.edu    };
1133091Sstever@eecs.umich.edu
1143091Sstever@eecs.umich.edu    ApicTimerEvent apicTimerEvent;
1153349Sbinkertn@umich.edu
1163091Sstever@eecs.umich.edu    /*
1173091Sstever@eecs.umich.edu     * A set of variables to keep track of interrupts that don't go through
1183091Sstever@eecs.umich.edu     * the IRR.
1193091Sstever@eecs.umich.edu     */
1203091Sstever@eecs.umich.edu    bool pendingSmi;
1213091Sstever@eecs.umich.edu    uint8_t smiVector;
1223091Sstever@eecs.umich.edu    bool pendingNmi;
1233091Sstever@eecs.umich.edu    uint8_t nmiVector;
1242914Ssaidi@eecs.umich.edu    bool pendingExtInt;
1252914Ssaidi@eecs.umich.edu    uint8_t extIntVector;
1263401Sktlim@umich.edu    bool pendingInit;
1274490Sstever@eecs.umich.edu    uint8_t initVector;
1284490Sstever@eecs.umich.edu    bool pendingStartup;
1294490Sstever@eecs.umich.edu    uint8_t startupVector;
1302914Ssaidi@eecs.umich.edu    bool startedUp;
1312914Ssaidi@eecs.umich.edu
1324490Sstever@eecs.umich.edu    // This is a quick check whether any of the above (except ExtInt) are set.
1334490Sstever@eecs.umich.edu    bool pendingUnmaskableInt;
1343091Sstever@eecs.umich.edu
1353091Sstever@eecs.umich.edu    // A count of how many IPIs are in flight.
1363091Sstever@eecs.umich.edu    int pendingIPIs;
1373091Sstever@eecs.umich.edu
1383091Sstever@eecs.umich.edu    /*
1393091Sstever@eecs.umich.edu     * IRR and ISR maintenance.
1403091Sstever@eecs.umich.edu     */
1413091Sstever@eecs.umich.edu    uint8_t IRRV;
1423091Sstever@eecs.umich.edu    uint8_t ISRV;
1433091Sstever@eecs.umich.edu
1443091Sstever@eecs.umich.edu    int
1453091Sstever@eecs.umich.edu    findRegArrayMSB(ApicRegIndex base)
1463091Sstever@eecs.umich.edu    {
1473091Sstever@eecs.umich.edu        int offset = 7;
1483091Sstever@eecs.umich.edu        do {
1493091Sstever@eecs.umich.edu            if (regs[base + offset] != 0) {
1502914Ssaidi@eecs.umich.edu                return offset * 32 + findMsbSet(regs[base + offset]);
1512914Ssaidi@eecs.umich.edu            }
1522914Ssaidi@eecs.umich.edu        } while (offset--);
1532914Ssaidi@eecs.umich.edu        return 0;
154    }
155
156    void
157    updateIRRV()
158    {
159        IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE);
160    }
161
162    void
163    updateISRV()
164    {
165        ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE);
166    }
167
168    void
169    setRegArrayBit(ApicRegIndex base, uint8_t vector)
170    {
171        regs[base + (vector / 32)] |= (1 << (vector % 32));
172    }
173
174    void
175    clearRegArrayBit(ApicRegIndex base, uint8_t vector)
176    {
177        regs[base + (vector / 32)] &= ~(1 << (vector % 32));
178    }
179
180    bool
181    getRegArrayBit(ApicRegIndex base, uint8_t vector)
182    {
183        return bits(regs[base + (vector / 32)], vector % 32);
184    }
185
186    void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
187
188    BaseCPU *cpu;
189
190    int initialApicId;
191
192    // Port for receiving interrupts
193    IntSlavePort intSlavePort;
194
195  public:
196
197    int getInitialApicId() { return initialApicId; }
198
199    /*
200     * Params stuff.
201     */
202    typedef X86LocalApicParams Params;
203
204    void setCPU(BaseCPU * newCPU);
205
206    const Params *
207    params() const
208    {
209        return dynamic_cast<const Params *>(_params);
210    }
211
212    /*
213     * Initialize this object by registering it with the IO APIC.
214     */
215    void init();
216
217    /*
218     * Functions to interact with the interrupt port from IntDevice.
219     */
220    Tick read(PacketPtr pkt);
221    Tick write(PacketPtr pkt);
222    Tick recvMessage(PacketPtr pkt);
223    Tick recvResponse(PacketPtr pkt);
224
225    bool
226    triggerTimerInterrupt()
227    {
228        LVTEntry entry = regs[APIC_LVT_TIMER];
229        if (!entry.masked)
230            requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger);
231        return entry.periodic;
232    }
233
234    AddrRangeList getIntAddrRange() const;
235
236    BaseMasterPort &getMasterPort(const std::string &if_name,
237                                  PortID idx = InvalidPortID)
238    {
239        if (if_name == "int_master") {
240            return intMasterPort;
241        }
242        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