faults.cc (3576:c5a2b916a9fa) | faults.cc (3578:6ef440cfc250) |
---|---|
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; --- 19 unchanged lines hidden (view full) --- 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" | 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; --- 19 unchanged lines hidden (view full) --- 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/types.hh" |
|
36#include "base/bitfield.hh" 37#include "base/trace.hh" 38#include "config/full_system.hh" 39#include "cpu/base.hh" 40#include "cpu/thread_context.hh" 41#if !FULL_SYSTEM 42#include "arch/sparc/process.hh" 43#include "mem/page_table.hh" --- 220 unchanged lines hidden (view full) --- 264 265#if !FULL_SYSTEM 266template<> SparcFaultBase::FaultVals 267 SparcFault<PageTableFault>::vals = 268 {"page_table_fault", 0x0000, 0, {SH, SH, SH}}; 269#endif 270 271/** | 37#include "base/bitfield.hh" 38#include "base/trace.hh" 39#include "config/full_system.hh" 40#include "cpu/base.hh" 41#include "cpu/thread_context.hh" 42#if !FULL_SYSTEM 43#include "arch/sparc/process.hh" 44#include "mem/page_table.hh" --- 220 unchanged lines hidden (view full) --- 265 266#if !FULL_SYSTEM 267template<> SparcFaultBase::FaultVals 268 SparcFault<PageTableFault>::vals = 269 {"page_table_fault", 0x0000, 0, {SH, SH, SH}}; 270#endif 271 272/** |
273 * This causes the thread context to enter RED state. This causes the side 274 * effects which go with entering RED state because of a trap. 275 */ 276 277void enterREDState(ThreadContext *tc) 278{ 279 //@todo Disable the mmu? 280 //@todo Disable watchpoints? 281 MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); 282 //HPSTATE.red = 1 283 HPSTATE |= (1 << 5); 284 //HPSTATE.hpriv = 1 285 HPSTATE |= (1 << 2); 286 tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); 287} 288 289/** 290 * This sets everything up for a RED state trap except for actually jumping to 291 * the handler. 292 */ 293 294void doREDFault(ThreadContext *tc, TrapType tt) 295{ 296 MiscReg TL = tc->readMiscReg(MISCREG_TL); 297 MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); 298 MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); 299 MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); 300 MiscReg CCR = tc->readMiscReg(MISCREG_CCR); 301 MiscReg ASI = tc->readMiscReg(MISCREG_ASI); 302 MiscReg CWP = tc->readMiscReg(MISCREG_CWP); 303 MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); 304 MiscReg GL = tc->readMiscReg(MISCREG_GL); 305 MiscReg PC = tc->readPC(); 306 MiscReg NPC = tc->readNextPC(); 307 308 TL++; 309 310 //set TSTATE.gl to gl 311 replaceBits(TSTATE, 42, 40, GL); 312 //set TSTATE.ccr to ccr 313 replaceBits(TSTATE, 39, 32, CCR); 314 //set TSTATE.asi to asi 315 replaceBits(TSTATE, 31, 24, ASI); 316 //set TSTATE.pstate to pstate 317 replaceBits(TSTATE, 20, 8, PSTATE); 318 //set TSTATE.cwp to cwp 319 replaceBits(TSTATE, 4, 0, CWP); 320 321 //Write back TSTATE 322 tc->setMiscReg(MISCREG_TSTATE, TSTATE); 323 324 //set TPC to PC 325 tc->setMiscReg(MISCREG_TPC, PC); 326 //set TNPC to NPC 327 tc->setMiscReg(MISCREG_TNPC, NPC); 328 329 //set HTSTATE.hpstate to hpstate 330 tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); 331 332 //TT = trap type; 333 tc->setMiscReg(MISCREG_TT, tt); 334 335 //Update GL 336 tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); 337 338 //set PSTATE.mm to 00 339 //set PSTATE.pef to 1 340 PSTATE |= (1 << 4); 341 //set PSTATE.am to 0 342 PSTATE &= ~(1 << 3); 343 //set PSTATE.priv to 0 344 PSTATE &= ~(1 << 2); 345 //set PSTATE.ie to 0 346 PSTATE &= ~(1 << 1); 347 //set PSTATE.cle to 0 348 PSTATE &= ~(1 << 9); 349 //PSTATE.tle is unchanged 350 //XXX Where is the tct bit? 351 //set PSTATE.tct to 0 352 tc->setMiscReg(MISCREG_PSTATE, PSTATE); 353 354 //set HPSTATE.red to 1 355 HPSTATE |= (1 << 5); 356 //set HPSTATE.hpriv to 1 357 HPSTATE |= (1 << 2); 358 //set HPSTATE.ibe to 0 359 HPSTATE &= ~(1 << 10); 360 //set HPSTATE.tlz to 0 361 HPSTATE &= ~(1 << 0); 362 tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); 363 364 bool changedCWP = true; 365 if(tt == 0x24) 366 CWP++; 367 else if(0x80 <= tt && tt <= 0xbf) 368 CWP += (CANSAVE + 2); 369 else if(0xc0 <= tt && tt <= 0xff) 370 CWP--; 371 else 372 changedCWP = false; 373 374 if(changedCWP) 375 { 376 CWP = (CWP + NWindows) % NWindows; 377 tc->setMiscRegWithEffect(MISCREG_CWP, CWP); 378 } 379} 380 381/** |
|
272 * This sets everything up for a normal trap except for actually jumping to | 382 * This sets everything up for a normal trap except for actually jumping to |
273 * the handler. It will need to be expanded to include the state machine in 274 * the manual. Right now it assumes that traps will always be to the 275 * privileged level. | 383 * the handler. |
276 */ 277 | 384 */ 385 |
278void doNormalFault(ThreadContext *tc, TrapType tt) | 386void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) |
279{ | 387{ |
280 uint64_t TL = tc->readMiscReg(MISCREG_TL); 281 uint64_t TSTATE = tc->readMiscReg(MISCREG_TSTATE); 282 uint64_t PSTATE = tc->readMiscReg(MISCREG_PSTATE); 283 uint64_t HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); 284 uint64_t CCR = tc->readMiscReg(MISCREG_CCR); 285 uint64_t ASI = tc->readMiscReg(MISCREG_ASI); 286 uint64_t CWP = tc->readMiscReg(MISCREG_CWP); 287 uint64_t CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); 288 uint64_t GL = tc->readMiscReg(MISCREG_GL); 289 uint64_t PC = tc->readPC(); 290 uint64_t NPC = tc->readNextPC(); | 388 MiscReg TL = tc->readMiscReg(MISCREG_TL); 389 MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); 390 MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); 391 MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); 392 MiscReg CCR = tc->readMiscReg(MISCREG_CCR); 393 MiscReg ASI = tc->readMiscReg(MISCREG_ASI); 394 MiscReg CWP = tc->readMiscReg(MISCREG_CWP); 395 MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); 396 MiscReg GL = tc->readMiscReg(MISCREG_GL); 397 MiscReg PC = tc->readPC(); 398 MiscReg NPC = tc->readNextPC(); |
291 292 //Increment the trap level 293 TL++; 294 tc->setMiscReg(MISCREG_TL, TL); 295 296 //Save off state 297 298 //set TSTATE.gl to gl --- 17 unchanged lines hidden (view full) --- 316 317 //set HTSTATE.hpstate to hpstate 318 tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); 319 320 //TT = trap type; 321 tc->setMiscReg(MISCREG_TT, tt); 322 323 //Update the global register level | 399 400 //Increment the trap level 401 TL++; 402 tc->setMiscReg(MISCREG_TL, TL); 403 404 //Save off state 405 406 //set TSTATE.gl to gl --- 17 unchanged lines hidden (view full) --- 424 425 //set HTSTATE.hpstate to hpstate 426 tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); 427 428 //TT = trap type; 429 tc->setMiscReg(MISCREG_TT, tt); 430 431 //Update the global register level |
324 if(1/*We're delivering the trap in priveleged mode*/) 325 tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL)); | 432 if(!gotoHpriv) 433 tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxPGL)); |
326 else | 434 else |
327 tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxPGL)); | 435 tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); |
328 329 //PSTATE.mm is unchanged 330 //PSTATE.pef = whether or not an fpu is present 331 //XXX We'll say there's one present, even though there aren't 332 //implementations for a decent number of the instructions 333 PSTATE |= (1 << 4); 334 //PSTATE.am = 0 335 PSTATE &= ~(1 << 3); | 436 437 //PSTATE.mm is unchanged 438 //PSTATE.pef = whether or not an fpu is present 439 //XXX We'll say there's one present, even though there aren't 440 //implementations for a decent number of the instructions 441 PSTATE |= (1 << 4); 442 //PSTATE.am = 0 443 PSTATE &= ~(1 << 3); |
336 if(1/*We're delivering the trap in priveleged mode*/) | 444 if(!gotoHpriv) |
337 { 338 //PSTATE.priv = 1 339 PSTATE |= (1 << 2); 340 //PSTATE.cle = PSTATE.tle 341 replaceBits(PSTATE, 9, 9, PSTATE >> 8); 342 } 343 else 344 { --- 4 unchanged lines hidden (view full) --- 349 } 350 //PSTATE.ie = 0 351 PSTATE &= ~(1 << 1); 352 //PSTATE.tle is unchanged 353 //PSTATE.tct = 0 354 //XXX Where exactly is this field? 355 tc->setMiscReg(MISCREG_PSTATE, PSTATE); 356 | 445 { 446 //PSTATE.priv = 1 447 PSTATE |= (1 << 2); 448 //PSTATE.cle = PSTATE.tle 449 replaceBits(PSTATE, 9, 9, PSTATE >> 8); 450 } 451 else 452 { --- 4 unchanged lines hidden (view full) --- 457 } 458 //PSTATE.ie = 0 459 PSTATE &= ~(1 << 1); 460 //PSTATE.tle is unchanged 461 //PSTATE.tct = 0 462 //XXX Where exactly is this field? 463 tc->setMiscReg(MISCREG_PSTATE, PSTATE); 464 |
357 if(0/*We're delivering the trap in hyperprivileged mode*/) | 465 if(gotoHpriv) |
358 { 359 //HPSTATE.red = 0 360 HPSTATE &= ~(1 << 5); 361 //HPSTATE.hpriv = 1 362 HPSTATE |= (1 << 2); 363 //HPSTATE.ibe = 0 364 HPSTATE &= ~(1 << 10); 365 //HPSTATE.tlz is unchanged --- 12 unchanged lines hidden (view full) --- 378 379 if(changedCWP) 380 { 381 CWP = (CWP + NWindows) % NWindows; 382 tc->setMiscRegWithEffect(MISCREG_CWP, CWP); 383 } 384} 385 | 466 { 467 //HPSTATE.red = 0 468 HPSTATE &= ~(1 << 5); 469 //HPSTATE.hpriv = 1 470 HPSTATE |= (1 << 2); 471 //HPSTATE.ibe = 0 472 HPSTATE &= ~(1 << 10); 473 //HPSTATE.tlz is unchanged --- 12 unchanged lines hidden (view full) --- 486 487 if(changedCWP) 488 { 489 CWP = (CWP + NWindows) % NWindows; 490 tc->setMiscRegWithEffect(MISCREG_CWP, CWP); 491 } 492} 493 |
494void getREDVector(Addr & PC, Addr & NPC) 495{ 496 const Addr RSTVAddr = 0xFFFFFFFFF0000000ULL; 497 PC = RSTVAddr | 0xA0; 498 NPC = PC + sizeof(MachInst); 499} 500 501void getHyperVector(Addr & PC, Addr & NPC, MiscReg TT) 502{ 503 Addr HTBA ; 504 PC = (HTBA & ~mask(14)) | ((TT << 5) & mask(14)); 505 NPC = PC + sizeof(MachInst); 506} 507 508void getPrivVector(Addr & PC, Addr & NPC, MiscReg TT, MiscReg TL) 509{ 510 Addr TBA ; 511 PC = (TBA & ~mask(15)) | 512 (TL > 1 ? (1 << 14) : 0) | 513 ((TT << 5) & mask(14)); 514 NPC = PC + sizeof(MachInst); 515} 516 |
|
386#if FULL_SYSTEM 387 388void SparcFaultBase::invoke(ThreadContext * tc) 389{ 390 FaultBase::invoke(tc); 391 countStat()++; 392 | 517#if FULL_SYSTEM 518 519void SparcFaultBase::invoke(ThreadContext * tc) 520{ 521 FaultBase::invoke(tc); 522 countStat()++; 523 |
393 //Use the SPARC trap state machine | 524 //We can refer to this to see what the trap level -was-, but something 525 //in the middle could change it in the regfile out from under us. 526 MiscReg TL = tc->readMiscReg(MISCREG_TL); 527 MiscReg TT = tc->readMiscReg(MISCREG_TT); 528 MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); 529 MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); 530 531 Addr PC, NPC; 532 533 PrivilegeLevel current; 534 if(!(PSTATE & (1 << 2))) 535 current = User; 536 else if(!(HPSTATE & (1 << 2))) 537 current = Privileged; 538 else 539 current = Hyperprivileged; 540 541 PrivilegeLevel level = getNextLevel(current); 542 543 if(HPSTATE & (1 << 5) || TL == MaxTL - 1) 544 { 545 getREDVector(PC, NPC); 546 enterREDState(tc); 547 doREDFault(tc, TT); 548 } 549 else if(TL == MaxTL) 550 { 551 //Do error_state somehow? 552 //Probably inject a WDR fault using the interrupt mechanism. 553 //What should the PC and NPC be set to? 554 } 555 else if(TL > MaxPTL && level == Privileged) 556 { 557 //guest_watchdog fault 558 doNormalFault(tc, trapType(), true); 559 getHyperVector(PC, NPC, 2); 560 } 561 else if(level == Hyperprivileged) 562 { 563 doNormalFault(tc, trapType(), true); 564 getHyperVector(PC, NPC, trapType()); 565 } 566 else 567 { 568 doNormalFault(tc, trapType(), false); 569 getPrivVector(PC, NPC, trapType(), TL+1); 570 } 571 572 tc->setPC(PC); 573 tc->setNextPC(NPC); 574 tc->setNextNPC(NPC + sizeof(MachInst)); |
394} 395 396void PowerOnReset::invoke(ThreadContext * tc) 397{ | 575} 576 577void PowerOnReset::invoke(ThreadContext * tc) 578{ |
579 //First, enter RED state. 580 enterREDState(tc); 581 |
|
398 //For SPARC, when a system is first started, there is a power 399 //on reset Trap which sets the processor into the following state. 400 //Bits that aren't set aren't defined on startup. 401 /* 402 tl = MaxTL; 403 gl = MaxGL; 404 405 tickFields.counter = 0; //The TICK register is unreadable bya --- 15 unchanged lines hidden (view full) --- 421 hpstateFields.hpriv = 1; 422 hpstateFields.tlz = 0; // this is a guess 423 hintp = 0; // no interrupts pending 424 hstick_cmprFields.int_dis = 1; // disable timer compare interrupts 425 hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing 426 */ 427} 428 | 582 //For SPARC, when a system is first started, there is a power 583 //on reset Trap which sets the processor into the following state. 584 //Bits that aren't set aren't defined on startup. 585 /* 586 tl = MaxTL; 587 gl = MaxGL; 588 589 tickFields.counter = 0; //The TICK register is unreadable bya --- 15 unchanged lines hidden (view full) --- 605 hpstateFields.hpriv = 1; 606 hpstateFields.tlz = 0; // this is a guess 607 hintp = 0; // no interrupts pending 608 hstick_cmprFields.int_dis = 1; // disable timer compare interrupts 609 hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing 610 */ 611} 612 |
429#endif | 613#else // !FULL_SYSTEM |
430 | 614 |
431#if !FULL_SYSTEM 432 | |
433void SpillNNormal::invoke(ThreadContext *tc) 434{ | 615void SpillNNormal::invoke(ThreadContext *tc) 616{ |
435 doNormalFault(tc, trapType()); | 617 doNormalFault(tc, trapType(), false); |
436 437 Process *p = tc->getProcessPtr(); 438 | 618 619 Process *p = tc->getProcessPtr(); 620 |
439 //This will only work in faults from a SparcLiveProcess | 621 //XXX This will only work in faults from a SparcLiveProcess |
440 SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); 441 assert(lp); 442 443 //Then adjust the PC and NPC 444 Addr spillStart = lp->readSpillStart(); 445 tc->setPC(spillStart); 446 tc->setNextPC(spillStart + sizeof(MachInst)); 447 tc->setNextNPC(spillStart + 2*sizeof(MachInst)); 448} 449 450void FillNNormal::invoke(ThreadContext *tc) 451{ | 622 SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); 623 assert(lp); 624 625 //Then adjust the PC and NPC 626 Addr spillStart = lp->readSpillStart(); 627 tc->setPC(spillStart); 628 tc->setNextPC(spillStart + sizeof(MachInst)); 629 tc->setNextNPC(spillStart + 2*sizeof(MachInst)); 630} 631 632void FillNNormal::invoke(ThreadContext *tc) 633{ |
452 doNormalFault(tc, trapType()); | 634 doNormalFault(tc, trapType(), false); |
453 454 Process * p = tc->getProcessPtr(); 455 | 635 636 Process * p = tc->getProcessPtr(); 637 |
456 //This will only work in faults from a SparcLiveProcess | 638 //XXX This will only work in faults from a SparcLiveProcess |
457 SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); 458 assert(lp); 459 | 639 SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); 640 assert(lp); 641 |
460 //The adjust the PC and NPC | 642 //Then adjust the PC and NPC |
461 Addr fillStart = lp->readFillStart(); 462 tc->setPC(fillStart); 463 tc->setNextPC(fillStart + sizeof(MachInst)); 464 tc->setNextNPC(fillStart + 2*sizeof(MachInst)); 465} 466 467void PageTableFault::invoke(ThreadContext *tc) 468{ --- 22 unchanged lines hidden --- | 643 Addr fillStart = lp->readFillStart(); 644 tc->setPC(fillStart); 645 tc->setNextPC(fillStart + sizeof(MachInst)); 646 tc->setNextNPC(fillStart + 2*sizeof(MachInst)); 647} 648 649void PageTableFault::invoke(ThreadContext *tc) 650{ --- 22 unchanged lines hidden --- |