interrupts.hh revision 5655
1/*
2 * Copyright (c) 2007 The Hewlett-Packard Development Company
3 * All rights reserved.
4 *
5 * Redistribution and use of this software in source and binary forms,
6 * with or without modification, are permitted provided that the
7 * following conditions are met:
8 *
9 * The software must be used only for Non-Commercial Use which means any
10 * use which is NOT directed to receiving any direct monetary
11 * compensation for, or commercial advantage from such use.  Illustrative
12 * examples of non-commercial use are academic research, personal study,
13 * teaching, education and corporate research & development.
14 * Illustrative examples of commercial use are distributing products for
15 * commercial advantage and providing services using the software for
16 * commercial advantage.
17 *
18 * If you wish to use this software or functionality therein that may be
19 * covered by patents for commercial use, please contact:
20 *     Director of Intellectual Property Licensing
21 *     Office of Strategy and Technology
22 *     Hewlett-Packard Company
23 *     1501 Page Mill Road
24 *     Palo Alto, California  94304
25 *
26 * Redistributions of source code must retain the above copyright notice,
27 * this list of conditions and the following disclaimer.  Redistributions
28 * in binary form must reproduce the above copyright notice, this list of
29 * conditions and the following disclaimer in the documentation and/or
30 * other materials provided with the distribution.  Neither the name of
31 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
32 * contributors may be used to endorse or promote products derived from
33 * this software without specific prior written permission.  No right of
34 * sublicense is granted herewith.  Derivatives of the software and
35 * output created using the software may be prepared, but only for
36 * Non-Commercial Uses.  Derivatives of the software may be shared with
37 * others provided: (i) the others agree to abide by the list of
38 * conditions herein which includes the Non-Commercial Use restrictions;
39 * and (ii) such Derivatives of the software include the above copyright
40 * notice to acknowledge the contribution from this software where
41 * applicable, this list of conditions and the disclaimer below.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 *
55 * Authors: Gabe Black
56 */
57
58#ifndef __ARCH_X86_INTERRUPTS_HH__
59#define __ARCH_X86_INTERRUPTS_HH__
60
61#include "arch/x86/apicregs.hh"
62#include "arch/x86/faults.hh"
63#include "arch/x86/intmessage.hh"
64#include "base/bitfield.hh"
65#include "cpu/thread_context.hh"
66#include "dev/io_device.hh"
67#include "dev/x86/intdev.hh"
68#include "params/X86LocalApic.hh"
69#include "sim/eventq.hh"
70
71class ThreadContext;
72
73namespace X86ISA
74{
75
76class Interrupts : public BasicPioDevice, IntDev
77{
78  protected:
79    // Storage for the APIC registers
80    uint32_t regs[NUM_APIC_REGS];
81
82    /*
83     * Timing related stuff.
84     */
85    Tick latency;
86    Tick clock;
87
88    class ApicTimerEvent : public Event
89    {
90      public:
91        ApicTimerEvent() : Event()
92        {}
93
94        void process()
95        {
96            warn("Local APIC timer event doesn't do anything!\n");
97        }
98    };
99
100    ApicTimerEvent apicTimerEvent;
101
102    /*
103     * A set of variables to keep track of interrupts that don't go through
104     * the IRR.
105     */
106    bool pendingSmi;
107    TriggerIntMessage smiMessage;
108    bool pendingNmi;
109    TriggerIntMessage nmiMessage;
110    bool pendingExtInt;
111    TriggerIntMessage extIntMessage;
112    bool pendingInit;
113    TriggerIntMessage initMessage;
114
115    // This is a quick check whether any of the above (except ExtInt) are set.
116    bool pendingUnmaskableInt;
117
118    /*
119     * IRR and ISR maintenance.
120     */
121    uint8_t IRRV;
122    uint8_t ISRV;
123
124    int
125    findRegArrayMSB(ApicRegIndex base)
126    {
127        int offset = 7;
128        do {
129            if (regs[base + offset] != 0) {
130                return offset * 32 + findMsbSet(regs[base + offset]);
131            }
132        } while (offset--);
133        return 0;
134    }
135
136    void
137    updateIRRV()
138    {
139        IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE);
140    }
141
142    void
143    updateISRV()
144    {
145        ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE);
146    }
147
148    void
149    setRegArrayBit(ApicRegIndex base, uint8_t vector)
150    {
151        regs[base + (vector % 32)] |= (1 << (vector >> 5));
152    }
153
154    void
155    clearRegArrayBit(ApicRegIndex base, uint8_t vector)
156    {
157        regs[base + (vector % 32)] &= ~(1 << (vector >> 5));
158    }
159
160    bool
161    getRegArrayBit(ApicRegIndex base, uint8_t vector)
162    {
163        return bits(regs[base + (vector % 32)], vector >> 5);
164    }
165
166  public:
167    /*
168     * Params stuff.
169     */
170    typedef X86LocalApicParams Params;
171
172    void setClock(Tick newClock)
173    {
174        clock = newClock;
175    }
176
177    const Params *
178    params() const
179    {
180        return dynamic_cast<const Params *>(_params);
181    }
182
183    /*
184     * Functions to interact with the interrupt port from IntDev.
185     */
186    Tick read(PacketPtr pkt);
187    Tick write(PacketPtr pkt);
188    Tick recvMessage(PacketPtr pkt);
189
190    void addressRanges(AddrRangeList &range_list)
191    {
192        range_list.clear();
193        range_list.push_back(RangeEx(x86LocalAPICAddress(0, 0),
194                                     x86LocalAPICAddress(0, 0) + PageBytes));
195    }
196
197    void getIntAddrRange(AddrRangeList &range_list)
198    {
199        range_list.clear();
200        range_list.push_back(RangeEx(x86InterruptAddress(0, 0),
201                    x86InterruptAddress(0, 0) + PhysAddrAPICRangeSize));
202    }
203
204    Port *getPort(const std::string &if_name, int idx = -1)
205    {
206        if (if_name == "int_port")
207            return intPort;
208        return BasicPioDevice::getPort(if_name, idx);
209    }
210
211    /*
212     * Functions to access and manipulate the APIC's registers.
213     */
214
215    uint32_t readReg(ApicRegIndex miscReg);
216    void setReg(ApicRegIndex reg, uint32_t val);
217    void setRegNoEffect(ApicRegIndex reg, uint32_t val)
218    {
219        regs[reg] = val;
220    }
221
222    /*
223     * Constructor.
224     */
225
226    Interrupts(Params * p) : BasicPioDevice(p), IntDev(this),
227                             latency(p->pio_latency), clock(0),
228                             pendingSmi(false), smiMessage(0),
229                             pendingNmi(false), nmiMessage(0),
230                             pendingExtInt(false), extIntMessage(0),
231                             pendingInit(false), initMessage(0),
232                             pendingUnmaskableInt(false)
233    {
234        pioSize = PageBytes;
235        memset(regs, 0, sizeof(regs));
236        //Set the local apic DFR to the flat model.
237        regs[APIC_DESTINATION_FORMAT] = (uint32_t)(-1);
238        ISRV = 0;
239        IRRV = 0;
240    }
241
242    /*
243     * Functions for retrieving interrupts for the CPU to handle.
244     */
245
246    bool check_interrupts(ThreadContext * tc) const;
247    Fault getInterrupt(ThreadContext * tc);
248    void updateIntrInfo(ThreadContext * tc);
249
250    /*
251     * Serialization.
252     */
253
254    void serialize(std::ostream & os)
255    {
256        panic("Interrupts::serialize unimplemented!\n");
257    }
258
259    void unserialize(Checkpoint * cp, const std::string & section)
260    {
261        panic("Interrupts::unserialize unimplemented!\n");
262    }
263
264    /*
265     * Old functions needed for compatability but which will be phased out
266     * eventually.
267     */
268    void post(int int_num, int index)
269    {
270        panic("Interrupts::post unimplemented!\n");
271    }
272
273    void clear(int int_num, int index)
274    {
275        panic("Interrupts::clear unimplemented!\n");
276    }
277
278    void clear_all()
279    {
280        panic("Interrupts::clear_all unimplemented!\n");
281    }
282};
283
284};
285
286#endif // __ARCH_X86_INTERRUPTS_HH__
287