interrupts.cc (5646:0a488a147fb8) interrupts.cc (5704:98224505352a)
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * Copyright (c) 2007 MIPS Technologies, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Steve Reinhardt
30 * Kevin Lim
31 * Korey Sewell
32 */
33
34#include "arch/mips/pra_constants.hh"
35#include "arch/mips/isa_traits.hh"
36#include "cpu/thread_context.hh"
37#include "arch/mips/interrupts.hh"
38
39namespace MipsISA
40{
41static inline uint8_t getCauseIP_(ThreadContext *tc) {
42 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
43 uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
44 return IP_;
45}
46
47static inline void setCauseIP_(ThreadContext *tc, uint8_t val) {
48 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
49 replaceBits(cause,Cause_IP7,Cause_IP0,val);
50 tc->setMiscRegNoEffect(MipsISA::Cause,cause);
51}
52
53/*
54 void Interrupts::post(int int_num, int index)
55 {
56 DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
57
58 //index should not be used
59 assert(index == 0);
60
61 if (int_num < 0 || int_num >= NumInterruptLevels)
62 panic("int_num out of bounds\n");
63 intstatus |= 1 << int_num;
64 }
65
66 void Interrupts::clear(int int_num, int index)
67 {
68 DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
69
70 //index should not be used
71 assert(index == 0);
72
73 if (int_num < 0 || int_num >= NumInterruptLevels)
74 panic("int_num out of bounds\n");
75
76 intstatus &= ~(1 << int_num);
77 }
78
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * Copyright (c) 2007 MIPS Technologies, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Steve Reinhardt
30 * Kevin Lim
31 * Korey Sewell
32 */
33
34#include "arch/mips/pra_constants.hh"
35#include "arch/mips/isa_traits.hh"
36#include "cpu/thread_context.hh"
37#include "arch/mips/interrupts.hh"
38
39namespace MipsISA
40{
41static inline uint8_t getCauseIP_(ThreadContext *tc) {
42 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
43 uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
44 return IP_;
45}
46
47static inline void setCauseIP_(ThreadContext *tc, uint8_t val) {
48 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
49 replaceBits(cause,Cause_IP7,Cause_IP0,val);
50 tc->setMiscRegNoEffect(MipsISA::Cause,cause);
51}
52
53/*
54 void Interrupts::post(int int_num, int index)
55 {
56 DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
57
58 //index should not be used
59 assert(index == 0);
60
61 if (int_num < 0 || int_num >= NumInterruptLevels)
62 panic("int_num out of bounds\n");
63 intstatus |= 1 << int_num;
64 }
65
66 void Interrupts::clear(int int_num, int index)
67 {
68 DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
69
70 //index should not be used
71 assert(index == 0);
72
73 if (int_num < 0 || int_num >= NumInterruptLevels)
74 panic("int_num out of bounds\n");
75
76 intstatus &= ~(1 << int_num);
77 }
78
79 void Interrupts::clear_all()
79 void Interrupts::clearAll()
80 {
81 DPRINTF(Interrupt, "Interrupts all cleared\n");
82 intstatus = 0;
83 }
84
85
86
87 Fault Interrupts::getInterrupt(ThreadContext * tc)
88 {
89 DPRINTF(Interrupt, "Interrupts getInterrupt\n");
90 // If a timer interrupt has occured, check to see if a
91 // mtc0 to Compare register caused this interrupt to
92 // be cleared. If this is the case, clear intstatus
93 // bit for timer interrupt
94 if (oncputimerintr){
95 DPRINTF(Interrupt, "Interrupts oncputimerintr==true\n");
96 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
97 uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
98 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
99 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
100 //mtc0 to compare must have cleared bit in IP
101 if ( ((1 << IPTI) & IP_) == 0){
102 clear(IPTI, 0);
103 oncputimerintr=false;
104 }
105 }
106 //if there is a on cpu timer interrupt (i.e. Compare == Count)
107 //update intstatus before proceeding to interrupt
108 if (onCpuTimerInterrupt(tc)){
109 DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
110 //determine timer interrupt IP #
111 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
112 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
113 //set intstatus to correspond
114 post(IPTI, 0);
115 oncputimerintr=true;
116 }
117
118 //Check if there are any outstanding interrupts
119 MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
120 if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled
121 bits(status, Status_ERL) == 0 && //error level must be 0 or interrupts inhibited
122 bits(status, Status_EXL) == 0 ) //exception level must be 0 or interrupts inhibited
123 {
124 // Software interrupts & hardware interrupts are handled in software.
125 // So if any interrupt that isn't masked is detected, jump to interrupt
126 // handler
127 uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending
128 IM = bits(status,Status_IM7,Status_IM0);
129 IP = intstatus;
130 //IM and IP are already correctly aligned
131 if (IM & IP){
132 DPRINTF(Flow, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
133 IM, IP);
134 return new InterruptFault;
135 }
136 }
137
138 return NoFault;
139
140 }
141
142 void Interrupts::updateIntrInfo(ThreadContext *tc) const
143 {
144 //Merge Interrupts.intstatus with mips MipISA::Status
145 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
146 replaceBits(cause,Cause_IP7,Cause_IP0,intstatus);
147 tc->setMiscRegNoEffect(MipsISA::Cause,cause);
148 }
149
150 bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
151 {
152 MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
153 MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
154 if (compare == count)
155 return true;
156 return false;
157 }
158
159*/
160void Interrupts::post(int int_num, ThreadContext* tc)
161{
162 DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
163 if (int_num < 0 || int_num >= NumInterruptLevels)
164 panic("int_num out of bounds\n");
165
166 uint8_t intstatus= getCauseIP_(tc);
167 intstatus |= 1 << int_num;
168 setCauseIP_(tc, intstatus);
169}
170
171void Interrupts::post(int int_num, int index)
172{
173 fatal("Must use Thread COntext when posting MIPS Interrupts in M5");
174}
175
176void Interrupts::clear(int int_num, ThreadContext* tc)
177{
178 DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
179 if (int_num < 0 || int_num >= NumInterruptLevels)
180 panic("int_num out of bounds\n");
181
182 uint8_t intstatus = getCauseIP_(tc);
183 intstatus &= ~(1 << int_num);
184 setCauseIP_(tc, intstatus);
185}
186
187void Interrupts::clear(int int_num, int index)
188{
189 fatal("Must use Thread COntext when clearing MIPS Interrupts in M5");
190}
191
80 {
81 DPRINTF(Interrupt, "Interrupts all cleared\n");
82 intstatus = 0;
83 }
84
85
86
87 Fault Interrupts::getInterrupt(ThreadContext * tc)
88 {
89 DPRINTF(Interrupt, "Interrupts getInterrupt\n");
90 // If a timer interrupt has occured, check to see if a
91 // mtc0 to Compare register caused this interrupt to
92 // be cleared. If this is the case, clear intstatus
93 // bit for timer interrupt
94 if (oncputimerintr){
95 DPRINTF(Interrupt, "Interrupts oncputimerintr==true\n");
96 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
97 uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
98 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
99 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
100 //mtc0 to compare must have cleared bit in IP
101 if ( ((1 << IPTI) & IP_) == 0){
102 clear(IPTI, 0);
103 oncputimerintr=false;
104 }
105 }
106 //if there is a on cpu timer interrupt (i.e. Compare == Count)
107 //update intstatus before proceeding to interrupt
108 if (onCpuTimerInterrupt(tc)){
109 DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
110 //determine timer interrupt IP #
111 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
112 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
113 //set intstatus to correspond
114 post(IPTI, 0);
115 oncputimerintr=true;
116 }
117
118 //Check if there are any outstanding interrupts
119 MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
120 if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled
121 bits(status, Status_ERL) == 0 && //error level must be 0 or interrupts inhibited
122 bits(status, Status_EXL) == 0 ) //exception level must be 0 or interrupts inhibited
123 {
124 // Software interrupts & hardware interrupts are handled in software.
125 // So if any interrupt that isn't masked is detected, jump to interrupt
126 // handler
127 uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending
128 IM = bits(status,Status_IM7,Status_IM0);
129 IP = intstatus;
130 //IM and IP are already correctly aligned
131 if (IM & IP){
132 DPRINTF(Flow, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
133 IM, IP);
134 return new InterruptFault;
135 }
136 }
137
138 return NoFault;
139
140 }
141
142 void Interrupts::updateIntrInfo(ThreadContext *tc) const
143 {
144 //Merge Interrupts.intstatus with mips MipISA::Status
145 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
146 replaceBits(cause,Cause_IP7,Cause_IP0,intstatus);
147 tc->setMiscRegNoEffect(MipsISA::Cause,cause);
148 }
149
150 bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
151 {
152 MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
153 MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
154 if (compare == count)
155 return true;
156 return false;
157 }
158
159*/
160void Interrupts::post(int int_num, ThreadContext* tc)
161{
162 DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
163 if (int_num < 0 || int_num >= NumInterruptLevels)
164 panic("int_num out of bounds\n");
165
166 uint8_t intstatus= getCauseIP_(tc);
167 intstatus |= 1 << int_num;
168 setCauseIP_(tc, intstatus);
169}
170
171void Interrupts::post(int int_num, int index)
172{
173 fatal("Must use Thread COntext when posting MIPS Interrupts in M5");
174}
175
176void Interrupts::clear(int int_num, ThreadContext* tc)
177{
178 DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
179 if (int_num < 0 || int_num >= NumInterruptLevels)
180 panic("int_num out of bounds\n");
181
182 uint8_t intstatus = getCauseIP_(tc);
183 intstatus &= ~(1 << int_num);
184 setCauseIP_(tc, intstatus);
185}
186
187void Interrupts::clear(int int_num, int index)
188{
189 fatal("Must use Thread COntext when clearing MIPS Interrupts in M5");
190}
191
192void Interrupts::clear_all(ThreadContext *tc)
192void Interrupts::clearAll(ThreadContext *tc)
193{
194 DPRINTF(Interrupt, "Interrupts all cleared\n");
195 uint8_t intstatus = 0;
196 setCauseIP_(tc, intstatus);
197}
198
193{
194 DPRINTF(Interrupt, "Interrupts all cleared\n");
195 uint8_t intstatus = 0;
196 setCauseIP_(tc, intstatus);
197}
198
199void Interrupts::clear_all()
199void Interrupts::clearAll()
200{
201 fatal("Must use Thread COntext when clearing MIPS Interrupts in M5");
202}
203
204
205
206Fault Interrupts::getInterrupt(ThreadContext * tc)
207{
208 DPRINTF(Interrupt, "Interrupts getInterrupt\n");
209
210
211
212 //Check if there are any outstanding interrupts
213 MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
214 if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled
215 bits(status, Status_ERL_HI,Status_ERL_LO) == 0 && //error level must be 0 or interrupts inhibited
216 bits(status, Status_EXL_HI,Status_EXL_LO) == 0 ) //exception level must be 0 or interrupts inhibited
217 {
218 // Software interrupts & hardware interrupts are handled in software.
219 // So if any interrupt that isn't masked is detected, jump to interrupt
220 // handler
221 uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending
222 IM = bits(status,Status_IM7,Status_IM0);
223 IP = getCauseIP_(tc);
224 //IM and IP are already correctly aligned
225 if (IM & IP){
226 DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
227 IM, IP);
228 return new InterruptFault;
229 }
230 }
231
232 return NoFault;
233
234}
235bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
236{
237 MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
238 MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
239 if (compare == count && count != 0)
240 return true;
241 return false;
242}
243void Interrupts::updateIntrInfo(ThreadContext *tc) const
244{
245 //Nothing needs to be done.
246 ;
247}
248
249bool Interrupts::interruptsPending(ThreadContext *tc) const
250{
251 //if there is a on cpu timer interrupt (i.e. Compare == Count)
252 //update CauseIP before proceeding to interrupt
253 if (onCpuTimerInterrupt(tc)){
254 DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
255 //determine timer interrupt IP #
256 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
257 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
258 //set intstatus to correspond
259 //post(IPTI, tc);
260 uint8_t intstatus= getCauseIP_(tc);
261 intstatus |= 1 << IPTI;
262 setCauseIP_(tc, intstatus);
263 }
264
265 return (getCauseIP_(tc) != 0);
266
267}
268
269
270
271
272
273}
200{
201 fatal("Must use Thread COntext when clearing MIPS Interrupts in M5");
202}
203
204
205
206Fault Interrupts::getInterrupt(ThreadContext * tc)
207{
208 DPRINTF(Interrupt, "Interrupts getInterrupt\n");
209
210
211
212 //Check if there are any outstanding interrupts
213 MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
214 if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled
215 bits(status, Status_ERL_HI,Status_ERL_LO) == 0 && //error level must be 0 or interrupts inhibited
216 bits(status, Status_EXL_HI,Status_EXL_LO) == 0 ) //exception level must be 0 or interrupts inhibited
217 {
218 // Software interrupts & hardware interrupts are handled in software.
219 // So if any interrupt that isn't masked is detected, jump to interrupt
220 // handler
221 uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending
222 IM = bits(status,Status_IM7,Status_IM0);
223 IP = getCauseIP_(tc);
224 //IM and IP are already correctly aligned
225 if (IM & IP){
226 DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
227 IM, IP);
228 return new InterruptFault;
229 }
230 }
231
232 return NoFault;
233
234}
235bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
236{
237 MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
238 MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
239 if (compare == count && count != 0)
240 return true;
241 return false;
242}
243void Interrupts::updateIntrInfo(ThreadContext *tc) const
244{
245 //Nothing needs to be done.
246 ;
247}
248
249bool Interrupts::interruptsPending(ThreadContext *tc) const
250{
251 //if there is a on cpu timer interrupt (i.e. Compare == Count)
252 //update CauseIP before proceeding to interrupt
253 if (onCpuTimerInterrupt(tc)){
254 DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
255 //determine timer interrupt IP #
256 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
257 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
258 //set intstatus to correspond
259 //post(IPTI, tc);
260 uint8_t intstatus= getCauseIP_(tc);
261 intstatus |= 1 << IPTI;
262 setCauseIP_(tc, intstatus);
263 }
264
265 return (getCauseIP_(tc) != 0);
266
267}
268
269
270
271
272
273}