interrupts.cc (5704:98224505352a) | interrupts.cc (6378:4a2ff62c3b4f) |
---|---|
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 --- 24 unchanged lines hidden (view full) --- 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{ | 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 --- 24 unchanged lines hidden (view full) --- 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) { | 41 42static inline uint8_t 43getCauseIP(ThreadContext *tc) { |
42 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); | 44 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); |
43 uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0); 44 return IP_; | 45 return bits(cause, Cause_IP7, Cause_IP0); |
45} 46 | 46} 47 |
47static inline void setCauseIP_(ThreadContext *tc, uint8_t val) { | 48static inline void 49setCauseIP_(ThreadContext *tc, uint8_t val) { |
48 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); | 50 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); |
49 replaceBits(cause,Cause_IP7,Cause_IP0,val); 50 tc->setMiscRegNoEffect(MipsISA::Cause,cause); | 51 replaceBits(cause, Cause_IP7, Cause_IP0, val); 52 tc->setMiscRegNoEffect(MipsISA::Cause, cause); |
51} 52 | 53} 54 |
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::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) | 55void 56Interrupts::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 | 57{ 58 DPRINTF(Interrupt, "Interrupt %d posted\n", int_num); 59 if (int_num < 0 || int_num >= NumInterruptLevels) 60 panic("int_num out of bounds\n"); 61 |
166 uint8_t intstatus= getCauseIP_(tc); | 62 uint8_t intstatus = getCauseIP(tc); |
167 intstatus |= 1 << int_num; | 63 intstatus |= 1 << int_num; |
168 setCauseIP_(tc, intstatus); | 64 setCauseIP(tc, intstatus); |
169} 170 | 65} 66 |
171void Interrupts::post(int int_num, int index) | 67void 68Interrupts::post(int int_num, int index) |
172{ | 69{ |
173 fatal("Must use Thread COntext when posting MIPS Interrupts in M5"); | 70 fatal("Must use Thread Context when posting MIPS Interrupts in M5"); |
174} 175 | 71} 72 |
176void Interrupts::clear(int int_num, ThreadContext* tc) | 73void 74Interrupts::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 | 75{ 76 DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num); 77 if (int_num < 0 || int_num >= NumInterruptLevels) 78 panic("int_num out of bounds\n"); 79 |
182 uint8_t intstatus = getCauseIP_(tc); | 80 uint8_t intstatus = getCauseIP(tc); |
183 intstatus &= ~(1 << int_num); | 81 intstatus &= ~(1 << int_num); |
184 setCauseIP_(tc, intstatus); | 82 setCauseIP(tc, intstatus); |
185} 186 | 83} 84 |
187void Interrupts::clear(int int_num, int index) | 85void 86Interrupts::clear(int int_num, int index) |
188{ | 87{ |
189 fatal("Must use Thread COntext when clearing MIPS Interrupts in M5"); | 88 fatal("Must use Thread Context when clearing MIPS Interrupts in M5"); |
190} 191 | 89} 90 |
192void Interrupts::clearAll(ThreadContext *tc) | 91void 92Interrupts::clearAll(ThreadContext *tc) |
193{ 194 DPRINTF(Interrupt, "Interrupts all cleared\n"); 195 uint8_t intstatus = 0; | 93{ 94 DPRINTF(Interrupt, "Interrupts all cleared\n"); 95 uint8_t intstatus = 0; |
196 setCauseIP_(tc, intstatus); | 96 setCauseIP(tc, intstatus); |
197} 198 | 97} 98 |
199void Interrupts::clearAll() | 99void 100Interrupts::clearAll() |
200{ | 101{ |
201 fatal("Must use Thread COntext when clearing MIPS Interrupts in M5"); | 102 fatal("Must use Thread Context when clearing MIPS Interrupts in M5"); |
202} 203 204 205 | 103} 104 105 106 |
206Fault Interrupts::getInterrupt(ThreadContext * tc) | 107Fault 108Interrupts::getInterrupt(ThreadContext * tc) |
207{ 208 DPRINTF(Interrupt, "Interrupts getInterrupt\n"); 209 | 109{ 110 DPRINTF(Interrupt, "Interrupts getInterrupt\n"); 111 |
210 211 | |
212 //Check if there are any outstanding interrupts 213 MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status); | 112 //Check if there are any outstanding interrupts 113 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 { | 114 // Interrupts must be enabled, error level must be 0 or interrupts 115 // inhibited, and exception level must be 0 or interrupts inhibited 116 if (bits(status, Status_IE_LO) == 1 && 117 bits(status, Status_ERL_HI, Status_ERL_LO) == 0 && 118 bits(status, Status_EXL_HI, Status_EXL_LO) == 0) { |
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 | 119 // Software interrupts & hardware interrupts are handled in software. 120 // So if any interrupt that isn't masked is detected, jump to interrupt 121 // 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){ | 122 uint8_t InterruptMask = bits(status, Status_IM7, Status_IM0); 123 uint8_t InterruptPending = getCauseIP(tc); 124 // InterruptMask and InterruptPending are already correctly aligned 125 if (InterruptMask && InterruptPending){ |
226 DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n", | 126 DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n", |
227 IM, IP); | 127 InterruptMask, InterruptPending); |
228 return new InterruptFault; 229 } 230 } 231 232 return NoFault; | 128 return new InterruptFault; 129 } 130 } 131 132 return NoFault; |
233 | |
234} | 133} |
235bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const | 134 135bool 136Interrupts::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} | 137{ 138 MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare); 139 MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count); 140 if (compare == count && count != 0) 141 return true; 142 return false; 143} |
243void Interrupts::updateIntrInfo(ThreadContext *tc) const | 144 145void 146Interrupts::updateIntrInfo(ThreadContext *tc) const |
244{ 245 //Nothing needs to be done. | 147{ 148 //Nothing needs to be done. |
246 ; | |
247} 248 | 149} 150 |
249bool Interrupts::interruptsPending(ThreadContext *tc) const | 151bool 152Interrupts::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 | 153{ 154 //if there is a on cpu timer interrupt (i.e. Compare == Count) 155 //update CauseIP before proceeding to interrupt |
253 if (onCpuTimerInterrupt(tc)){ 254 DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n"); | 156 if (onCpuTimerInterrupt(tc)) { 157 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); | 158 //determine timer interrupt IP # 159 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl); 160 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO); 161 //set intstatus to correspond 162 //post(IPTI, tc); |
260 uint8_t intstatus= getCauseIP_(tc); | 163 uint8_t intstatus = getCauseIP(tc); |
261 intstatus |= 1 << IPTI; | 164 intstatus |= 1 << IPTI; |
262 setCauseIP_(tc, intstatus); | 165 setCauseIP(tc, intstatus); |
263 } 264 | 166 } 167 |
265 return (getCauseIP_(tc) != 0); | 168 return (getCauseIP(tc) != 0); |
266 267} 268 | 169 170} 171 |
269 270 271 272 | |
273} | 172} |