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