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