interrupts.hh revision 4028:e936c7dc2d68
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef __ARCH_SPARC_INTERRUPT_HH__
30#define __ARCH_SPARC_INTERRUPT_HH__
31
32#include "arch/sparc/faults.hh"
33#include "cpu/thread_context.hh"
34
35namespace SparcISA
36{
37
38enum interrupts_t {
39    trap_level_zero,
40    hstick_match,
41    interrupt_vector,
42    cpu_mondo,
43    dev_mondo,
44    resumable_error,
45    soft_interrupt,
46    num_interrupt_types
47};
48
49class Interrupts
50{
51
52  private:
53
54    bool interrupts[num_interrupt_types];
55    int numPosted;
56
57  public:
58    Interrupts()
59    {
60        for (int i = 0; i < num_interrupt_types; ++i) {
61            interrupts[i] = false;
62        }
63        numPosted = 0;
64    }
65
66    void post(int int_type)
67    {
68        if (int_type < 0 || int_type >= num_interrupt_types)
69            panic("posting unknown interrupt!\n");
70        if (interrupts[int_type] == false) {
71            interrupts[int_type] = true;
72            ++numPosted;
73        }
74    }
75
76    void post(int int_num, int index)
77    {
78
79    }
80
81    void clear(int int_num, int index)
82    {
83
84    }
85
86    void clear_all()
87    {
88
89    }
90
91    bool check_interrupts(ThreadContext * tc) const
92    {
93        if (numPosted)
94            return true;
95        else
96            return false;
97    }
98
99    Fault getInterrupt(ThreadContext * tc)
100    {
101        int hpstate = tc->readMiscReg(MISCREG_HPSTATE);
102        int pstate = tc->readMiscReg(MISCREG_PSTATE);
103        bool ie = pstate & PSTATE::ie;
104
105        // THESE ARE IN ORDER OF PRIORITY
106        // since there are early returns, and the highest
107        // priority interrupts should get serviced,
108        // it is v. important that new interrupts are inserted
109        // in the right order of processing
110        if (hpstate & HPSTATE::hpriv) {
111            if (ie) {
112                if (interrupts[hstick_match]) {
113                    if (tc->readMiscReg(MISCREG_HINTP) & 1) {
114                        interrupts[hstick_match] = false;
115                        --numPosted;
116                        return new HstickMatch;
117                    }
118                }
119                if (interrupts[interrupt_vector]) {
120                    interrupts[interrupt_vector] = false;
121                    --numPosted;
122                    //HAVEN'T IMPLed THIS YET
123                    return NoFault;
124                }
125            } else {
126                if (interrupts[hstick_match]) {
127                    return NoFault;
128                }
129
130            }
131        } else {
132            if (interrupts[trap_level_zero]) {
133                if ((pstate & HPSTATE::tlz) && (tc->readMiscReg(MISCREG_TL) == 0)) {
134                    interrupts[trap_level_zero] = false;
135                    --numPosted;
136                    return new TrapLevelZero;
137                }
138            }
139            if (interrupts[hstick_match]) {
140                if (tc->readMiscReg(MISCREG_HINTP) & 1) {
141                    interrupts[hstick_match] = false;
142                    --numPosted;
143                    return new HstickMatch;
144                    }
145            }
146            if (ie) {
147                if (interrupts[cpu_mondo]) {
148                    interrupts[cpu_mondo] = false;
149                    --numPosted;
150                    return new CpuMondo;
151                }
152                if (interrupts[dev_mondo]) {
153                    interrupts[dev_mondo] = false;
154                    --numPosted;
155                    return new DevMondo;
156                }
157                if (interrupts[soft_interrupt]) {
158                    int il = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
159                    // it seems that interrupt vectors are right in
160                    // the middle of interrupt levels with regard to
161                    // priority, so have to check
162                    if ((il < 6) &&
163                        interrupts[interrupt_vector]) {
164                            // may require more details here since there
165                            // may be lots of interrupts embedded in an
166                            // platform interrupt vector
167                            interrupts[interrupt_vector] = false;
168                            --numPosted;
169                            //HAVEN'T IMPLed YET
170                            return NoFault;
171                    } else {
172                        if (il > tc->readMiscReg(MISCREG_PIL)) {
173                            uint64_t si = tc->readMiscReg(MISCREG_SOFTINT);
174                            uint64_t more = si & ~(1 << (il + 1));
175                            if (!InterruptLevel(more)) {
176                                interrupts[soft_interrupt] = false;
177                                --numPosted;
178                            }
179                            return new InterruptLevelN(il);
180                        }
181                    }
182                }
183                if (interrupts[resumable_error]) {
184                    interrupts[resumable_error] = false;
185                    --numPosted;
186                    return new ResumableError;
187                }
188            }
189        }
190        return NoFault;
191    }
192
193    void updateIntrInfo(ThreadContext * tc)
194    {
195
196    }
197
198    void serialize(std::ostream &os)
199    {
200        SERIALIZE_ARRAY(interrupts,num_interrupt_types);
201        SERIALIZE_SCALAR(numPosted);
202    }
203
204    void unserialize(Checkpoint *cp, const std::string &section)
205    {
206        UNSERIALIZE_ARRAY(interrupts,num_interrupt_types);
207        UNSERIALIZE_SCALAR(numPosted);
208    }
209};
210} // namespace SPARC_ISA
211
212#endif // __ARCH_SPARC_INTERRUPT_HH__
213