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