interrupts.hh revision 6050:852ba59fa8d9
15470Snate@binkert.org/*
25470Snate@binkert.org * Copyright (c) 2007 The Hewlett-Packard Development Company
35470Snate@binkert.org * All rights reserved.
45470Snate@binkert.org *
55470Snate@binkert.org * Redistribution and use of this software in source and binary forms,
65470Snate@binkert.org * with or without modification, are permitted provided that the
75470Snate@binkert.org * following conditions are met:
85470Snate@binkert.org *
95470Snate@binkert.org * The software must be used only for Non-Commercial Use which means any
105470Snate@binkert.org * use which is NOT directed to receiving any direct monetary
115470Snate@binkert.org * compensation for, or commercial advantage from such use.  Illustrative
125470Snate@binkert.org * examples of non-commercial use are academic research, personal study,
135470Snate@binkert.org * teaching, education and corporate research & development.
145470Snate@binkert.org * Illustrative examples of commercial use are distributing products for
155470Snate@binkert.org * commercial advantage and providing services using the software for
165470Snate@binkert.org * commercial advantage.
175470Snate@binkert.org *
185470Snate@binkert.org * If you wish to use this software or functionality therein that may be
195470Snate@binkert.org * covered by patents for commercial use, please contact:
205470Snate@binkert.org *     Director of Intellectual Property Licensing
215470Snate@binkert.org *     Office of Strategy and Technology
225470Snate@binkert.org *     Hewlett-Packard Company
235470Snate@binkert.org *     1501 Page Mill Road
245470Snate@binkert.org *     Palo Alto, California  94304
255470Snate@binkert.org *
265470Snate@binkert.org * Redistributions of source code must retain the above copyright notice,
275470Snate@binkert.org * this list of conditions and the following disclaimer.  Redistributions
285470Snate@binkert.org * in binary form must reproduce the above copyright notice, this list of
295470Snate@binkert.org * conditions and the following disclaimer in the documentation and/or
305470Snate@binkert.org * other materials provided with the distribution.  Neither the name of
315470Snate@binkert.org * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
325470Snate@binkert.org * contributors may be used to endorse or promote products derived from
335470Snate@binkert.org * this software without specific prior written permission.  No right of
345470Snate@binkert.org * sublicense is granted herewith.  Derivatives of the software and
355470Snate@binkert.org * output created using the software may be prepared, but only for
365470Snate@binkert.org * Non-Commercial Uses.  Derivatives of the software may be shared with
375470Snate@binkert.org * others provided: (i) the others agree to abide by the list of
385470Snate@binkert.org * conditions herein which includes the Non-Commercial Use restrictions;
395470Snate@binkert.org * and (ii) such Derivatives of the software include the above copyright
405470Snate@binkert.org * notice to acknowledge the contribution from this software where
415470Snate@binkert.org * applicable, this list of conditions and the disclaimer below.
425470Snate@binkert.org *
435470Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
445470Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
455470Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
465470Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
475586Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
485470Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
495470Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
505470Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
515470Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
525470Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
535470Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
545470Snate@binkert.org *
555470Snate@binkert.org * Authors: Gabe Black
565470Snate@binkert.org */
575470Snate@binkert.org
585586Snate@binkert.org#ifndef __ARCH_X86_INTERRUPTS_HH__
595586Snate@binkert.org#define __ARCH_X86_INTERRUPTS_HH__
605586Snate@binkert.org
615470Snate@binkert.org#include "arch/x86/apicregs.hh"
625470Snate@binkert.org#include "arch/x86/faults.hh"
635470Snate@binkert.org#include "arch/x86/intmessage.hh"
645470Snate@binkert.org#include "base/bitfield.hh"
655470Snate@binkert.org#include "cpu/thread_context.hh"
665470Snate@binkert.org#include "dev/io_device.hh"
675470Snate@binkert.org#include "dev/x86/intdev.hh"
685470Snate@binkert.org#include "params/X86LocalApic.hh"
695470Snate@binkert.org#include "sim/eventq.hh"
705470Snate@binkert.org
715470Snate@binkert.orgclass ThreadContext;
725470Snate@binkert.orgclass BaseCPU;
735470Snate@binkert.org
745470Snate@binkert.orgnamespace X86ISA {
755470Snate@binkert.org
765470Snate@binkert.orgclass Interrupts : public BasicPioDevice, IntDev
775470Snate@binkert.org{
785470Snate@binkert.org  protected:
795470Snate@binkert.org    // Storage for the APIC registers
805470Snate@binkert.org    uint32_t regs[NUM_APIC_REGS];
815470Snate@binkert.org
825470Snate@binkert.org    BitUnion32(LVTEntry)
835470Snate@binkert.org        Bitfield<7, 0> vector;
845470Snate@binkert.org        Bitfield<10, 8> deliveryMode;
855470Snate@binkert.org        Bitfield<12> status;
865470Snate@binkert.org        Bitfield<13> polarity;
875470Snate@binkert.org        Bitfield<14> remoteIRR;
885470Snate@binkert.org        Bitfield<15> trigger;
895470Snate@binkert.org        Bitfield<16> masked;
905470Snate@binkert.org        Bitfield<17> periodic;
915470Snate@binkert.org    EndBitUnion(LVTEntry)
925470Snate@binkert.org
935470Snate@binkert.org    /*
945470Snate@binkert.org     * Timing related stuff.
955470Snate@binkert.org     */
965470Snate@binkert.org    Tick latency;
975470Snate@binkert.org    Tick clock;
985470Snate@binkert.org
995470Snate@binkert.org    class ApicTimerEvent : public Event
1005470Snate@binkert.org    {
1015470Snate@binkert.org      private:
1025470Snate@binkert.org        Interrupts *localApic;
1035470Snate@binkert.org      public:
1045470Snate@binkert.org        ApicTimerEvent(Interrupts *_localApic) :
1055470Snate@binkert.org            Event(), localApic(_localApic)
1065470Snate@binkert.org        {}
1075470Snate@binkert.org
1085470Snate@binkert.org        void process()
1095470Snate@binkert.org        {
1105470Snate@binkert.org            assert(localApic);
1115586Snate@binkert.org            if (localApic->triggerTimerInterrupt()) {
1125470Snate@binkert.org                localApic->setReg(APIC_INITIAL_COUNT,
1135586Snate@binkert.org                        localApic->readReg(APIC_INITIAL_COUNT));
1145586Snate@binkert.org            }
1155470Snate@binkert.org        }
1165586Snate@binkert.org    };
1175470Snate@binkert.org
1185470Snate@binkert.org    ApicTimerEvent apicTimerEvent;
1195470Snate@binkert.org
1205586Snate@binkert.org    /*
1215586Snate@binkert.org     * A set of variables to keep track of interrupts that don't go through
1225586Snate@binkert.org     * the IRR.
1235586Snate@binkert.org     */
1245586Snate@binkert.org    bool pendingSmi;
1255586Snate@binkert.org    uint8_t smiVector;
1265586Snate@binkert.org    bool pendingNmi;
1275586Snate@binkert.org    uint8_t nmiVector;
1285470Snate@binkert.org    bool pendingExtInt;
1295470Snate@binkert.org    uint8_t extIntVector;
1305470Snate@binkert.org    bool pendingInit;
1315470Snate@binkert.org    uint8_t initVector;
1325470Snate@binkert.org    bool pendingStartup;
1335586Snate@binkert.org    uint8_t startupVector;
1345586Snate@binkert.org
1355470Snate@binkert.org    // This is a quick check whether any of the above (except ExtInt) are set.
1365470Snate@binkert.org    bool pendingUnmaskableInt;
1375470Snate@binkert.org
1385470Snate@binkert.org    /*
1395470Snate@binkert.org     * IRR and ISR maintenance.
1405470Snate@binkert.org     */
1415470Snate@binkert.org    uint8_t IRRV;
1425470Snate@binkert.org    uint8_t ISRV;
143
144    int
145    findRegArrayMSB(ApicRegIndex base)
146    {
147        int offset = 7;
148        do {
149            if (regs[base + offset] != 0) {
150                return offset * 32 + findMsbSet(regs[base + offset]);
151            }
152        } while (offset--);
153        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 >> 5));
172    }
173
174    void
175    clearRegArrayBit(ApicRegIndex base, uint8_t vector)
176    {
177        regs[base + (vector % 32)] &= ~(1 << (vector >> 5));
178    }
179
180    bool
181    getRegArrayBit(ApicRegIndex base, uint8_t vector)
182    {
183        return bits(regs[base + (vector % 32)], vector >> 5);
184    }
185
186    void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
187
188    BaseCPU *cpu;
189
190  public:
191    /*
192     * Params stuff.
193     */
194    typedef X86LocalApicParams Params;
195
196    void setCPU(BaseCPU * newCPU);
197
198    void
199    setClock(Tick newClock)
200    {
201        clock = newClock;
202    }
203
204    const Params *
205    params() const
206    {
207        return dynamic_cast<const Params *>(_params);
208    }
209
210    /*
211     * Functions to interact with the interrupt port from IntDev.
212     */
213    Tick read(PacketPtr pkt);
214    Tick write(PacketPtr pkt);
215    Tick recvMessage(PacketPtr pkt);
216
217    bool
218    triggerTimerInterrupt()
219    {
220        LVTEntry entry = regs[APIC_LVT_TIMER];
221        if (!entry.masked)
222            requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger);
223        return entry.periodic;
224    }
225
226    void addressRanges(AddrRangeList &range_list);
227    void getIntAddrRange(AddrRangeList &range_list);
228
229    Port *getPort(const std::string &if_name, int idx = -1)
230    {
231        if (if_name == "int_port")
232            return intPort;
233        return BasicPioDevice::getPort(if_name, idx);
234    }
235
236    /*
237     * Functions to access and manipulate the APIC's registers.
238     */
239
240    uint32_t readReg(ApicRegIndex miscReg);
241    void setReg(ApicRegIndex reg, uint32_t val);
242    void
243    setRegNoEffect(ApicRegIndex reg, uint32_t val)
244    {
245        regs[reg] = val;
246    }
247
248    /*
249     * Constructor.
250     */
251
252    Interrupts(Params * p);
253
254    /*
255     * Functions for retrieving interrupts for the CPU to handle.
256     */
257
258    bool checkInterrupts(ThreadContext *tc) const;
259    Fault getInterrupt(ThreadContext *tc);
260    void updateIntrInfo(ThreadContext *tc);
261
262    /*
263     * Serialization.
264     */
265
266    void
267    serialize(std::ostream &os)
268    {
269        panic("Interrupts::serialize unimplemented!\n");
270    }
271
272    void
273    unserialize(Checkpoint *cp, const std::string &section)
274    {
275        panic("Interrupts::unserialize unimplemented!\n");
276    }
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