2 * Copyright \e.A\eN) 2007 MIPS Technologies, Inc. All Rights Reserved
4 * This software is part of the M5 simulator.
6 * THIS IS A LEGAL AGREEMENT. BY DOWNLOADING, USING, COPYING, CREATING
7 * DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING
8 * TO THESE TERMS AND CONDITIONS.
10 * Permission is granted to use, copy, create derivative works and
11 * distribute this software and such derivative works for any purpose,
12 * so long as (1) the copyright notice above, this grant of permission,
13 * and the disclaimer below appear in all copies and derivative works
14 * made, (2) the copyright notice above is augmented as appropriate to
15 * reflect the addition of any new copyrightable work in a derivative
16 * work (e.g., Copyright \e.A\eN) <Publication Year> Copyright Owner), and (3)
17 * the name of MIPS Technologies, Inc. (\e$B!H\e(BMIPS\e$B!I\e(B) is not used in any
18 * advertising or publicity pertaining to the use or distribution of
19 * this software without specific, written prior authorization.
21 * THIS SOFTWARE IS PROVIDED \e$B!H\e(BAS IS.\e$B!I\e(B MIPS MAKES NO WARRANTIES AND
22 * DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR
23 * OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
25 * NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE.
26 * IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT,
27 * INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF
28 * ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT,
29 * THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY
30 * IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR
31 * STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE
32 * POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE.
34 * Authors: Richard Strong
38 #include "arch/mips/pra_constants.hh"
39 #include "arch/mips/isa_traits.hh"
40 #include "cpu/thread_context.hh"
41 #include "arch/mips/interrupts.hh"
45 static inline uint8_t getCauseIP_(ThreadContext
*tc
) {
46 MiscReg cause
= tc
->readMiscRegNoEffect(MipsISA::Cause
);
47 uint8_t IP_
= bits(cause
,Cause_IP7
, Cause_IP0
);
51 static inline void setCauseIP_(ThreadContext
*tc
, uint8_t val
) {
52 MiscReg cause
= tc
->readMiscRegNoEffect(MipsISA::Cause
);
53 replaceBits(cause
,Cause_IP7
,Cause_IP0
,val
);
54 tc
->setMiscRegNoEffect(MipsISA::Cause
,cause
);
58 void Interrupts::post(int int_num, int index)
60 DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
62 //index should not be used
65 if (int_num < 0 || int_num >= NumInterruptLevels)
66 panic("int_num out of bounds\n");
67 intstatus |= 1 << int_num;
70 void Interrupts::clear(int int_num, int index)
72 DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
74 //index should not be used
77 if (int_num < 0 || int_num >= NumInterruptLevels)
78 panic("int_num out of bounds\n");
80 intstatus &= ~(1 << int_num);
83 void Interrupts::clear_all()
85 DPRINTF(Interrupt, "Interrupts all cleared\n");
91 Fault Interrupts::getInterrupt(ThreadContext * tc)
93 DPRINTF(Interrupt, "Interrupts getInterrupt\n");
94 // If a timer interrupt has occured, check to see if a
95 // mtc0 to Compare register caused this interrupt to
96 // be cleared. If this is the case, clear intstatus
97 // bit for timer interrupt
99 DPRINTF(Interrupt, "Interrupts oncputimerintr==true\n");
100 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
101 uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
102 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
103 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
104 //mtc0 to compare must have cleared bit in IP
105 if ( ((1 << IPTI) & IP_) == 0){
107 oncputimerintr=false;
110 //if there is a on cpu timer interrupt (i.e. Compare == Count)
111 //update intstatus before proceeding to interrupt
112 if (onCpuTimerInterrupt(tc)){
113 DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
114 //determine timer interrupt IP #
115 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
116 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
117 //set intstatus to correspond
122 //Check if there are any outstanding interrupts
123 MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
124 if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled
125 bits(status, Status_ERL) == 0 && //error level must be 0 or interrupts inhibited
126 bits(status, Status_EXL) == 0 ) //exception level must be 0 or interrupts inhibited
128 // Software interrupts & hardware interrupts are handled in software.
129 // So if any interrupt that isn't masked is detected, jump to interrupt
131 uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending
132 IM = bits(status,Status_IM7,Status_IM0);
134 //IM and IP are already correctly aligned
136 DPRINTF(Flow, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
138 return new InterruptFault;
146 void Interrupts::updateIntrInfo(ThreadContext *tc) const
148 //Merge Interrupts.intstatus with mips MipISA::Status
149 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
150 replaceBits(cause,Cause_IP7,Cause_IP0,intstatus);
151 tc->setMiscRegNoEffect(MipsISA::Cause,cause);
154 bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
156 MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
157 MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
158 if (compare == count)
164 uint64_t Interrupts::get_vec(int int_num)
166 panic("MipsISA::Interrupts::get_vec() is not implemented. \n");
170 void Interrupts::post(int int_num
, ThreadContext
* tc
)
172 DPRINTF(Interrupt
, "Interrupt %d posted\n", int_num
);
173 if (int_num
< 0 || int_num
>= NumInterruptLevels
)
174 panic("int_num out of bounds\n");
176 uint8_t intstatus
= getCauseIP_(tc
);
177 intstatus
|= 1 << int_num
;
178 setCauseIP_(tc
, intstatus
);
181 void Interrupts::post(int int_num
, int index
)
183 fatal("Must use Thread COntext when posting MIPS Interrupts in M5");
186 void Interrupts::clear(int int_num
, ThreadContext
* tc
)
188 DPRINTF(Interrupt
, "Interrupt %d cleared\n", int_num
);
189 if (int_num
< 0 || int_num
>= NumInterruptLevels
)
190 panic("int_num out of bounds\n");
192 uint8_t intstatus
= getCauseIP_(tc
);
193 intstatus
&= ~(1 << int_num
);
194 setCauseIP_(tc
, intstatus
);
197 void Interrupts::clear(int int_num
, int index
)
199 fatal("Must use Thread COntext when clearing MIPS Interrupts in M5");
202 void Interrupts::clear_all(ThreadContext
*tc
)
204 DPRINTF(Interrupt
, "Interrupts all cleared\n");
205 uint8_t intstatus
= 0;
206 setCauseIP_(tc
, intstatus
);
209 void Interrupts::clear_all()
211 fatal("Must use Thread COntext when clearing MIPS Interrupts in M5");
216 Fault
Interrupts::getInterrupt(ThreadContext
* tc
)
218 DPRINTF(Interrupt
, "Interrupts getInterrupt\n");
222 //Check if there are any outstanding interrupts
223 MiscReg status
= tc
->readMiscRegNoEffect(MipsISA::Status
);
224 if (bits(status
, Status_IE_LO
) == 1 && //interrupts must be enabled
225 bits(status
, Status_ERL_HI
,Status_ERL_LO
) == 0 && //error level must be 0 or interrupts inhibited
226 bits(status
, Status_EXL_HI
,Status_EXL_LO
) == 0 ) //exception level must be 0 or interrupts inhibited
228 // Software interrupts & hardware interrupts are handled in software.
229 // So if any interrupt that isn't masked is detected, jump to interrupt
231 uint8_t IM
, IP
; //IM=interrupt mask, IP=interrupt pending
232 IM
= bits(status
,Status_IM7
,Status_IM0
);
233 IP
= getCauseIP_(tc
);
234 //IM and IP are already correctly aligned
236 DPRINTF(Interrupt
, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
238 return new InterruptFault
;
245 bool Interrupts::onCpuTimerInterrupt(ThreadContext
* tc
) const
247 MiscReg compare
= tc
->readMiscRegNoEffect(MipsISA::Compare
);
248 MiscReg count
= tc
->readMiscRegNoEffect(MipsISA::Count
);
249 if (compare
== count
&& count
!= 0)
253 void Interrupts::updateIntrInfo(ThreadContext
*tc
) const
255 //Nothing needs to be done.
259 uint64_t Interrupts::get_vec(int int_num
)
261 panic("MipsISA::Interrupts::get_vec() is not implemented. \n");
265 bool Interrupts::interruptsPending(ThreadContext
*tc
) const
267 //if there is a on cpu timer interrupt (i.e. Compare == Count)
268 //update CauseIP before proceeding to interrupt
269 if (onCpuTimerInterrupt(tc
)){
270 DPRINTF(Interrupt
, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
271 //determine timer interrupt IP #
272 MiscReg intctl
= tc
->readMiscRegNoEffect(MipsISA::IntCtl
);
273 uint8_t IPTI
= bits(intctl
, IntCtl_IPTI_HI
, IntCtl_IPTI_LO
);
274 //set intstatus to correspond
276 uint8_t intstatus
= getCauseIP_(tc
);
277 intstatus
|= 1 << IPTI
;
278 setCauseIP_(tc
, intstatus
);
281 return (getCauseIP_(tc
) != 0);