faults.cc revision 8568:83f728db3332
1/* 2 * Copyright (c) 2003-2005 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: Gabe Black 30 * Korey Sewell 31 * Jaidev Patwardhan 32 */ 33 34#include "arch/mips/faults.hh" 35#include "arch/mips/pra_constants.hh" 36#include "base/trace.hh" 37#include "cpu/base.hh" 38#include "cpu/thread_context.hh" 39#include "debug/MipsPRA.hh" 40 41#if !FULL_SYSTEM 42#include "mem/page_table.hh" 43#include "sim/process.hh" 44#endif 45 46namespace MipsISA 47{ 48 49typedef MipsFaultBase::FaultVals FaultVals; 50 51template <> FaultVals MipsFault<MachineCheckFault>::vals = 52 { "Machine Check", 0x0401 }; 53 54template <> FaultVals MipsFault<ResetFault>::vals = 55#if FULL_SYSTEM 56 { "Reset Fault", 0xBFC00000}; 57#else 58 { "Reset Fault", 0x001}; 59#endif 60 61template <> FaultVals MipsFault<AddressErrorFault>::vals = 62 { "Address Error", 0x0180 }; 63 64template <> FaultVals MipsFault<StoreAddressErrorFault>::vals = 65 { "Store Address Error", 0x0180 }; 66 67template <> FaultVals MipsFault<SystemCallFault>::vals = 68 { "Syscall", 0x0180 }; 69 70template <> FaultVals MipsFault<CoprocessorUnusableFault>::vals = 71 { "Coprocessor Unusable Fault", 0x180 }; 72 73template <> FaultVals MipsFault<ReservedInstructionFault>::vals = 74 { "Reserved Instruction Fault", 0x0180 }; 75 76template <> FaultVals MipsFault<ThreadFault>::vals = 77 { "Thread Fault", 0x00F1 }; 78 79template <> FaultVals MipsFault<IntegerOverflowFault>::vals = 80 { "Integer Overflow Exception", 0x180 }; 81 82template <> FaultVals MipsFault<InterruptFault>::vals = 83 { "interrupt", 0x0180 }; 84 85template <> FaultVals MipsFault<TrapFault>::vals = 86 { "Trap", 0x0180 }; 87 88template <> FaultVals MipsFault<BreakpointFault>::vals = 89 { "Breakpoint", 0x0180 }; 90 91template <> FaultVals MipsFault<ItbInvalidFault>::vals = 92 { "Invalid TLB Entry Exception (I-Fetch/LW)", 0x0180 }; 93 94template <> FaultVals MipsFault<ItbRefillFault>::vals = 95 { "TLB Refill Exception (I-Fetch/LW)", 0x0180 }; 96 97template <> FaultVals MipsFault<DtbInvalidFault>::vals = 98 { "Invalid TLB Entry Exception (Store)", 0x0180 }; 99 100template <> FaultVals MipsFault<DtbRefillFault>::vals = 101 { "TLB Refill Exception (Store)", 0x0180 }; 102 103template <> FaultVals MipsFault<TLBModifiedFault>::vals = 104 { "TLB Modified Exception", 0x0180 }; 105 106template <> FaultVals MipsFault<DspStateDisabledFault>::vals = 107 { "DSP Disabled Fault", 0x001a }; 108 109#if FULL_SYSTEM 110void 111MipsFaultBase::setHandlerPC(Addr HandlerBase, ThreadContext *tc) 112{ 113 tc->setPC(HandlerBase); 114 tc->setNextPC(HandlerBase + sizeof(MachInst)); 115 tc->setNextNPC(HandlerBase + 2 * sizeof(MachInst)); 116} 117 118void 119MipsFaultBase::setExceptionState(ThreadContext *tc, uint8_t excCode) 120{ 121 // modify SRS Ctl - Save CSS, put ESS into CSS 122 StatusReg status = tc->readMiscReg(MISCREG_STATUS); 123 if (status.exl != 1 && status.bev != 1) { 124 // SRS Ctl is modified only if Status_EXL and Status_BEV are not set 125 SRSCtlReg srsCtl = tc->readMiscReg(MISCREG_SRSCTL); 126 srsCtl.pss = srsCtl.css; 127 srsCtl.css = srsCtl.ess; 128 tc->setMiscRegNoEffect(MISCREG_SRSCTL, srsCtl); 129 } 130 131 // set EXL bit (don't care if it is already set!) 132 status.exl = 1; 133 tc->setMiscRegNoEffect(MISCREG_STATUS, status); 134 135 // write EPC 136 // CHECK ME or FIXME or FIX ME or POSSIBLE HACK 137 // Check to see if the exception occurred in the branch delay slot 138 DPRINTF(MipsPRA, "PC: %x, NextPC: %x, NNPC: %x\n", 139 tc->readPC(), tc->readNextPC(), tc->readNextNPC()); 140 int bd = 0; 141 if (tc->readPC() + sizeof(MachInst) != tc->readNextPC()) { 142 tc->setMiscRegNoEffect(MISCREG_EPC, tc->readPC() - sizeof(MachInst)); 143 // In the branch delay slot? set CAUSE_31 144 bd = 1; 145 } else { 146 tc->setMiscRegNoEffect(MISCREG_EPC, tc->readPC()); 147 // In the branch delay slot? reset CAUSE_31 148 bd = 0; 149 } 150 151 // Set Cause_EXCCODE field 152 CauseReg cause = tc->readMiscReg(MISCREG_CAUSE); 153 cause.excCode = excCode; 154 cause.bd = bd; 155 cause.ce = 0; 156 tc->setMiscRegNoEffect(MISCREG_CAUSE, cause); 157} 158 159void 160IntegerOverflowFault::invoke(ThreadContext *tc, StaticInstPtr inst) 161{ 162 DPRINTF(MipsPRA, "%s encountered.\n", name()); 163 setExceptionState(tc, 0xC); 164 165 // Set new PC 166 Addr HandlerBase; 167 StatusReg status = tc->readMiscReg(MISCREG_STATUS); 168 // Here, the handler is dependent on BEV, which is not modified by 169 // setExceptionState() 170 if (!status.bev) { 171 // See MIPS ARM Vol 3, Revision 2, Page 38 172 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE); 173 } else { 174 HandlerBase = 0xBFC00200; 175 } 176 setHandlerPC(HandlerBase, tc); 177} 178 179void 180StoreAddressErrorFault::invoke(ThreadContext *tc, StaticInstPtr inst) 181{ 182 DPRINTF(MipsPRA, "%s encountered.\n", name()); 183 setExceptionState(tc, 0x5); 184 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr); 185 186 // Set new PC 187 Addr HandlerBase; 188 // Offset 0x180 - General Exception Vector 189 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE); 190 setHandlerPC(HandlerBase, tc); 191} 192 193void 194TrapFault::invoke(ThreadContext *tc, StaticInstPtr inst) 195{ 196 DPRINTF(MipsPRA, "%s encountered.\n", name()); 197 setExceptionState(tc, 0xD); 198 199 // Set new PC 200 Addr HandlerBase; 201 // Offset 0x180 - General Exception Vector 202 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE); 203 setHandlerPC(HandlerBase, tc); 204} 205 206void 207BreakpointFault::invoke(ThreadContext *tc, StaticInstPtr inst) 208{ 209 setExceptionState(tc, 0x9); 210 211 // Set new PC 212 Addr HandlerBase; 213 // Offset 0x180 - General Exception Vector 214 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE); 215 setHandlerPC(HandlerBase, tc); 216} 217 218void 219DtbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst) 220{ 221 DPRINTF(MipsPRA, "%s encountered.\n", name()); 222 223 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr); 224 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI); 225 entryHi.asid = entryHiAsid; 226 entryHi.vpn2 = entryHiVPN2; 227 entryHi.vpn2x = entryHiVPN2X; 228 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi); 229 230 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT); 231 context.badVPN2 = contextBadVPN2; 232 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context); 233 setExceptionState(tc, 0x3); 234 235 236 // Set new PC 237 Addr HandlerBase; 238 // Offset 0x180 - General Exception Vector 239 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE); 240 setHandlerPC(HandlerBase, tc); 241} 242 243void 244AddressErrorFault::invoke(ThreadContext *tc, StaticInstPtr inst) 245{ 246 DPRINTF(MipsPRA, "%s encountered.\n", name()); 247 setExceptionState(tc, 0x4); 248 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr); 249 250 // Set new PC 251 Addr HandlerBase; 252 // Offset 0x180 - General Exception Vector 253 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE); 254 setHandlerPC(HandlerBase, tc); 255} 256 257void 258ItbInvalidFault::invoke(ThreadContext *tc, StaticInstPtr inst) 259{ 260 DPRINTF(MipsPRA, "%s encountered.\n", name()); 261 setExceptionState(tc, 0x2); 262 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr); 263 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI); 264 entryHi.asid = entryHiAsid; 265 entryHi.vpn2 = entryHiVPN2; 266 entryHi.vpn2x = entryHiVPN2X; 267 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi); 268 269 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT); 270 context.badVPN2 = contextBadVPN2; 271 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context); 272 273 274 // Set new PC 275 Addr HandlerBase; 276 // Offset 0x180 - General Exception Vector 277 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE); 278 setHandlerPC(HandlerBase,tc); 279 DPRINTF(MipsPRA, "Exception Handler At: %x , EPC set to %x\n", 280 HandlerBase, tc->readMiscReg(MISCREG_EPC)); 281} 282 283void 284ItbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst) 285{ 286 DPRINTF(MipsPRA, "%s encountered (%x).\n", name(), MISCREG_BADVADDR); 287 Addr HandlerBase; 288 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr); 289 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI); 290 entryHi.asid = entryHiAsid; 291 entryHi.vpn2 = entryHiVPN2; 292 entryHi.vpn2x = entryHiVPN2X; 293 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi); 294 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT); 295 context.badVPN2 = contextBadVPN2; 296 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context); 297 298 StatusReg status = tc->readMiscReg(MISCREG_STATUS); 299 // Since handler depends on EXL bit, must check EXL bit before setting it!! 300 // See MIPS ARM Vol 3, Revision 2, Page 38 301 if (status.exl == 1) { 302 // Offset 0x180 - General Exception Vector 303 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE); 304 } else { 305 // Offset 0x000 306 HandlerBase = tc->readMiscReg(MISCREG_EBASE); 307 } 308 309 setExceptionState(tc, 0x2); 310 setHandlerPC(HandlerBase, tc); 311} 312 313void 314DtbRefillFault::invoke(ThreadContext *tc, StaticInstPtr inst) 315{ 316 // Set new PC 317 DPRINTF(MipsPRA, "%s encountered.\n", name()); 318 Addr HandlerBase; 319 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr); 320 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI); 321 entryHi.asid = entryHiAsid; 322 entryHi.vpn2 = entryHiVPN2; 323 entryHi.vpn2x = entryHiVPN2X; 324 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi); 325 326 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT); 327 context.badVPN2 = contextBadVPN2; 328 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context); 329 330 StatusReg status = tc->readMiscReg(MISCREG_STATUS); 331 // Since handler depends on EXL bit, must check EXL bit before setting it!! 332 // See MIPS ARM Vol 3, Revision 2, Page 38 333 if (status.exl) { 334 // Offset 0x180 - General Exception Vector 335 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE); 336 } else { 337 // Offset 0x000 338 HandlerBase = tc->readMiscReg(MISCREG_EBASE); 339 } 340 341 setExceptionState(tc, 0x3); 342 343 setHandlerPC(HandlerBase, tc); 344} 345 346void 347TLBModifiedFault::invoke(ThreadContext *tc, StaticInstPtr inst) 348{ 349 DPRINTF(MipsPRA, "%s encountered.\n", name()); 350 tc->setMiscRegNoEffect(MISCREG_BADVADDR, badVAddr); 351 EntryHiReg entryHi = tc->readMiscReg(MISCREG_ENTRYHI); 352 entryHi.asid = entryHiAsid; 353 entryHi.vpn2 = entryHiVPN2; 354 entryHi.vpn2x = entryHiVPN2X; 355 tc->setMiscRegNoEffect(MISCREG_ENTRYHI, entryHi); 356 357 ContextReg context = tc->readMiscReg(MISCREG_CONTEXT); 358 context.badVPN2 = contextBadVPN2; 359 tc->setMiscRegNoEffect(MISCREG_CONTEXT, context); 360 361 // Set new PC 362 Addr HandlerBase; 363 // Offset 0x180 - General Exception Vector 364 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE); 365 setExceptionState(tc, 0x1); 366 setHandlerPC(HandlerBase, tc); 367 368} 369 370void 371SystemCallFault::invoke(ThreadContext *tc, StaticInstPtr inst) 372{ 373 DPRINTF(MipsPRA, "%s encountered.\n", name()); 374 setExceptionState(tc, 0x8); 375 376 // Set new PC 377 Addr HandlerBase; 378 // Offset 0x180 - General Exception Vector 379 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE); 380 setHandlerPC(HandlerBase, tc); 381} 382 383void 384InterruptFault::invoke(ThreadContext *tc, StaticInstPtr inst) 385{ 386#if FULL_SYSTEM 387 DPRINTF(MipsPRA, "%s encountered.\n", name()); 388 setExceptionState(tc, 0x0A); 389 Addr HandlerBase; 390 391 CauseReg cause = tc->readMiscRegNoEffect(MISCREG_CAUSE); 392 if (cause.iv) { 393 // Offset 200 for release 2 394 HandlerBase = 0x20 + vect() + tc->readMiscRegNoEffect(MISCREG_EBASE); 395 } else { 396 //Ofset at 180 for release 1 397 HandlerBase = vect() + tc->readMiscRegNoEffect(MISCREG_EBASE); 398 } 399 400 setHandlerPC(HandlerBase, tc); 401#endif 402} 403 404#endif // FULL_SYSTEM 405 406void 407ResetFault::invoke(ThreadContext *tc, StaticInstPtr inst) 408{ 409#if FULL_SYSTEM 410 DPRINTF(MipsPRA, "%s encountered.\n", name()); 411 /* All reset activity must be invoked from here */ 412 tc->setPC(vect()); 413 tc->setNextPC(vect() + sizeof(MachInst)); 414 tc->setNextNPC(vect() + sizeof(MachInst) + sizeof(MachInst)); 415 DPRINTF(MipsPRA, "ResetFault::invoke : PC set to %x", tc->readPC()); 416#endif 417 418 // Set Coprocessor 1 (Floating Point) To Usable 419 StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS); 420 status.cu.cu1 = 1; 421 tc->setMiscReg(MISCREG_STATUS, status); 422} 423 424void 425ReservedInstructionFault::invoke(ThreadContext *tc, StaticInstPtr inst) 426{ 427#if FULL_SYSTEM 428 DPRINTF(MipsPRA, "%s encountered.\n", name()); 429 setExceptionState(tc, 0x0A); 430 Addr HandlerBase; 431 // Offset 0x180 - General Exception Vector 432 HandlerBase = vect() + tc->readMiscRegNoEffect(MISCREG_EBASE); 433 setHandlerPC(HandlerBase, tc); 434#else 435 panic("%s encountered.\n", name()); 436#endif 437} 438 439void 440ThreadFault::invoke(ThreadContext *tc, StaticInstPtr inst) 441{ 442 DPRINTF(MipsPRA, "%s encountered.\n", name()); 443 panic("%s encountered.\n", name()); 444} 445 446void 447DspStateDisabledFault::invoke(ThreadContext *tc, StaticInstPtr inst) 448{ 449 DPRINTF(MipsPRA, "%s encountered.\n", name()); 450 panic("%s encountered.\n", name()); 451} 452 453void 454CoprocessorUnusableFault::invoke(ThreadContext *tc, StaticInstPtr inst) 455{ 456#if FULL_SYSTEM 457 DPRINTF(MipsPRA, "%s encountered.\n", name()); 458 setExceptionState(tc, 0xb); 459 // The ID of the coprocessor causing the exception is stored in 460 // CoprocessorUnusableFault::coProcID 461 CauseReg cause = tc->readMiscReg(MISCREG_CAUSE); 462 cause.ce = coProcID; 463 tc->setMiscRegNoEffect(MISCREG_CAUSE, cause); 464 465 Addr HandlerBase; 466 // Offset 0x180 - General Exception Vector 467 HandlerBase = vect() + tc->readMiscReg(MISCREG_EBASE); 468 setHandlerPC(HandlerBase, tc); 469 470#else 471 warn("%s (CP%d) encountered.\n", name(), coProcID); 472#endif 473} 474 475} // namespace MipsISA 476 477