interrupts.hh revision 8839
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2007 The Hewlett-Packard Development Company
15 * All rights reserved.
16 *
17 * The license below extends only to copyright in the software and shall
18 * not be construed as granting a license to any other intellectual
19 * property including but not limited to intellectual property relating
20 * to a hardware implementation of the functionality of the software
21 * licensed hereunder.  You may use the software subject to the license
22 * terms below provided that you ensure that this notice is replicated
23 * unmodified and in its entirety in all distributions of the software,
24 * modified or unmodified, in source code or in binary form.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions are
28 * met: redistributions of source code must retain the above copyright
29 * notice, this list of conditions and the following disclaimer;
30 * redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer in the
32 * documentation and/or other materials provided with the distribution;
33 * neither the name of the copyright holders nor the names of its
34 * contributors may be used to endorse or promote products derived from
35 * this software without specific prior written permission.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
38 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
39 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
40 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
41 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
45 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 *
49 * Authors: Gabe Black
50 *          Andreas Hansson
51 */
52
53#ifndef __ARCH_X86_INTERRUPTS_HH__
54#define __ARCH_X86_INTERRUPTS_HH__
55
56#include "arch/x86/regs/apic.hh"
57#include "arch/x86/faults.hh"
58#include "arch/x86/intmessage.hh"
59#include "base/bitfield.hh"
60#include "cpu/thread_context.hh"
61#include "dev/x86/intdev.hh"
62#include "dev/io_device.hh"
63#include "params/X86LocalApic.hh"
64#include "sim/eventq.hh"
65
66class ThreadContext;
67class BaseCPU;
68
69namespace X86ISA {
70
71class Interrupts : public BasicPioDevice, IntDev
72{
73  protected:
74    // Storage for the APIC registers
75    uint32_t regs[NUM_APIC_REGS];
76
77    BitUnion32(LVTEntry)
78        Bitfield<7, 0> vector;
79        Bitfield<10, 8> deliveryMode;
80        Bitfield<12> status;
81        Bitfield<13> polarity;
82        Bitfield<14> remoteIRR;
83        Bitfield<15> trigger;
84        Bitfield<16> masked;
85        Bitfield<17> periodic;
86    EndBitUnion(LVTEntry)
87
88    /*
89     * Timing related stuff.
90     */
91    Tick latency;
92    Tick clock;
93
94    class ApicTimerEvent : public Event
95    {
96      private:
97        Interrupts *localApic;
98      public:
99        ApicTimerEvent(Interrupts *_localApic) :
100            Event(), localApic(_localApic)
101        {}
102
103        void process()
104        {
105            assert(localApic);
106            if (localApic->triggerTimerInterrupt()) {
107                localApic->setReg(APIC_INITIAL_COUNT,
108                        localApic->readReg(APIC_INITIAL_COUNT));
109            }
110        }
111    };
112
113    ApicTimerEvent apicTimerEvent;
114
115    /*
116     * A set of variables to keep track of interrupts that don't go through
117     * the IRR.
118     */
119    bool pendingSmi;
120    uint8_t smiVector;
121    bool pendingNmi;
122    uint8_t nmiVector;
123    bool pendingExtInt;
124    uint8_t extIntVector;
125    bool pendingInit;
126    uint8_t initVector;
127    bool pendingStartup;
128    uint8_t startupVector;
129    bool startedUp;
130
131    // This is a quick check whether any of the above (except ExtInt) are set.
132    bool pendingUnmaskableInt;
133
134    // A count of how many IPIs are in flight.
135    int pendingIPIs;
136
137    /*
138     * IRR and ISR maintenance.
139     */
140    uint8_t IRRV;
141    uint8_t ISRV;
142
143    int
144    findRegArrayMSB(ApicRegIndex base)
145    {
146        int offset = 7;
147        do {
148            if (regs[base + offset] != 0) {
149                return offset * 32 + findMsbSet(regs[base + offset]);
150            }
151        } while (offset--);
152        return 0;
153    }
154
155    void
156    updateIRRV()
157    {
158        IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE);
159    }
160
161    void
162    updateISRV()
163    {
164        ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE);
165    }
166
167    void
168    setRegArrayBit(ApicRegIndex base, uint8_t vector)
169    {
170        regs[base + (vector / 32)] |= (1 << (vector % 32));
171    }
172
173    void
174    clearRegArrayBit(ApicRegIndex base, uint8_t vector)
175    {
176        regs[base + (vector / 32)] &= ~(1 << (vector % 32));
177    }
178
179    bool
180    getRegArrayBit(ApicRegIndex base, uint8_t vector)
181    {
182        return bits(regs[base + (vector / 32)], vector % 5);
183    }
184
185    void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
186
187    BaseCPU *cpu;
188
189    int initialApicId;
190
191  public:
192
193    int getInitialApicId() { return initialApicId; }
194
195    /*
196     * Params stuff.
197     */
198    typedef X86LocalApicParams Params;
199
200    void setCPU(BaseCPU * newCPU);
201
202    void
203    setClock(Tick newClock)
204    {
205        clock = newClock;
206    }
207
208    const Params *
209    params() const
210    {
211        return dynamic_cast<const Params *>(_params);
212    }
213
214    /*
215     * Initialize this object by registering it with the IO APIC.
216     */
217    void init();
218
219    /*
220     * Functions to interact with the interrupt port from IntDev.
221     */
222    Tick read(PacketPtr pkt);
223    Tick write(PacketPtr pkt);
224    Tick recvMessage(PacketPtr pkt);
225    Tick recvResponse(PacketPtr pkt);
226
227    bool
228    triggerTimerInterrupt()
229    {
230        LVTEntry entry = regs[APIC_LVT_TIMER];
231        if (!entry.masked)
232            requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger);
233        return entry.periodic;
234    }
235
236    AddrRangeList getAddrRanges();
237    AddrRangeList getIntAddrRange();
238
239    Port *getPort(const std::string &if_name, int idx = -1)
240    {
241        // a bit of an odd one since there is now two ports in the
242        // Python class we also need two ports even if they are
243        // identical
244        if (if_name == "int_master") {
245            return intPort;
246        } else if (if_name == "int_slave") {
247            // memory leak...but will be removed in the next patch
248            return new IntPort(name() + ".int_slave", this, this, latency);
249        }
250        return BasicPioDevice::getPort(if_name, idx);
251    }
252
253    /*
254     * Functions to access and manipulate the APIC's registers.
255     */
256
257    uint32_t readReg(ApicRegIndex miscReg);
258    void setReg(ApicRegIndex reg, uint32_t val);
259    void
260    setRegNoEffect(ApicRegIndex reg, uint32_t val)
261    {
262        regs[reg] = val;
263    }
264
265    /*
266     * Constructor.
267     */
268
269    Interrupts(Params * p);
270
271    /*
272     * Functions for retrieving interrupts for the CPU to handle.
273     */
274
275    bool checkInterrupts(ThreadContext *tc) const;
276    Fault getInterrupt(ThreadContext *tc);
277    void updateIntrInfo(ThreadContext *tc);
278
279    /*
280     * Serialization.
281     */
282
283    virtual void serialize(std::ostream &os);
284    virtual void unserialize(Checkpoint *cp, const std::string &section);
285
286    /*
287     * Old functions needed for compatability but which will be phased out
288     * eventually.
289     */
290    void
291    post(int int_num, int index)
292    {
293        panic("Interrupts::post unimplemented!\n");
294    }
295
296    void
297    clear(int int_num, int index)
298    {
299        panic("Interrupts::clear unimplemented!\n");
300    }
301
302    void
303    clearAll()
304    {
305        panic("Interrupts::clearAll unimplemented!\n");
306    }
307};
308
309} // namespace X86ISA
310
311#endif // __ARCH_X86_INTERRUPTS_HH__
312