interrupts.cc revision 5222:bb733a878f85
112855Sgabeblack@google.com/* 212855Sgabeblack@google.com * Copyright .AN) 2007 MIPS Technologies, Inc. All Rights Reserved 312855Sgabeblack@google.com * 412855Sgabeblack@google.com * This software is part of the M5 simulator. 512855Sgabeblack@google.com * 612855Sgabeblack@google.com * THIS IS A LEGAL AGREEMENT. BY DOWNLOADING, USING, COPYING, CREATING 712855Sgabeblack@google.com * DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING 812855Sgabeblack@google.com * TO THESE TERMS AND CONDITIONS. 912855Sgabeblack@google.com * 1012855Sgabeblack@google.com * Permission is granted to use, copy, create derivative works and 1112855Sgabeblack@google.com * distribute this software and such derivative works for any purpose, 1212855Sgabeblack@google.com * so long as (1) the copyright notice above, this grant of permission, 1312855Sgabeblack@google.com * and the disclaimer below appear in all copies and derivative works 1412855Sgabeblack@google.com * made, (2) the copyright notice above is augmented as appropriate to 1512855Sgabeblack@google.com * reflect the addition of any new copyrightable work in a derivative 1612855Sgabeblack@google.com * work (e.g., Copyright .AN) <Publication Year> Copyright Owner), and (3) 1712855Sgabeblack@google.com * the name of MIPS Technologies, Inc. ($B!H(BMIPS$B!I(B) is not used in any 1812855Sgabeblack@google.com * advertising or publicity pertaining to the use or distribution of 1912855Sgabeblack@google.com * this software without specific, written prior authorization. 2012855Sgabeblack@google.com * 2112855Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED $B!H(BAS IS.$B!I(B MIPS MAKES NO WARRANTIES AND 2212855Sgabeblack@google.com * DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR 2312855Sgabeblack@google.com * OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 2412855Sgabeblack@google.com * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND 2512855Sgabeblack@google.com * NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE. 2612855Sgabeblack@google.com * IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, 2712855Sgabeblack@google.com * INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF 2812855Sgabeblack@google.com * ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT, 2912855Sgabeblack@google.com * THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY 3012855Sgabeblack@google.com * IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR 3112855Sgabeblack@google.com * STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE 3212855Sgabeblack@google.com * POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE. 3312855Sgabeblack@google.com * 3412855Sgabeblack@google.com * Authors: Richard Strong 3512855Sgabeblack@google.com */ 3612855Sgabeblack@google.com 3712855Sgabeblack@google.com 3812855Sgabeblack@google.com#include "arch/mips/pra_constants.hh" 3912855Sgabeblack@google.com#include "arch/mips/isa_traits.hh" 4012855Sgabeblack@google.com#include "cpu/thread_context.hh" 4112855Sgabeblack@google.com#include "arch/mips/interrupts.hh" 4212855Sgabeblack@google.com 4312855Sgabeblack@google.comnamespace MipsISA 4412855Sgabeblack@google.com{ 4512855Sgabeblack@google.comstatic inline uint8_t getCauseIP_(ThreadContext *tc) { 4612855Sgabeblack@google.com MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); 4712855Sgabeblack@google.com uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0); 4812855Sgabeblack@google.com return IP_; 4912855Sgabeblack@google.com} 5012855Sgabeblack@google.com 5112855Sgabeblack@google.comstatic inline void setCauseIP_(ThreadContext *tc, uint8_t val) { 5212855Sgabeblack@google.com MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); 5312855Sgabeblack@google.com replaceBits(cause,Cause_IP7,Cause_IP0,val); 5412855Sgabeblack@google.com tc->setMiscRegNoEffect(MipsISA::Cause,cause); 5512855Sgabeblack@google.com} 5612855Sgabeblack@google.com 5712855Sgabeblack@google.com/* 5812855Sgabeblack@google.com void Interrupts::post(int int_num, int index) 5912855Sgabeblack@google.com { 6012855Sgabeblack@google.com DPRINTF(Interrupt, "Interrupt %d posted\n", int_num); 6112855Sgabeblack@google.com 6212855Sgabeblack@google.com //index should not be used 6312855Sgabeblack@google.com assert(index == 0); 6412855Sgabeblack@google.com 6512855Sgabeblack@google.com if (int_num < 0 || int_num >= NumInterruptLevels) 6612855Sgabeblack@google.com panic("int_num out of bounds\n"); 6712855Sgabeblack@google.com intstatus |= 1 << int_num; 6812855Sgabeblack@google.com } 6912855Sgabeblack@google.com 7012855Sgabeblack@google.com void Interrupts::clear(int int_num, int index) 7112855Sgabeblack@google.com { 7212855Sgabeblack@google.com DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num); 7312855Sgabeblack@google.com 7412855Sgabeblack@google.com //index should not be used 7512855Sgabeblack@google.com assert(index == 0); 7612855Sgabeblack@google.com 7712855Sgabeblack@google.com if (int_num < 0 || int_num >= NumInterruptLevels) 7812855Sgabeblack@google.com panic("int_num out of bounds\n"); 7912855Sgabeblack@google.com 8012855Sgabeblack@google.com intstatus &= ~(1 << int_num); 8112855Sgabeblack@google.com } 82 83 void Interrupts::clear_all() 84 { 85 DPRINTF(Interrupt, "Interrupts all cleared\n"); 86 intstatus = 0; 87 } 88 89 90 91 Fault Interrupts::getInterrupt(ThreadContext * tc) 92 { 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 98 if (oncputimerintr){ 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){ 106 clear(IPTI, 0); 107 oncputimerintr=false; 108 } 109 } 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 118 post(IPTI, 0); 119 oncputimerintr=true; 120 } 121 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 127 { 128 // Software interrupts & hardware interrupts are handled in software. 129 // So if any interrupt that isn't masked is detected, jump to interrupt 130 // handler 131 uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending 132 IM = bits(status,Status_IM7,Status_IM0); 133 IP = intstatus; 134 //IM and IP are already correctly aligned 135 if (IM & IP){ 136 DPRINTF(Flow, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n", 137 IM, IP); 138 return new InterruptFault; 139 } 140 } 141 142 return NoFault; 143 144 } 145 146 void Interrupts::updateIntrInfo(ThreadContext *tc) const 147 { 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); 152 } 153 154 bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const 155 { 156 MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare); 157 MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count); 158 if (compare == count) 159 return true; 160 return false; 161 } 162 163 164 uint64_t Interrupts::get_vec(int int_num) 165 { 166 panic("MipsISA::Interrupts::get_vec() is not implemented. \n"); 167 M5_DUMMY_RETURN 168 } 169*/ 170void Interrupts::post(int int_num, ThreadContext* tc) 171{ 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"); 175 176 uint8_t intstatus= getCauseIP_(tc); 177 intstatus |= 1 << int_num; 178 setCauseIP_(tc, intstatus); 179} 180 181void Interrupts::post(int int_num, int index) 182{ 183 fatal("Must use Thread COntext when posting MIPS Interrupts in M5"); 184} 185 186void Interrupts::clear(int int_num, ThreadContext* tc) 187{ 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"); 191 192 uint8_t intstatus = getCauseIP_(tc); 193 intstatus &= ~(1 << int_num); 194 setCauseIP_(tc, intstatus); 195} 196 197void Interrupts::clear(int int_num, int index) 198{ 199 fatal("Must use Thread COntext when clearing MIPS Interrupts in M5"); 200} 201 202void Interrupts::clear_all(ThreadContext *tc) 203{ 204 DPRINTF(Interrupt, "Interrupts all cleared\n"); 205 uint8_t intstatus = 0; 206 setCauseIP_(tc, intstatus); 207} 208 209void Interrupts::clear_all() 210{ 211 fatal("Must use Thread COntext when clearing MIPS Interrupts in M5"); 212} 213 214 215 216Fault Interrupts::getInterrupt(ThreadContext * tc) 217{ 218 DPRINTF(Interrupt, "Interrupts getInterrupt\n"); 219 220 221 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 227 { 228 // Software interrupts & hardware interrupts are handled in software. 229 // So if any interrupt that isn't masked is detected, jump to interrupt 230 // handler 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 235 if (IM & IP){ 236 DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n", 237 IM, IP); 238 return new InterruptFault; 239 } 240 } 241 242 return NoFault; 243 244} 245bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const 246{ 247 MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare); 248 MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count); 249 if (compare == count && count != 0) 250 return true; 251 return false; 252} 253void Interrupts::updateIntrInfo(ThreadContext *tc) const 254{ 255 //Nothing needs to be done. 256 ; 257} 258 259uint64_t Interrupts::get_vec(int int_num) 260{ 261 panic("MipsISA::Interrupts::get_vec() is not implemented. \n"); 262 M5_DUMMY_RETURN 263 } 264 265bool Interrupts::interruptsPending(ThreadContext *tc) const 266{ 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 275 //post(IPTI, tc); 276 uint8_t intstatus= getCauseIP_(tc); 277 intstatus |= 1 << IPTI; 278 setCauseIP_(tc, intstatus); 279 } 280 281 return (getCauseIP_(tc) != 0); 282 283} 284 285 286 287 288 289} 290