faults.cc revision 3415
1/* 2 * Copyright (c) 2003-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Gabe Black 29 * Kevin Lim 30 */ 31 32#include <algorithm> 33 34#include "arch/sparc/faults.hh" 35#include "arch/sparc/isa_traits.hh" 36#include "arch/sparc/process.hh" 37#include "base/bitfield.hh" 38#include "base/trace.hh" 39#include "cpu/base.hh" 40#include "cpu/thread_context.hh" 41#if !FULL_SYSTEM 42#include "mem/page_table.hh" 43#include "sim/process.hh" 44#endif 45 46using namespace std; 47 48namespace SparcISA 49{ 50 51FaultName InternalProcessorError::_name = "intprocerr"; 52TrapType InternalProcessorError::_trapType = 0x029; 53FaultPriority InternalProcessorError::_priority = 4; 54FaultStat InternalProcessorError::_count; 55 56FaultName MemAddressNotAligned::_name = "unalign"; 57TrapType MemAddressNotAligned::_trapType = 0x034; 58FaultPriority MemAddressNotAligned::_priority = 10; 59FaultStat MemAddressNotAligned::_count; 60 61FaultName PowerOnReset::_name = "pow_reset"; 62TrapType PowerOnReset::_trapType = 0x001; 63FaultPriority PowerOnReset::_priority = 0; 64FaultStat PowerOnReset::_count; 65 66FaultName WatchDogReset::_name = "watch_dog_reset"; 67TrapType WatchDogReset::_trapType = 0x002; 68FaultPriority WatchDogReset::_priority = 1; 69FaultStat WatchDogReset::_count; 70 71FaultName ExternallyInitiatedReset::_name = "extern_reset"; 72TrapType ExternallyInitiatedReset::_trapType = 0x003; 73FaultPriority ExternallyInitiatedReset::_priority = 1; 74FaultStat ExternallyInitiatedReset::_count; 75 76FaultName SoftwareInitiatedReset::_name = "software_reset"; 77TrapType SoftwareInitiatedReset::_trapType = 0x004; 78FaultPriority SoftwareInitiatedReset::_priority = 1; 79FaultStat SoftwareInitiatedReset::_count; 80 81FaultName REDStateException::_name = "red_counte"; 82TrapType REDStateException::_trapType = 0x005; 83FaultPriority REDStateException::_priority = 1; 84FaultStat REDStateException::_count; 85 86FaultName InstructionAccessException::_name = "inst_access"; 87TrapType InstructionAccessException::_trapType = 0x008; 88FaultPriority InstructionAccessException::_priority = 5; 89FaultStat InstructionAccessException::_count; 90 91FaultName InstructionAccessMMUMiss::_name = "inst_mmu"; 92TrapType InstructionAccessMMUMiss::_trapType = 0x009; 93FaultPriority InstructionAccessMMUMiss::_priority = 2; 94FaultStat InstructionAccessMMUMiss::_count; 95 96FaultName InstructionAccessError::_name = "inst_error"; 97TrapType InstructionAccessError::_trapType = 0x00A; 98FaultPriority InstructionAccessError::_priority = 3; 99FaultStat InstructionAccessError::_count; 100 101FaultName IllegalInstruction::_name = "illegal_inst"; 102TrapType IllegalInstruction::_trapType = 0x010; 103FaultPriority IllegalInstruction::_priority = 7; 104FaultStat IllegalInstruction::_count; 105 106FaultName PrivilegedOpcode::_name = "priv_opcode"; 107TrapType PrivilegedOpcode::_trapType = 0x011; 108FaultPriority PrivilegedOpcode::_priority = 6; 109FaultStat PrivilegedOpcode::_count; 110 111FaultName UnimplementedLDD::_name = "unimp_ldd"; 112TrapType UnimplementedLDD::_trapType = 0x012; 113FaultPriority UnimplementedLDD::_priority = 6; 114FaultStat UnimplementedLDD::_count; 115 116FaultName UnimplementedSTD::_name = "unimp_std"; 117TrapType UnimplementedSTD::_trapType = 0x013; 118FaultPriority UnimplementedSTD::_priority = 6; 119FaultStat UnimplementedSTD::_count; 120 121FaultName FpDisabled::_name = "fp_disabled"; 122TrapType FpDisabled::_trapType = 0x020; 123FaultPriority FpDisabled::_priority = 8; 124FaultStat FpDisabled::_count; 125 126FaultName FpExceptionIEEE754::_name = "fp_754"; 127TrapType FpExceptionIEEE754::_trapType = 0x021; 128FaultPriority FpExceptionIEEE754::_priority = 11; 129FaultStat FpExceptionIEEE754::_count; 130 131FaultName FpExceptionOther::_name = "fp_other"; 132TrapType FpExceptionOther::_trapType = 0x022; 133FaultPriority FpExceptionOther::_priority = 11; 134FaultStat FpExceptionOther::_count; 135 136FaultName TagOverflow::_name = "tag_overflow"; 137TrapType TagOverflow::_trapType = 0x023; 138FaultPriority TagOverflow::_priority = 14; 139FaultStat TagOverflow::_count; 140 141FaultName DivisionByZero::_name = "div_by_zero"; 142TrapType DivisionByZero::_trapType = 0x028; 143FaultPriority DivisionByZero::_priority = 15; 144FaultStat DivisionByZero::_count; 145 146FaultName DataAccessException::_name = "data_access"; 147TrapType DataAccessException::_trapType = 0x030; 148FaultPriority DataAccessException::_priority = 12; 149FaultStat DataAccessException::_count; 150 151FaultName DataAccessMMUMiss::_name = "data_mmu"; 152TrapType DataAccessMMUMiss::_trapType = 0x031; 153FaultPriority DataAccessMMUMiss::_priority = 12; 154FaultStat DataAccessMMUMiss::_count; 155 156FaultName DataAccessError::_name = "data_error"; 157TrapType DataAccessError::_trapType = 0x032; 158FaultPriority DataAccessError::_priority = 12; 159FaultStat DataAccessError::_count; 160 161FaultName DataAccessProtection::_name = "data_protection"; 162TrapType DataAccessProtection::_trapType = 0x033; 163FaultPriority DataAccessProtection::_priority = 12; 164FaultStat DataAccessProtection::_count; 165 166FaultName LDDFMemAddressNotAligned::_name = "unalign_lddf"; 167TrapType LDDFMemAddressNotAligned::_trapType = 0x035; 168FaultPriority LDDFMemAddressNotAligned::_priority = 10; 169FaultStat LDDFMemAddressNotAligned::_count; 170 171FaultName STDFMemAddressNotAligned::_name = "unalign_stdf"; 172TrapType STDFMemAddressNotAligned::_trapType = 0x036; 173FaultPriority STDFMemAddressNotAligned::_priority = 10; 174FaultStat STDFMemAddressNotAligned::_count; 175 176FaultName PrivilegedAction::_name = "priv_action"; 177TrapType PrivilegedAction::_trapType = 0x037; 178FaultPriority PrivilegedAction::_priority = 11; 179FaultStat PrivilegedAction::_count; 180 181FaultName LDQFMemAddressNotAligned::_name = "unalign_ldqf"; 182TrapType LDQFMemAddressNotAligned::_trapType = 0x038; 183FaultPriority LDQFMemAddressNotAligned::_priority = 10; 184FaultStat LDQFMemAddressNotAligned::_count; 185 186FaultName STQFMemAddressNotAligned::_name = "unalign_stqf"; 187TrapType STQFMemAddressNotAligned::_trapType = 0x039; 188FaultPriority STQFMemAddressNotAligned::_priority = 10; 189FaultStat STQFMemAddressNotAligned::_count; 190 191FaultName AsyncDataError::_name = "async_data"; 192TrapType AsyncDataError::_trapType = 0x040; 193FaultPriority AsyncDataError::_priority = 2; 194FaultStat AsyncDataError::_count; 195 196FaultName CleanWindow::_name = "clean_win"; 197TrapType CleanWindow::_trapType = 0x024; 198FaultPriority CleanWindow::_priority = 10; 199FaultStat CleanWindow::_count; 200 201//The enumerated faults 202 203FaultName InterruptLevelN::_name = "interrupt_n"; 204TrapType InterruptLevelN::_baseTrapType = 0x041; 205FaultStat InterruptLevelN::_count; 206 207FaultName SpillNNormal::_name = "spill_n_normal"; 208TrapType SpillNNormal::_baseTrapType = 0x080; 209FaultPriority SpillNNormal::_priority = 9; 210FaultStat SpillNNormal::_count; 211 212FaultName SpillNOther::_name = "spill_n_other"; 213TrapType SpillNOther::_baseTrapType = 0x0A0; 214FaultPriority SpillNOther::_priority = 9; 215FaultStat SpillNOther::_count; 216 217FaultName FillNNormal::_name = "fill_n_normal"; 218TrapType FillNNormal::_baseTrapType = 0x0C0; 219FaultPriority FillNNormal::_priority = 9; 220FaultStat FillNNormal::_count; 221 222FaultName FillNOther::_name = "fill_n_other"; 223TrapType FillNOther::_baseTrapType = 0x0E0; 224FaultPriority FillNOther::_priority = 9; 225FaultStat FillNOther::_count; 226 227FaultName TrapInstruction::_name = "trap_inst_n"; 228TrapType TrapInstruction::_baseTrapType = 0x100; 229FaultPriority TrapInstruction::_priority = 16; 230FaultStat TrapInstruction::_count; 231 232#if !FULL_SYSTEM 233FaultName PageTableFault::_name = "page_table_fault"; 234TrapType PageTableFault::_trapType = 0x0000; 235FaultPriority PageTableFault::_priority = 0; 236FaultStat PageTableFault::_count; 237#endif 238 239/** 240 * This sets everything up for a normal trap except for actually jumping to 241 * the handler. It will need to be expanded to include the state machine in 242 * the manual. Right now it assumes that traps will always be to the 243 * privileged level. 244 */ 245 246void doNormalFault(ThreadContext *tc, TrapType tt) 247{ 248 uint64_t TL = tc->readMiscReg(MISCREG_TL); 249 uint64_t TSTATE = tc->readMiscReg(MISCREG_TSTATE); 250 uint64_t PSTATE = tc->readMiscReg(MISCREG_PSTATE); 251 uint64_t HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); 252 uint64_t CCR = tc->readMiscReg(MISCREG_CCR); 253 uint64_t ASI = tc->readMiscReg(MISCREG_ASI); 254 uint64_t CWP = tc->readMiscReg(MISCREG_CWP); 255 uint64_t CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); 256 uint64_t GL = tc->readMiscReg(MISCREG_GL); 257 uint64_t PC = tc->readPC(); 258 uint64_t NPC = tc->readNextPC(); 259 260 //Increment the trap level 261 TL++; 262 tc->setMiscReg(MISCREG_TL, TL); 263 264 //Save off state 265 266 //set TSTATE.gl to gl 267 replaceBits(TSTATE, 42, 40, GL); 268 //set TSTATE.ccr to ccr 269 replaceBits(TSTATE, 39, 32, CCR); 270 //set TSTATE.asi to asi 271 replaceBits(TSTATE, 31, 24, ASI); 272 //set TSTATE.pstate to pstate 273 replaceBits(TSTATE, 20, 8, PSTATE); 274 //set TSTATE.cwp to cwp 275 replaceBits(TSTATE, 4, 0, CWP); 276 277 //Write back TSTATE 278 tc->setMiscReg(MISCREG_TSTATE, TSTATE); 279 280 //set TPC to PC 281 tc->setMiscReg(MISCREG_TPC, PC); 282 //set TNPC to NPC 283 tc->setMiscReg(MISCREG_TNPC, NPC); 284 285 //set HTSTATE.hpstate to hpstate 286 tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); 287 288 //TT = trap type; 289 tc->setMiscReg(MISCREG_TT, tt); 290 291 //Update the global register level 292 if(1/*We're delivering the trap in priveleged mode*/) 293 tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxGL)); 294 else 295 tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxPGL)); 296 297 //PSTATE.mm is unchanged 298 //PSTATE.pef = whether or not an fpu is present 299 //XXX We'll say there's one present, even though there aren't 300 //implementations for a decent number of the instructions 301 PSTATE |= (1 << 4); 302 //PSTATE.am = 0 303 PSTATE &= ~(1 << 3); 304 if(1/*We're delivering the trap in priveleged mode*/) 305 { 306 //PSTATE.priv = 1 307 PSTATE |= (1 << 2); 308 //PSTATE.cle = PSTATE.tle 309 replaceBits(PSTATE, 9, 9, PSTATE >> 8); 310 } 311 else 312 { 313 //PSTATE.priv = 0 314 PSTATE &= ~(1 << 2); 315 //PSTATE.cle = 0 316 PSTATE &= ~(1 << 9); 317 } 318 //PSTATE.ie = 0 319 PSTATE &= ~(1 << 1); 320 //PSTATE.tle is unchanged 321 //PSTATE.tct = 0 322 //XXX Where exactly is this field? 323 tc->setMiscReg(MISCREG_PSTATE, PSTATE); 324 325 if(0/*We're delivering the trap in hyperprivileged mode*/) 326 { 327 //HPSTATE.red = 0 328 HPSTATE &= ~(1 << 5); 329 //HPSTATE.hpriv = 1 330 HPSTATE |= (1 << 2); 331 //HPSTATE.ibe = 0 332 HPSTATE &= ~(1 << 10); 333 //HPSTATE.tlz is unchanged 334 tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); 335 } 336 337 bool changedCWP = true; 338 if(tt == 0x24) 339 { 340 warn("Incrementing the CWP by 1\n"); 341 CWP++; 342 } 343 else if(0x80 <= tt && tt <= 0xbf) 344 { 345 warn("Incrementing the CWP by %d\n", CANSAVE + 2); 346 CWP += (CANSAVE + 2); 347 } 348 else if(0xc0 <= tt && tt <= 0xff) 349 { 350 warn("Decrementing the CWP by 1\n"); 351 CWP--; 352 } 353 else 354 changedCWP = false; 355 if(changedCWP) 356 { 357 CWP = (CWP + NWindows) % NWindows; 358 tc->setMiscRegWithEffect(MISCREG_CWP, CWP); 359 } 360} 361 362#if FULL_SYSTEM 363 364void SparcFault::invoke(ThreadContext * tc) 365{ 366 FaultBase::invoke(tc); 367 countStat()++; 368 369 //Use the SPARC trap state machine 370 /*// exception restart address 371 if (setRestartAddress() || !tc->inPalMode()) 372 tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, tc->regs.pc); 373 374 if (skipFaultingInstruction()) { 375 // traps... skip faulting instruction. 376 tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, 377 tc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4); 378 } 379 380 if (!tc->inPalMode()) 381 AlphaISA::swap_palshadow(&(tc->regs), true); 382 383 tc->regs.pc = tc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect(); 384 tc->regs.npc = tc->regs.pc + sizeof(MachInst);*/ 385} 386 387#endif 388 389#if !FULL_SYSTEM 390 391void TrapInstruction::invoke(ThreadContext * tc) 392{ 393 // Should be handled in ISA. 394} 395 396void SpillNNormal::invoke(ThreadContext *tc) 397{ 398 warn("I'm in a spill trap\n"); 399 doNormalFault(tc, trapType()); 400 401 Process *p = tc->getProcessPtr(); 402 403 //This will only work in faults from a SparcLiveProcess 404 SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); 405 assert(lp); 406 407 //Then adjust the PC and NPC 408 Addr spillStart = lp->readSpillStart(); 409 tc->setPC(spillStart); 410 tc->setNextPC(spillStart + sizeof(MachInst)); 411 tc->setNextNPC(spillStart + 2*sizeof(MachInst)); 412} 413 414void FillNNormal::invoke(ThreadContext *tc) 415{ 416 warn("I'm in a fill trap\n"); 417 doNormalFault(tc, trapType()); 418 419 Process * p = tc->getProcessPtr(); 420 421 //This will only work in faults from a SparcLiveProcess 422 SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); 423 assert(lp); 424 425 //The adjust the PC and NPC 426 Addr fillStart = lp->readFillStart(); 427 tc->setPC(fillStart); 428 tc->setNextPC(fillStart + sizeof(MachInst)); 429 tc->setNextNPC(fillStart + 2*sizeof(MachInst)); 430} 431 432void PageTableFault::invoke(ThreadContext *tc) 433{ 434 Process *p = tc->getProcessPtr(); 435 436 // address is higher than the stack region or in the current stack region 437 if (vaddr > p->stack_base || vaddr > p->stack_min) 438 FaultBase::invoke(tc); 439 440 // We've accessed the next page 441 if (vaddr > p->stack_min - PageBytes) { 442 p->stack_min -= PageBytes; 443 if (p->stack_base - p->stack_min > 8*1024*1024) 444 fatal("Over max stack size for one thread\n"); 445 p->pTable->allocate(p->stack_min, PageBytes); 446 warn("Increasing stack size by one page."); 447 } else { 448 FaultBase::invoke(tc); 449 } 450} 451 452#endif 453 454} // namespace SparcISA 455 456