faults.cc (3928:9486450f013f) | faults.cc (3949:b6664282d899) |
---|---|
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; --- 183 unchanged lines hidden (view full) --- 192 193//XXX This trap is apparently dropped from ua2005 194/*template<> SparcFaultBase::FaultVals 195 SparcFault<AsyncDataError>::vals = 196 {"async_data", 0x040, 2, {H, H, H}};*/ 197 198template<> SparcFaultBase::FaultVals 199 SparcFault<InterruptLevelN>::vals = | 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; --- 183 unchanged lines hidden (view full) --- 192 193//XXX This trap is apparently dropped from ua2005 194/*template<> SparcFaultBase::FaultVals 195 SparcFault<AsyncDataError>::vals = 196 {"async_data", 0x040, 2, {H, H, H}};*/ 197 198template<> SparcFaultBase::FaultVals 199 SparcFault<InterruptLevelN>::vals = |
200 {"interrupt_level_n", 0x040, 0, {P, P, SH}}; | 200 {"interrupt_level_n", 0x041, 0, {P, P, SH}}; |
201 202template<> SparcFaultBase::FaultVals 203 SparcFault<HstickMatch>::vals = 204 {"hstick_match", 0x05E, 1601, {H, H, H}}; 205 206template<> SparcFaultBase::FaultVals 207 SparcFault<TrapLevelZero>::vals = 208 {"trap_level_zero", 0x05F, 202, {H, H, SH}}; --- 26 unchanged lines hidden (view full) --- 235 SparcFault<CpuMondo>::vals = 236 {"cpu_mondo", 0x07C, 1608, {P, P, SH}}; 237 238template<> SparcFaultBase::FaultVals 239 SparcFault<DevMondo>::vals = 240 {"dev_mondo", 0x07D, 1611, {P, P, SH}}; 241 242template<> SparcFaultBase::FaultVals | 201 202template<> SparcFaultBase::FaultVals 203 SparcFault<HstickMatch>::vals = 204 {"hstick_match", 0x05E, 1601, {H, H, H}}; 205 206template<> SparcFaultBase::FaultVals 207 SparcFault<TrapLevelZero>::vals = 208 {"trap_level_zero", 0x05F, 202, {H, H, SH}}; --- 26 unchanged lines hidden (view full) --- 235 SparcFault<CpuMondo>::vals = 236 {"cpu_mondo", 0x07C, 1608, {P, P, SH}}; 237 238template<> SparcFaultBase::FaultVals 239 SparcFault<DevMondo>::vals = 240 {"dev_mondo", 0x07D, 1611, {P, P, SH}}; 241 242template<> SparcFaultBase::FaultVals |
243 SparcFault | 243 SparcFault<ResumeableError>::vals = |
244 {"resume_error", 0x07E, 3330, {P, P, SH}}; 245 246template<> SparcFaultBase::FaultVals 247 SparcFault<SpillNNormal>::vals = 248 {"spill_n_normal", 0x080, 900, {P, P, H}}; 249 250template<> SparcFaultBase::FaultVals 251 SparcFault<SpillNOther>::vals = --- 45 unchanged lines hidden (view full) --- 297 */ 298 299void doREDFault(ThreadContext *tc, TrapType tt) 300{ 301 MiscReg TL = tc->readMiscReg(MISCREG_TL); 302 MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); 303 MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); 304 MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); | 244 {"resume_error", 0x07E, 3330, {P, P, SH}}; 245 246template<> SparcFaultBase::FaultVals 247 SparcFault<SpillNNormal>::vals = 248 {"spill_n_normal", 0x080, 900, {P, P, H}}; 249 250template<> SparcFaultBase::FaultVals 251 SparcFault<SpillNOther>::vals = --- 45 unchanged lines hidden (view full) --- 297 */ 298 299void doREDFault(ThreadContext *tc, TrapType tt) 300{ 301 MiscReg TL = tc->readMiscReg(MISCREG_TL); 302 MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); 303 MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); 304 MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); |
305 MiscReg CCR = tc->readMiscReg(MISCREG_CCR); | 305 //MiscReg CCR = tc->readMiscReg(MISCREG_CCR); 306 MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); |
306 MiscReg ASI = tc->readMiscReg(MISCREG_ASI); 307 MiscReg CWP = tc->readMiscReg(MISCREG_CWP); | 307 MiscReg ASI = tc->readMiscReg(MISCREG_ASI); 308 MiscReg CWP = tc->readMiscReg(MISCREG_CWP); |
308 MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); | 309 //MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); 310 MiscReg CANSAVE = tc->readMiscReg(NumIntArchRegs + 3); |
309 MiscReg GL = tc->readMiscReg(MISCREG_GL); 310 MiscReg PC = tc->readPC(); 311 MiscReg NPC = tc->readNextPC(); 312 313 TL++; 314 | 311 MiscReg GL = tc->readMiscReg(MISCREG_GL); 312 MiscReg PC = tc->readPC(); 313 MiscReg NPC = tc->readNextPC(); 314 315 TL++; 316 |
315 if (bits(PSTATE, 3,3)) { 316 PC &= mask(32); 317 NPC &= mask(32); 318 } 319 | |
320 //set TSTATE.gl to gl 321 replaceBits(TSTATE, 42, 40, GL); 322 //set TSTATE.ccr to ccr 323 replaceBits(TSTATE, 39, 32, CCR); 324 //set TSTATE.asi to asi 325 replaceBits(TSTATE, 31, 24, ASI); 326 //set TSTATE.pstate to pstate 327 replaceBits(TSTATE, 20, 8, PSTATE); --- 12 unchanged lines hidden (view full) --- 340 tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); 341 342 //TT = trap type; 343 tc->setMiscReg(MISCREG_TT, tt); 344 345 //Update GL 346 tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); 347 | 317 //set TSTATE.gl to gl 318 replaceBits(TSTATE, 42, 40, GL); 319 //set TSTATE.ccr to ccr 320 replaceBits(TSTATE, 39, 32, CCR); 321 //set TSTATE.asi to asi 322 replaceBits(TSTATE, 31, 24, ASI); 323 //set TSTATE.pstate to pstate 324 replaceBits(TSTATE, 20, 8, PSTATE); --- 12 unchanged lines hidden (view full) --- 337 tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); 338 339 //TT = trap type; 340 tc->setMiscReg(MISCREG_TT, tt); 341 342 //Update GL 343 tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); 344 |
348 PSTATE = mbits(PSTATE, 2, 2); // just save the priv bit 349 PSTATE |= (1 << 4); //set PSTATE.pef to 1 | 345 //set PSTATE.mm to 00 346 //set PSTATE.pef to 1 347 PSTATE |= (1 << 4); 348 //set PSTATE.am to 0 349 PSTATE &= ~(1 << 3); 350/* //set PSTATE.priv to 0 351 PSTATE &= ~(1 << 2);*/ 352 //set PSTATE.ie to 0 353 //PSTATE.priv is set to 1 here. The manual says it should be 0, but 354 //Legion sets it to 1. 355 PSTATE |= (1 << 2); 356 //set PSTATE.cle to 0 357 PSTATE &= ~(1 << 9); 358 //PSTATE.tle is unchanged 359 //XXX Where is the tct bit? 360 //set PSTATE.tct to 0 |
350 tc->setMiscReg(MISCREG_PSTATE, PSTATE); 351 352 //set HPSTATE.red to 1 353 HPSTATE |= (1 << 5); 354 //set HPSTATE.hpriv to 1 355 HPSTATE |= (1 << 2); 356 //set HPSTATE.ibe to 0 357 HPSTATE &= ~(1 << 10); --- 24 unchanged lines hidden (view full) --- 382 */ 383 384void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) 385{ 386 MiscReg TL = tc->readMiscReg(MISCREG_TL); 387 MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); 388 MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); 389 MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); | 361 tc->setMiscReg(MISCREG_PSTATE, PSTATE); 362 363 //set HPSTATE.red to 1 364 HPSTATE |= (1 << 5); 365 //set HPSTATE.hpriv to 1 366 HPSTATE |= (1 << 2); 367 //set HPSTATE.ibe to 0 368 HPSTATE &= ~(1 << 10); --- 24 unchanged lines hidden (view full) --- 393 */ 394 395void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) 396{ 397 MiscReg TL = tc->readMiscReg(MISCREG_TL); 398 MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); 399 MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); 400 MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); |
390 MiscReg CCR = tc->readMiscReg(MISCREG_CCR); | 401 //MiscReg CCR = tc->readMiscReg(MISCREG_CCR); 402 MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); |
391 MiscReg ASI = tc->readMiscReg(MISCREG_ASI); 392 MiscReg CWP = tc->readMiscReg(MISCREG_CWP); | 403 MiscReg ASI = tc->readMiscReg(MISCREG_ASI); 404 MiscReg CWP = tc->readMiscReg(MISCREG_CWP); |
393 MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); | 405 //MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); 406 MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3); |
394 MiscReg GL = tc->readMiscReg(MISCREG_GL); 395 MiscReg PC = tc->readPC(); 396 MiscReg NPC = tc->readNextPC(); 397 | 407 MiscReg GL = tc->readMiscReg(MISCREG_GL); 408 MiscReg PC = tc->readPC(); 409 MiscReg NPC = tc->readNextPC(); 410 |
398 if (bits(PSTATE, 3,3)) { 399 PC &= mask(32); 400 NPC &= mask(32); 401 } 402 | |
403 //Increment the trap level 404 TL++; 405 tc->setMiscReg(MISCREG_TL, TL); 406 407 //Save off state 408 409 //set TSTATE.gl to gl 410 replaceBits(TSTATE, 42, 40, GL); --- 16 unchanged lines hidden (view full) --- 427 428 //set HTSTATE.hpstate to hpstate 429 tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); 430 431 //TT = trap type; 432 tc->setMiscReg(MISCREG_TT, tt); 433 434 //Update the global register level | 411 //Increment the trap level 412 TL++; 413 tc->setMiscReg(MISCREG_TL, TL); 414 415 //Save off state 416 417 //set TSTATE.gl to gl 418 replaceBits(TSTATE, 42, 40, GL); --- 16 unchanged lines hidden (view full) --- 435 436 //set HTSTATE.hpstate to hpstate 437 tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); 438 439 //TT = trap type; 440 tc->setMiscReg(MISCREG_TT, tt); 441 442 //Update the global register level |
435 if (!gotoHpriv) | 443 if(!gotoHpriv) |
436 tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxPGL)); 437 else 438 tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); 439 440 //PSTATE.mm is unchanged | 444 tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxPGL)); 445 else 446 tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); 447 448 //PSTATE.mm is unchanged |
441 PSTATE |= (1 << 4); //PSTATE.pef = whether or not an fpu is present 442 PSTATE &= ~(1 << 3); //PSTATE.am = 0 443 PSTATE &= ~(1 << 1); //PSTATE.ie = 0 | 449 //PSTATE.pef = whether or not an fpu is present 450 //XXX We'll say there's one present, even though there aren't 451 //implementations for a decent number of the instructions 452 PSTATE |= (1 << 4); 453 //PSTATE.am = 0 454 PSTATE &= ~(1 << 3); 455 if(!gotoHpriv) 456 { 457 //PSTATE.priv = 1 458 PSTATE |= (1 << 2); 459 //PSTATE.cle = PSTATE.tle 460 replaceBits(PSTATE, 9, 9, PSTATE >> 8); 461 } 462 else 463 { 464 //PSTATE.priv = 0 465 //PSTATE.priv is set to 1 here. The manual says it should be 0, but 466 //Legion sets it to 1. 467 PSTATE |= (1 << 2); 468 //PSTATE.cle = 0 469 PSTATE &= ~(1 << 9); 470 } 471 //PSTATE.ie = 0 472 PSTATE &= ~(1 << 1); |
444 //PSTATE.tle is unchanged 445 //PSTATE.tct = 0 | 473 //PSTATE.tle is unchanged 474 //PSTATE.tct = 0 |
475 //XXX Where exactly is this field? 476 tc->setMiscReg(MISCREG_PSTATE, PSTATE); |
|
446 | 477 |
447 if (gotoHpriv) | 478 if(gotoHpriv) |
448 { | 479 { |
449 PSTATE &= ~(1 << 9); // PSTATE.cle = 0 450 //The manual says PSTATE.priv should be 0, but Legion leaves it alone 451 HPSTATE &= ~(1 << 5); //HPSTATE.red = 0 452 HPSTATE |= (1 << 2); //HPSTATE.hpriv = 1 453 HPSTATE &= ~(1 << 10); //HPSTATE.ibe = 0 | 480 //HPSTATE.red = 0 481 HPSTATE &= ~(1 << 5); 482 //HPSTATE.hpriv = 1 483 HPSTATE |= (1 << 2); 484 //HPSTATE.ibe = 0 485 HPSTATE &= ~(1 << 10); |
454 //HPSTATE.tlz is unchanged 455 tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); | 486 //HPSTATE.tlz is unchanged 487 tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); |
456 } else { // we are going to priv 457 PSTATE |= (1 << 2); //PSTATE.priv = 1 458 replaceBits(PSTATE, 9, 9, PSTATE >> 8); //PSTATE.cle = PSTATE.tle | |
459 } | 488 } |
460 tc->setMiscReg(MISCREG_PSTATE, PSTATE); | |
461 | 489 |
462 | |
463 bool changedCWP = true; | 490 bool changedCWP = true; |
464 if (tt == 0x24) | 491 if(tt == 0x24) |
465 CWP++; | 492 CWP++; |
466 else if (0x80 <= tt && tt <= 0xbf) | 493 else if(0x80 <= tt && tt <= 0xbf) |
467 CWP += (CANSAVE + 2); | 494 CWP += (CANSAVE + 2); |
468 else if (0xc0 <= tt && tt <= 0xff) | 495 else if(0xc0 <= tt && tt <= 0xff) |
469 CWP--; 470 else 471 changedCWP = false; 472 | 496 CWP--; 497 else 498 changedCWP = false; 499 |
473 if (changedCWP) | 500 if(changedCWP) |
474 { 475 CWP = (CWP + NWindows) % NWindows; 476 tc->setMiscRegWithEffect(MISCREG_CWP, CWP); 477 } 478} 479 480void getREDVector(MiscReg TT, Addr & PC, Addr & NPC) 481{ --- 24 unchanged lines hidden (view full) --- 506void SparcFaultBase::invoke(ThreadContext * tc) 507{ 508 //panic("Invoking a second fault!\n"); 509 FaultBase::invoke(tc); 510 countStat()++; 511 512 //We can refer to this to see what the trap level -was-, but something 513 //in the middle could change it in the regfile out from under us. | 501 { 502 CWP = (CWP + NWindows) % NWindows; 503 tc->setMiscRegWithEffect(MISCREG_CWP, CWP); 504 } 505} 506 507void getREDVector(MiscReg TT, Addr & PC, Addr & NPC) 508{ --- 24 unchanged lines hidden (view full) --- 533void SparcFaultBase::invoke(ThreadContext * tc) 534{ 535 //panic("Invoking a second fault!\n"); 536 FaultBase::invoke(tc); 537 countStat()++; 538 539 //We can refer to this to see what the trap level -was-, but something 540 //in the middle could change it in the regfile out from under us. |
514 MiscReg tl = tc->readMiscReg(MISCREG_TL); 515 MiscReg tt = tc->readMiscReg(MISCREG_TT); 516 MiscReg pstate = tc->readMiscReg(MISCREG_PSTATE); 517 MiscReg hpstate = tc->readMiscReg(MISCREG_HPSTATE); | 541 MiscReg TL = tc->readMiscReg(MISCREG_TL); 542 MiscReg TT = tc->readMiscReg(MISCREG_TT); 543 MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); 544 MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); |
518 519 Addr PC, NPC; 520 521 PrivilegeLevel current; | 545 546 Addr PC, NPC; 547 548 PrivilegeLevel current; |
522 if (hpstate & HPSTATE::hpriv) | 549 if(HPSTATE & (1 << 2)) |
523 current = Hyperprivileged; | 550 current = Hyperprivileged; |
524 else if (pstate & PSTATE::priv) | 551 else if(PSTATE & (1 << 2)) |
525 current = Privileged; 526 else 527 current = User; 528 529 PrivilegeLevel level = getNextLevel(current); 530 | 552 current = Privileged; 553 else 554 current = User; 555 556 PrivilegeLevel level = getNextLevel(current); 557 |
531 if ((hpstate & HPSTATE::red) || (tl == MaxTL - 1)) { | 558 if(HPSTATE & (1 << 5) || TL == MaxTL - 1) { |
532 getREDVector(5, PC, NPC); | 559 getREDVector(5, PC, NPC); |
533 doREDFault(tc, tt); | 560 doREDFault(tc, TT); |
534 //This changes the hpstate and pstate, so we need to make sure we 535 //save the old version on the trap stack in doREDFault. 536 enterREDState(tc); | 561 //This changes the hpstate and pstate, so we need to make sure we 562 //save the old version on the trap stack in doREDFault. 563 enterREDState(tc); |
537 } else if (tl == MaxTL) { | 564 } else if(TL == MaxTL) { |
538 panic("Should go to error state here.. crap\n"); 539 //Do error_state somehow? 540 //Probably inject a WDR fault using the interrupt mechanism. 541 //What should the PC and NPC be set to? | 565 panic("Should go to error state here.. crap\n"); 566 //Do error_state somehow? 567 //Probably inject a WDR fault using the interrupt mechanism. 568 //What should the PC and NPC be set to? |
542 } else if (tl > MaxPTL && level == Privileged) { | 569 } else if(TL > MaxPTL && level == Privileged) { |
543 //guest_watchdog fault 544 doNormalFault(tc, trapType(), true); 545 getHyperVector(tc, PC, NPC, 2); | 570 //guest_watchdog fault 571 doNormalFault(tc, trapType(), true); 572 getHyperVector(tc, PC, NPC, 2); |
546 } else if (level == Hyperprivileged || | 573 } else if(level == Hyperprivileged || |
547 level == Privileged && trapType() >= 384) { 548 doNormalFault(tc, trapType(), true); 549 getHyperVector(tc, PC, NPC, trapType()); 550 } else { 551 doNormalFault(tc, trapType(), false); | 574 level == Privileged && trapType() >= 384) { 575 doNormalFault(tc, trapType(), true); 576 getHyperVector(tc, PC, NPC, trapType()); 577 } else { 578 doNormalFault(tc, trapType(), false); |
552 getPrivVector(tc, PC, NPC, trapType(), tl+1); | 579 getPrivVector(tc, PC, NPC, trapType(), TL+1); |
553 } 554 555 tc->setPC(PC); 556 tc->setNextPC(NPC); 557 tc->setNextNPC(NPC + sizeof(MachInst)); 558} 559 560void PowerOnReset::invoke(ThreadContext * tc) --- 90 unchanged lines hidden (view full) --- 651 tc->setNextPC(fillStart + sizeof(MachInst)); 652 tc->setNextNPC(fillStart + 2*sizeof(MachInst)); 653} 654 655void PageTableFault::invoke(ThreadContext *tc) 656{ 657 Process *p = tc->getProcessPtr(); 658 | 580 } 581 582 tc->setPC(PC); 583 tc->setNextPC(NPC); 584 tc->setNextNPC(NPC + sizeof(MachInst)); 585} 586 587void PowerOnReset::invoke(ThreadContext * tc) --- 90 unchanged lines hidden (view full) --- 678 tc->setNextPC(fillStart + sizeof(MachInst)); 679 tc->setNextNPC(fillStart + 2*sizeof(MachInst)); 680} 681 682void PageTableFault::invoke(ThreadContext *tc) 683{ 684 Process *p = tc->getProcessPtr(); 685 |
659 // address is higher than the stack region or in the current stack region 660 if (vaddr > p->stack_base || vaddr > p->stack_min) 661 FaultBase::invoke(tc); 662 663 // We've accessed the next page 664 if (vaddr > p->stack_min - PageBytes) { | 686 // We've accessed the next page of the stack, so extend the stack 687 // to cover it. 688 if(vaddr < p->stack_min && vaddr >= p->stack_min - PageBytes) 689 { |
665 p->stack_min -= PageBytes; | 690 p->stack_min -= PageBytes; |
666 if (p->stack_base - p->stack_min > 8*1024*1024) | 691 if(p->stack_base - p->stack_min > 8*1024*1024) |
667 fatal("Over max stack size for one thread\n"); 668 p->pTable->allocate(p->stack_min, PageBytes); 669 warn("Increasing stack size by one page."); | 692 fatal("Over max stack size for one thread\n"); 693 p->pTable->allocate(p->stack_min, PageBytes); 694 warn("Increasing stack size by one page."); |
670 } else { 671 FaultBase::invoke(tc); | |
672 } | 695 } |
696 // Otherwise, we have an unexpected page fault. Report that fact, 697 // and what address was accessed to cause the fault. 698 else 699 { 700 panic("Page table fault when accessing virtual address %#x\n", vaddr); 701 } |
|
673} 674 675#endif 676 677} // namespace SparcISA 678 | 702} 703 704#endif 705 706} // namespace SparcISA 707 |