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