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; --- 258 unchanged lines hidden (view full) --- 267 SparcFault<TrapInstruction>::vals = 268 {"trap_instruction", 0x100, 1602, {P, P, H}}; 269 270/** 271 * This causes the thread context to enter RED state. This causes the side 272 * effects which go with entering RED state because of a trap. 273 */ 274 |
275void 276enterREDState(ThreadContext *tc) |
277{ 278 //@todo Disable the mmu? 279 //@todo Disable watchpoints? 280 MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); |
281 // HPSTATE.red = 1 |
282 HPSTATE |= (1 << 5); |
283 // HPSTATE.hpriv = 1 |
284 HPSTATE |= (1 << 2); 285 tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); |
286 // PSTATE.priv is set to 1 here. The manual says it should be 0, but 287 // Legion sets it to 1. |
288 MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE); 289 PSTATE |= (1 << 2); 290 tc->setMiscReg(MISCREG_PSTATE, PSTATE); 291} 292 293/** 294 * This sets everything up for a RED state trap except for actually jumping to 295 * the handler. 296 */ 297 |
298void 299doREDFault(ThreadContext *tc, TrapType tt) |
300{ 301 MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL); 302 MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE); 303 MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE); 304 MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); |
305 MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); 306 MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI); 307 MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP); |
308 MiscReg CANSAVE = tc->readMiscRegNoEffect(NumIntArchRegs + 3); 309 MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL); 310 PCState pc = tc->pcState(); 311 312 TL++; 313 314 Addr pcMask = bits(PSTATE, 3) ? mask(32) : mask(64); 315 |
316 // set TSTATE.gl to gl |
317 replaceBits(TSTATE, 42, 40, GL); |
318 // set TSTATE.ccr to ccr |
319 replaceBits(TSTATE, 39, 32, CCR); |
320 // set TSTATE.asi to asi |
321 replaceBits(TSTATE, 31, 24, ASI); |
322 // set TSTATE.pstate to pstate |
323 replaceBits(TSTATE, 20, 8, PSTATE); |
324 // set TSTATE.cwp to cwp |
325 replaceBits(TSTATE, 4, 0, CWP); 326 |
327 // Write back TSTATE |
328 tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE); 329 |
330 // set TPC to PC |
331 tc->setMiscRegNoEffect(MISCREG_TPC, pc.pc() & pcMask); |
332 // set TNPC to NPC |
333 tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask); 334 |
335 // set HTSTATE.hpstate to hpstate |
336 tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE); 337 |
338 // TT = trap type; |
339 tc->setMiscRegNoEffect(MISCREG_TT, tt); 340 |
341 // Update GL |
342 tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL)); 343 344 PSTATE = mbits(PSTATE, 2, 2); // just save the priv bit |
345 PSTATE |= (1 << 4); // set PSTATE.pef to 1 |
346 tc->setMiscRegNoEffect(MISCREG_PSTATE, PSTATE); 347 |
348 // set HPSTATE.red to 1 |
349 HPSTATE |= (1 << 5); |
350 // set HPSTATE.hpriv to 1 |
351 HPSTATE |= (1 << 2); |
352 // set HPSTATE.ibe to 0 |
353 HPSTATE &= ~(1 << 10); |
354 // set HPSTATE.tlz to 0 |
355 HPSTATE &= ~(1 << 0); 356 tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE); 357 358 bool changedCWP = true; |
359 if (tt == 0x24) |
360 CWP++; |
361 else if (0x80 <= tt && tt <= 0xbf) |
362 CWP += (CANSAVE + 2); |
363 else if (0xc0 <= tt && tt <= 0xff) |
364 CWP--; 365 else 366 changedCWP = false; 367 |
368 if (changedCWP) { |
369 CWP = (CWP + NWindows) % NWindows; 370 tc->setMiscReg(MISCREG_CWP, CWP); 371 } 372} 373 374/** 375 * This sets everything up for a normal trap except for actually jumping to 376 * the handler. 377 */ 378 |
379void 380doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) |
381{ 382 MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL); 383 MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE); 384 MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE); 385 MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); |
386 MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); 387 MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI); 388 MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP); |
389 MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3); 390 MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL); 391 PCState pc = tc->pcState(); 392 |
393 // Increment the trap level |
394 TL++; 395 tc->setMiscRegNoEffect(MISCREG_TL, TL); 396 397 Addr pcMask = bits(PSTATE, 3) ? mask(32) : mask(64); 398 |
399 // Save off state |
400 |
401 // set TSTATE.gl to gl |
402 replaceBits(TSTATE, 42, 40, GL); |
403 // set TSTATE.ccr to ccr |
404 replaceBits(TSTATE, 39, 32, CCR); |
405 // set TSTATE.asi to asi |
406 replaceBits(TSTATE, 31, 24, ASI); |
407 // set TSTATE.pstate to pstate |
408 replaceBits(TSTATE, 20, 8, PSTATE); |
409 // set TSTATE.cwp to cwp |
410 replaceBits(TSTATE, 4, 0, CWP); 411 |
412 // Write back TSTATE |
413 tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE); 414 |
415 // set TPC to PC |
416 tc->setMiscRegNoEffect(MISCREG_TPC, pc.pc() & pcMask); |
417 // set TNPC to NPC |
418 tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask); 419 |
420 // set HTSTATE.hpstate to hpstate |
421 tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE); 422 |
423 // TT = trap type; |
424 tc->setMiscRegNoEffect(MISCREG_TT, tt); 425 |
426 // Update the global register level |
427 if (!gotoHpriv) |
428 tc->setMiscReg(MISCREG_GL, min<int>(GL + 1, MaxPGL)); |
429 else |
430 tc->setMiscReg(MISCREG_GL, min<int>(GL + 1, MaxGL)); |
431 |
432 // PSTATE.mm is unchanged 433 PSTATE |= (1 << 4); // PSTATE.pef = whether or not an fpu is present 434 PSTATE &= ~(1 << 3); // PSTATE.am = 0 435 PSTATE &= ~(1 << 1); // PSTATE.ie = 0 436 // PSTATE.tle is unchanged 437 // PSTATE.tct = 0 |
438 |
439 if (gotoHpriv) { |
440 PSTATE &= ~(1 << 9); // PSTATE.cle = 0 |
441 // The manual says PSTATE.priv should be 0, but Legion leaves it alone 442 HPSTATE &= ~(1 << 5); // HPSTATE.red = 0 443 HPSTATE |= (1 << 2); // HPSTATE.hpriv = 1 444 HPSTATE &= ~(1 << 10); // HPSTATE.ibe = 0 445 // HPSTATE.tlz is unchanged |
446 tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE); 447 } else { // we are going to priv |
448 PSTATE |= (1 << 2); // PSTATE.priv = 1 449 replaceBits(PSTATE, 9, 9, PSTATE >> 8); // PSTATE.cle = PSTATE.tle |
450 } 451 tc->setMiscRegNoEffect(MISCREG_PSTATE, PSTATE); 452 453 454 bool changedCWP = true; 455 if (tt == 0x24) 456 CWP++; 457 else if (0x80 <= tt && tt <= 0xbf) 458 CWP += (CANSAVE + 2); 459 else if (0xc0 <= tt && tt <= 0xff) 460 CWP--; 461 else 462 changedCWP = false; 463 |
464 if (changedCWP) { |
465 CWP = (CWP + NWindows) % NWindows; 466 tc->setMiscReg(MISCREG_CWP, CWP); 467 } 468} 469 |
470void 471getREDVector(MiscReg TT, Addr &PC, Addr &NPC) |
472{ 473 //XXX The following constant might belong in a header file. 474 const Addr RSTVAddr = 0xFFF0000000ULL; 475 PC = RSTVAddr | ((TT << 5) & 0xFF); 476 NPC = PC + sizeof(MachInst); 477} 478 |
479void 480getHyperVector(ThreadContext * tc, Addr &PC, Addr &NPC, MiscReg TT) |
481{ 482 Addr HTBA = tc->readMiscRegNoEffect(MISCREG_HTBA); 483 PC = (HTBA & ~mask(14)) | ((TT << 5) & mask(14)); 484 NPC = PC + sizeof(MachInst); 485} 486 |
487void 488getPrivVector(ThreadContext *tc, Addr &PC, Addr &NPC, MiscReg TT, MiscReg TL) |
489{ 490 Addr TBA = tc->readMiscRegNoEffect(MISCREG_TBA); 491 PC = (TBA & ~mask(15)) | 492 (TL > 1 ? (1 << 14) : 0) | 493 ((TT << 5) & mask(14)); 494 NPC = PC + sizeof(MachInst); 495} 496 497#if FULL_SYSTEM 498 |
499void 500SparcFaultBase::invoke(ThreadContext * tc, StaticInstPtr inst) |
501{ |
502 FaultBase::invoke(tc); 503 countStat()++; 504 |
505 // We can refer to this to see what the trap level -was-, but something 506 // in the middle could change it in the regfile out from under us. |
507 MiscReg tl = tc->readMiscRegNoEffect(MISCREG_TL); 508 MiscReg tt = tc->readMiscRegNoEffect(MISCREG_TT); 509 MiscReg pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); 510 MiscReg hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); 511 512 Addr PC, NPC; 513 514 PrivilegeLevel current; --- 4 unchanged lines hidden (view full) --- 519 else 520 current = User; 521 522 PrivilegeLevel level = getNextLevel(current); 523 524 if ((hpstate & HPSTATE::red) || (tl == MaxTL - 1)) { 525 getREDVector(5, PC, NPC); 526 doREDFault(tc, tt); |
527 // This changes the hpstate and pstate, so we need to make sure we 528 // save the old version on the trap stack in doREDFault. |
529 enterREDState(tc); 530 } else if (tl == MaxTL) { 531 panic("Should go to error state here.. crap\n"); |
532 // Do error_state somehow? 533 // Probably inject a WDR fault using the interrupt mechanism. 534 // What should the PC and NPC be set to? |
535 } else if (tl > MaxPTL && level == Privileged) { |
536 // guest_watchdog fault |
537 doNormalFault(tc, trapType(), true); 538 getHyperVector(tc, PC, NPC, 2); 539 } else if (level == Hyperprivileged || 540 (level == Privileged && trapType() >= 384)) { 541 doNormalFault(tc, trapType(), true); 542 getHyperVector(tc, PC, NPC, trapType()); 543 } else { 544 doNormalFault(tc, trapType(), false); |
545 getPrivVector(tc, PC, NPC, trapType(), tl + 1); |
546 } 547 548 PCState pc; 549 pc.pc(PC); 550 pc.npc(NPC); 551 pc.nnpc(NPC + sizeof(MachInst)); 552 pc.upc(0); 553 pc.nupc(1); 554 tc->pcState(pc); 555} 556 |
557void 558PowerOnReset::invoke(ThreadContext *tc, StaticInstPtr inst) |
559{ |
560 // For SPARC, when a system is first started, there is a power 561 // on reset Trap which sets the processor into the following state. 562 // Bits that aren't set aren't defined on startup. |
563 564 tc->setMiscRegNoEffect(MISCREG_TL, MaxTL); 565 tc->setMiscRegNoEffect(MISCREG_TT, trapType()); 566 tc->setMiscReg(MISCREG_GL, MaxGL); 567 |
568 // Turn on pef and priv, set everything else to 0 |
569 tc->setMiscRegNoEffect(MISCREG_PSTATE, (1 << 4) | (1 << 2)); 570 |
571 // Turn on red and hpriv, set everything else to 0 |
572 MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); |
573 // HPSTATE.red = 1 |
574 HPSTATE |= (1 << 5); |
575 // HPSTATE.hpriv = 1 |
576 HPSTATE |= (1 << 2); |
577 // HPSTATE.ibe = 0 |
578 HPSTATE &= ~(1 << 10); |
579 // HPSTATE.tlz = 0 |
580 HPSTATE &= ~(1 << 0); 581 tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE); 582 |
583 // The tick register is unreadable by nonprivileged software |
584 tc->setMiscRegNoEffect(MISCREG_TICK, 1ULL << 63); 585 |
586 // Enter RED state. We do this last so that the actual state preserved in 587 // the trap stack is the state from before this fault. |
588 enterREDState(tc); 589 590 Addr PC, NPC; 591 getREDVector(trapType(), PC, NPC); 592 593 PCState pc; 594 pc.pc(PC); 595 pc.npc(NPC); 596 pc.nnpc(NPC + sizeof(MachInst)); 597 pc.upc(0); 598 pc.nupc(1); 599 tc->pcState(pc); 600 |
601 // These registers are specified as "undefined" after a POR, and they 602 // should have reasonable values after the miscregfile is reset |
603 /* 604 // Clear all the soft interrupt bits 605 softint = 0; 606 // disable timer compare interrupts, reset tick_cmpr 607 tc->setMiscRegNoEffect(MISCREG_ 608 tick_cmprFields.int_dis = 1; 609 tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing |
610 stickFields.npt = 1; // The TICK register is unreadable by by !priv |
611 stick_cmprFields.int_dis = 1; // disable timer compare interrupts 612 stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing 613 614 tt[tl] = _trapType; 615 616 hintp = 0; // no interrupts pending 617 hstick_cmprFields.int_dis = 1; // disable timer compare interrupts 618 hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing 619 */ 620} 621 622#else // !FULL_SYSTEM 623 |
624void 625FastInstructionAccessMMUMiss::invoke(ThreadContext *tc, StaticInstPtr inst) |
626{ 627 Process *p = tc->getProcessPtr(); 628 TlbEntry entry; 629 bool success = p->pTable->lookup(vaddr, entry); |
630 if (!success) { |
631 panic("Tried to execute unmapped address %#x.\n", vaddr); 632 } else { 633 Addr alignedVaddr = p->pTable->pageAlign(vaddr); 634 tc->getITBPtr()->insert(alignedVaddr, 0 /*partition id*/, 635 p->M5_pid /*context id*/, false, entry.pte); 636 } 637} 638 |
639void 640FastDataAccessMMUMiss::invoke(ThreadContext *tc, StaticInstPtr inst) |
641{ 642 Process *p = tc->getProcessPtr(); 643 TlbEntry entry; 644 bool success = p->pTable->lookup(vaddr, entry); |
645 if (!success) { |
646 p->checkAndAllocNextPage(vaddr); 647 success = p->pTable->lookup(vaddr, entry); 648 } |
649 if (!success) { |
650 panic("Tried to access unmapped address %#x.\n", vaddr); 651 } else { 652 Addr alignedVaddr = p->pTable->pageAlign(vaddr); 653 tc->getDTBPtr()->insert(alignedVaddr, 0 /*partition id*/, 654 p->M5_pid /*context id*/, false, entry.pte); 655 } 656} 657 |
658void 659SpillNNormal::invoke(ThreadContext *tc, StaticInstPtr inst) |
660{ 661 doNormalFault(tc, trapType(), false); 662 663 Process *p = tc->getProcessPtr(); 664 665 //XXX This will only work in faults from a SparcLiveProcess 666 SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); 667 assert(lp); 668 |
669 // Then adjust the PC and NPC |
670 tc->pcState(lp->readSpillStart()); 671} 672 |
673void 674FillNNormal::invoke(ThreadContext *tc, StaticInstPtr inst) |
675{ 676 doNormalFault(tc, trapType(), false); 677 |
678 Process *p = tc->getProcessPtr(); |
679 680 //XXX This will only work in faults from a SparcLiveProcess 681 SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); 682 assert(lp); 683 |
684 // Then adjust the PC and NPC |
685 tc->pcState(lp->readFillStart()); 686} 687 |
688void 689TrapInstruction::invoke(ThreadContext *tc, StaticInstPtr inst) |
690{ |
691 // In SE, this mechanism is how the process requests a service from the 692 // operating system. We'll get the process object from the thread context 693 // and let it service the request. |
694 695 Process *p = tc->getProcessPtr(); 696 697 SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); 698 assert(lp); 699 700 lp->handleTrap(_n, tc); 701 |
702 // We need to explicitly advance the pc, since that's not done for us 703 // on a faulting instruction |
704 PCState pc = tc->pcState(); 705 pc.advance(); 706 tc->pcState(pc); 707} 708 709#endif 710 711} // namespace SparcISA 712 |