ev5.cc revision 1717
1/* $Id$ */ 2 3#include "arch/alpha/alpha_memory.hh" 4#include "arch/alpha/isa_traits.hh" 5#include "arch/alpha/osfpal.hh" 6#include "base/kgdb.h" 7#include "base/remote_gdb.hh" 8#include "base/stats/events.hh" 9#include "cpu/base.hh" 10#include "cpu/exec_context.hh" 11#include "cpu/fast/cpu.hh" 12#include "kern/kernel_stats.hh" 13#include "sim/debug.hh" 14#include "sim/sim_events.hh" 15 16#ifdef FULL_SYSTEM 17 18using namespace EV5; 19 20//////////////////////////////////////////////////////////////////////// 21// 22// 23// 24void 25AlphaISA::swap_palshadow(RegFile *regs, bool use_shadow) 26{ 27 if (regs->pal_shadow == use_shadow) 28 panic("swap_palshadow: wrong PAL shadow state"); 29 30 regs->pal_shadow = use_shadow; 31 32 for (int i = 0; i < NumIntRegs; i++) { 33 if (reg_redir[i]) { 34 IntReg temp = regs->intRegFile[i]; 35 regs->intRegFile[i] = regs->palregs[i]; 36 regs->palregs[i] = temp; 37 } 38 } 39} 40 41//////////////////////////////////////////////////////////////////////// 42// 43// Machine dependent functions 44// 45void 46AlphaISA::initCPU(RegFile *regs) 47{ 48 initIPRs(regs); 49 // CPU comes up with PAL regs enabled 50 swap_palshadow(regs, true); 51 52 regs->pc = regs->ipr[IPR_PAL_BASE] + fault_addr[Reset_Fault]; 53 regs->npc = regs->pc + sizeof(MachInst); 54} 55 56//////////////////////////////////////////////////////////////////////// 57// 58// alpha exceptions - value equals trap address, update with MD_FAULT_TYPE 59// 60Addr 61AlphaISA::fault_addr[Num_Faults] = { 62 0x0000, /* No_Fault */ 63 0x0001, /* Reset_Fault */ 64 0x0401, /* Machine_Check_Fault */ 65 0x0501, /* Arithmetic_Fault */ 66 0x0101, /* Interrupt_Fault */ 67 0x0201, /* Ndtb_Miss_Fault */ 68 0x0281, /* Pdtb_Miss_Fault */ 69 0x0301, /* Alignment_Fault */ 70 0x0381, /* DTB_Fault_Fault */ 71 0x0381, /* DTB_Acv_Fault */ 72 0x0181, /* ITB_Miss_Fault */ 73 0x0181, /* ITB_Fault_Fault */ 74 0x0081, /* ITB_Acv_Fault */ 75 0x0481, /* Unimplemented_Opcode_Fault */ 76 0x0581, /* Fen_Fault */ 77 0x2001, /* Pal_Fault */ 78 0x0501, /* Integer_Overflow_Fault: maps to Arithmetic_Fault */ 79}; 80 81const int AlphaISA::reg_redir[AlphaISA::NumIntRegs] = { 82 /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 83 /* 8 */ 1, 1, 1, 1, 1, 1, 1, 0, 84 /* 16 */ 0, 0, 0, 0, 0, 0, 0, 0, 85 /* 24 */ 0, 1, 0, 0, 0, 0, 0, 0 }; 86 87//////////////////////////////////////////////////////////////////////// 88// 89// 90// 91void 92AlphaISA::initIPRs(RegFile *regs) 93{ 94 uint64_t *ipr = regs->ipr; 95 96 bzero((char *)ipr, NumInternalProcRegs * sizeof(InternalProcReg)); 97 ipr[IPR_PAL_BASE] = PalBase; 98 ipr[IPR_MCSR] = 0x6; 99} 100 101 102template <class CPU> 103void 104AlphaISA::processInterrupts(CPU *cpu) 105{ 106 //Check if there are any outstanding interrupts 107 //Handle the interrupts 108 int ipl = 0; 109 int summary = 0; 110 IntReg *ipr = cpu->getIprPtr(); 111 112 cpu->checkInterrupts = false; 113 114 if (ipr[IPR_ASTRR]) 115 panic("asynchronous traps not implemented\n"); 116 117 if (ipr[IPR_SIRR]) { 118 for (int i = INTLEVEL_SOFTWARE_MIN; 119 i < INTLEVEL_SOFTWARE_MAX; i++) { 120 if (ipr[IPR_SIRR] & (ULL(1) << i)) { 121 // See table 4-19 of the 21164 hardware reference 122 ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; 123 summary |= (ULL(1) << i); 124 } 125 } 126 } 127 128 uint64_t interrupts = cpu->intr_status(); 129 130 if (interrupts) { 131 for (int i = INTLEVEL_EXTERNAL_MIN; 132 i < INTLEVEL_EXTERNAL_MAX; i++) { 133 if (interrupts & (ULL(1) << i)) { 134 // See table 4-19 of the 21164 hardware reference 135 ipl = i; 136 summary |= (ULL(1) << i); 137 } 138 } 139 } 140 141 if (ipl && ipl > ipr[IPR_IPLR]) { 142 ipr[IPR_ISR] = summary; 143 ipr[IPR_INTID] = ipl; 144 cpu->trap(Interrupt_Fault); 145 DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", 146 ipr[IPR_IPLR], ipl, summary); 147 } 148 149} 150 151template <class CPU> 152void 153AlphaISA::zeroRegisters(CPU *cpu) 154{ 155 // Insure ISA semantics 156 // (no longer very clean due to the change in setIntReg() in the 157 // cpu model. Consider changing later.) 158 cpu->xc->setIntReg(ZeroReg, 0); 159 cpu->xc->setFloatRegDouble(ZeroReg, 0.0); 160} 161 162void 163ExecContext::ev5_trap(Fault fault) 164{ 165 DPRINTF(Fault, "Fault %s at PC: %#x\n", FaultName(fault), regs.pc); 166 cpu->recordEvent(csprintf("Fault %s", FaultName(fault))); 167 168 assert(!misspeculating()); 169 kernelStats->fault(fault); 170 171 if (fault == Arithmetic_Fault) 172 panic("Arithmetic traps are unimplemented!"); 173 174 AlphaISA::InternalProcReg *ipr = regs.ipr; 175 176 // exception restart address 177 if (fault != Interrupt_Fault || !inPalMode()) 178 ipr[AlphaISA::IPR_EXC_ADDR] = regs.pc; 179 180 if (fault == Pal_Fault || fault == Arithmetic_Fault /* || 181 fault == Interrupt_Fault && !inPalMode() */) { 182 // traps... skip faulting instruction 183 ipr[AlphaISA::IPR_EXC_ADDR] += 4; 184 } 185 186 if (!inPalMode()) 187 AlphaISA::swap_palshadow(®s, true); 188 189 regs.pc = ipr[AlphaISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault]; 190 regs.npc = regs.pc + sizeof(MachInst); 191} 192 193 194void 195AlphaISA::intr_post(RegFile *regs, Fault fault, Addr pc) 196{ 197 InternalProcReg *ipr = regs->ipr; 198 bool use_pc = (fault == No_Fault); 199 200 if (fault == Arithmetic_Fault) 201 panic("arithmetic faults NYI..."); 202 203 // compute exception restart address 204 if (use_pc || fault == Pal_Fault || fault == Arithmetic_Fault) { 205 // traps... skip faulting instruction 206 ipr[IPR_EXC_ADDR] = regs->pc + 4; 207 } else { 208 // fault, post fault at excepting instruction 209 ipr[IPR_EXC_ADDR] = regs->pc; 210 } 211 212 // jump to expection address (PAL PC bit set here as well...) 213 if (!use_pc) 214 regs->npc = ipr[IPR_PAL_BASE] + fault_addr[fault]; 215 else 216 regs->npc = ipr[IPR_PAL_BASE] + pc; 217 218 // that's it! (orders of magnitude less painful than x86) 219} 220 221Fault 222ExecContext::hwrei() 223{ 224 uint64_t *ipr = regs.ipr; 225 226 if (!inPalMode()) 227 return Unimplemented_Opcode_Fault; 228 229 setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]); 230 231 if (!misspeculating()) { 232 kernelStats->hwrei(); 233 234 if ((ipr[AlphaISA::IPR_EXC_ADDR] & 1) == 0) 235 AlphaISA::swap_palshadow(®s, false); 236 237 cpu->checkInterrupts = true; 238 } 239 240 // FIXME: XXX check for interrupts? XXX 241 return No_Fault; 242} 243 244uint64_t 245ExecContext::readIpr(int idx, Fault &fault) 246{ 247 uint64_t *ipr = regs.ipr; 248 uint64_t retval = 0; // return value, default 0 249 250 switch (idx) { 251 case AlphaISA::IPR_PALtemp0: 252 case AlphaISA::IPR_PALtemp1: 253 case AlphaISA::IPR_PALtemp2: 254 case AlphaISA::IPR_PALtemp3: 255 case AlphaISA::IPR_PALtemp4: 256 case AlphaISA::IPR_PALtemp5: 257 case AlphaISA::IPR_PALtemp6: 258 case AlphaISA::IPR_PALtemp7: 259 case AlphaISA::IPR_PALtemp8: 260 case AlphaISA::IPR_PALtemp9: 261 case AlphaISA::IPR_PALtemp10: 262 case AlphaISA::IPR_PALtemp11: 263 case AlphaISA::IPR_PALtemp12: 264 case AlphaISA::IPR_PALtemp13: 265 case AlphaISA::IPR_PALtemp14: 266 case AlphaISA::IPR_PALtemp15: 267 case AlphaISA::IPR_PALtemp16: 268 case AlphaISA::IPR_PALtemp17: 269 case AlphaISA::IPR_PALtemp18: 270 case AlphaISA::IPR_PALtemp19: 271 case AlphaISA::IPR_PALtemp20: 272 case AlphaISA::IPR_PALtemp21: 273 case AlphaISA::IPR_PALtemp22: 274 case AlphaISA::IPR_PALtemp23: 275 case AlphaISA::IPR_PAL_BASE: 276 277 case AlphaISA::IPR_IVPTBR: 278 case AlphaISA::IPR_DC_MODE: 279 case AlphaISA::IPR_MAF_MODE: 280 case AlphaISA::IPR_ISR: 281 case AlphaISA::IPR_EXC_ADDR: 282 case AlphaISA::IPR_IC_PERR_STAT: 283 case AlphaISA::IPR_DC_PERR_STAT: 284 case AlphaISA::IPR_MCSR: 285 case AlphaISA::IPR_ASTRR: 286 case AlphaISA::IPR_ASTER: 287 case AlphaISA::IPR_SIRR: 288 case AlphaISA::IPR_ICSR: 289 case AlphaISA::IPR_ICM: 290 case AlphaISA::IPR_DTB_CM: 291 case AlphaISA::IPR_IPLR: 292 case AlphaISA::IPR_INTID: 293 case AlphaISA::IPR_PMCTR: 294 // no side-effect 295 retval = ipr[idx]; 296 break; 297 298 case AlphaISA::IPR_CC: 299 retval |= ipr[idx] & ULL(0xffffffff00000000); 300 retval |= cpu->curCycle() & ULL(0x00000000ffffffff); 301 break; 302 303 case AlphaISA::IPR_VA: 304 retval = ipr[idx]; 305 break; 306 307 case AlphaISA::IPR_VA_FORM: 308 case AlphaISA::IPR_MM_STAT: 309 case AlphaISA::IPR_IFAULT_VA_FORM: 310 case AlphaISA::IPR_EXC_MASK: 311 case AlphaISA::IPR_EXC_SUM: 312 retval = ipr[idx]; 313 break; 314 315 case AlphaISA::IPR_DTB_PTE: 316 { 317 AlphaISA::PTE &pte = dtb->index(!misspeculating()); 318 319 retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32; 320 retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8; 321 retval |= ((u_int64_t)pte.xwe & ULL(0xf)) << 12; 322 retval |= ((u_int64_t)pte.fonr & ULL(0x1)) << 1; 323 retval |= ((u_int64_t)pte.fonw & ULL(0x1))<< 2; 324 retval |= ((u_int64_t)pte.asma & ULL(0x1)) << 4; 325 retval |= ((u_int64_t)pte.asn & ULL(0x7f)) << 57; 326 } 327 break; 328 329 // write only registers 330 case AlphaISA::IPR_HWINT_CLR: 331 case AlphaISA::IPR_SL_XMIT: 332 case AlphaISA::IPR_DC_FLUSH: 333 case AlphaISA::IPR_IC_FLUSH: 334 case AlphaISA::IPR_ALT_MODE: 335 case AlphaISA::IPR_DTB_IA: 336 case AlphaISA::IPR_DTB_IAP: 337 case AlphaISA::IPR_ITB_IA: 338 case AlphaISA::IPR_ITB_IAP: 339 fault = Unimplemented_Opcode_Fault; 340 break; 341 342 default: 343 // invalid IPR 344 fault = Unimplemented_Opcode_Fault; 345 break; 346 } 347 348 return retval; 349} 350 351#ifdef DEBUG 352// Cause the simulator to break when changing to the following IPL 353int break_ipl = -1; 354#endif 355 356Fault 357ExecContext::setIpr(int idx, uint64_t val) 358{ 359 uint64_t *ipr = regs.ipr; 360 uint64_t old; 361 362 if (misspeculating()) 363 return No_Fault; 364 365 switch (idx) { 366 case AlphaISA::IPR_PALtemp0: 367 case AlphaISA::IPR_PALtemp1: 368 case AlphaISA::IPR_PALtemp2: 369 case AlphaISA::IPR_PALtemp3: 370 case AlphaISA::IPR_PALtemp4: 371 case AlphaISA::IPR_PALtemp5: 372 case AlphaISA::IPR_PALtemp6: 373 case AlphaISA::IPR_PALtemp7: 374 case AlphaISA::IPR_PALtemp8: 375 case AlphaISA::IPR_PALtemp9: 376 case AlphaISA::IPR_PALtemp10: 377 case AlphaISA::IPR_PALtemp11: 378 case AlphaISA::IPR_PALtemp12: 379 case AlphaISA::IPR_PALtemp13: 380 case AlphaISA::IPR_PALtemp14: 381 case AlphaISA::IPR_PALtemp15: 382 case AlphaISA::IPR_PALtemp16: 383 case AlphaISA::IPR_PALtemp17: 384 case AlphaISA::IPR_PALtemp18: 385 case AlphaISA::IPR_PALtemp19: 386 case AlphaISA::IPR_PALtemp20: 387 case AlphaISA::IPR_PALtemp21: 388 case AlphaISA::IPR_PALtemp22: 389 case AlphaISA::IPR_PAL_BASE: 390 case AlphaISA::IPR_IC_PERR_STAT: 391 case AlphaISA::IPR_DC_PERR_STAT: 392 case AlphaISA::IPR_PMCTR: 393 // write entire quad w/ no side-effect 394 ipr[idx] = val; 395 break; 396 397 case AlphaISA::IPR_CC_CTL: 398 // This IPR resets the cycle counter. We assume this only 399 // happens once... let's verify that. 400 assert(ipr[idx] == 0); 401 ipr[idx] = 1; 402 break; 403 404 case AlphaISA::IPR_CC: 405 // This IPR only writes the upper 64 bits. It's ok to write 406 // all 64 here since we mask out the lower 32 in rpcc (see 407 // isa_desc). 408 ipr[idx] = val; 409 break; 410 411 case AlphaISA::IPR_PALtemp23: 412 // write entire quad w/ no side-effect 413 old = ipr[idx]; 414 ipr[idx] = val; 415 kernelStats->context(old, val); 416 break; 417 418 case AlphaISA::IPR_DTB_PTE: 419 // write entire quad w/ no side-effect, tag is forthcoming 420 ipr[idx] = val; 421 break; 422 423 case AlphaISA::IPR_EXC_ADDR: 424 // second least significant bit in PC is always zero 425 ipr[idx] = val & ~2; 426 break; 427 428 case AlphaISA::IPR_ASTRR: 429 case AlphaISA::IPR_ASTER: 430 // only write least significant four bits - privilege mask 431 ipr[idx] = val & 0xf; 432 break; 433 434 case AlphaISA::IPR_IPLR: 435#ifdef DEBUG 436 if (break_ipl != -1 && break_ipl == (val & 0x1f)) 437 debug_break(); 438#endif 439 440 // only write least significant five bits - interrupt level 441 ipr[idx] = val & 0x1f; 442 kernelStats->swpipl(ipr[idx]); 443 break; 444 445 case AlphaISA::IPR_DTB_CM: 446 if (val & 0x18) 447 kernelStats->mode(Kernel::user); 448 else 449 kernelStats->mode(Kernel::kernel); 450 451 case AlphaISA::IPR_ICM: 452 // only write two mode bits - processor mode 453 ipr[idx] = val & 0x18; 454 break; 455 456 case AlphaISA::IPR_ALT_MODE: 457 // only write two mode bits - processor mode 458 ipr[idx] = val & 0x18; 459 break; 460 461 case AlphaISA::IPR_MCSR: 462 // more here after optimization... 463 ipr[idx] = val; 464 break; 465 466 case AlphaISA::IPR_SIRR: 467 // only write software interrupt mask 468 ipr[idx] = val & 0x7fff0; 469 break; 470 471 case AlphaISA::IPR_ICSR: 472 ipr[idx] = val & ULL(0xffffff0300); 473 break; 474 475 case AlphaISA::IPR_IVPTBR: 476 case AlphaISA::IPR_MVPTBR: 477 ipr[idx] = val & ULL(0xffffffffc0000000); 478 break; 479 480 case AlphaISA::IPR_DC_TEST_CTL: 481 ipr[idx] = val & 0x1ffb; 482 break; 483 484 case AlphaISA::IPR_DC_MODE: 485 case AlphaISA::IPR_MAF_MODE: 486 ipr[idx] = val & 0x3f; 487 break; 488 489 case AlphaISA::IPR_ITB_ASN: 490 ipr[idx] = val & 0x7f0; 491 break; 492 493 case AlphaISA::IPR_DTB_ASN: 494 ipr[idx] = val & ULL(0xfe00000000000000); 495 break; 496 497 case AlphaISA::IPR_EXC_SUM: 498 case AlphaISA::IPR_EXC_MASK: 499 // any write to this register clears it 500 ipr[idx] = 0; 501 break; 502 503 case AlphaISA::IPR_INTID: 504 case AlphaISA::IPR_SL_RCV: 505 case AlphaISA::IPR_MM_STAT: 506 case AlphaISA::IPR_ITB_PTE_TEMP: 507 case AlphaISA::IPR_DTB_PTE_TEMP: 508 // read-only registers 509 return Unimplemented_Opcode_Fault; 510 511 case AlphaISA::IPR_HWINT_CLR: 512 case AlphaISA::IPR_SL_XMIT: 513 case AlphaISA::IPR_DC_FLUSH: 514 case AlphaISA::IPR_IC_FLUSH: 515 // the following are write only 516 ipr[idx] = val; 517 break; 518 519 case AlphaISA::IPR_DTB_IA: 520 // really a control write 521 ipr[idx] = 0; 522 523 dtb->flushAll(); 524 break; 525 526 case AlphaISA::IPR_DTB_IAP: 527 // really a control write 528 ipr[idx] = 0; 529 530 dtb->flushProcesses(); 531 break; 532 533 case AlphaISA::IPR_DTB_IS: 534 // really a control write 535 ipr[idx] = val; 536 537 dtb->flushAddr(val, DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); 538 break; 539 540 case AlphaISA::IPR_DTB_TAG: { 541 struct AlphaISA::PTE pte; 542 543 // FIXME: granularity hints NYI... 544 if (DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0) 545 panic("PTE GH field != 0"); 546 547 // write entire quad 548 ipr[idx] = val; 549 550 // construct PTE for new entry 551 pte.ppn = DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]); 552 pte.xre = DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]); 553 pte.xwe = DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]); 554 pte.fonr = DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]); 555 pte.fonw = DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]); 556 pte.asma = DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]); 557 pte.asn = DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]); 558 559 // insert new TAG/PTE value into data TLB 560 dtb->insert(val, pte); 561 } 562 break; 563 564 case AlphaISA::IPR_ITB_PTE: { 565 struct AlphaISA::PTE pte; 566 567 // FIXME: granularity hints NYI... 568 if (ITB_PTE_GH(val) != 0) 569 panic("PTE GH field != 0"); 570 571 // write entire quad 572 ipr[idx] = val; 573 574 // construct PTE for new entry 575 pte.ppn = ITB_PTE_PPN(val); 576 pte.xre = ITB_PTE_XRE(val); 577 pte.xwe = 0; 578 pte.fonr = ITB_PTE_FONR(val); 579 pte.fonw = ITB_PTE_FONW(val); 580 pte.asma = ITB_PTE_ASMA(val); 581 pte.asn = ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]); 582 583 // insert new TAG/PTE value into data TLB 584 itb->insert(ipr[AlphaISA::IPR_ITB_TAG], pte); 585 } 586 break; 587 588 case AlphaISA::IPR_ITB_IA: 589 // really a control write 590 ipr[idx] = 0; 591 592 itb->flushAll(); 593 break; 594 595 case AlphaISA::IPR_ITB_IAP: 596 // really a control write 597 ipr[idx] = 0; 598 599 itb->flushProcesses(); 600 break; 601 602 case AlphaISA::IPR_ITB_IS: 603 // really a control write 604 ipr[idx] = val; 605 606 itb->flushAddr(val, ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN])); 607 break; 608 609 default: 610 // invalid IPR 611 return Unimplemented_Opcode_Fault; 612 } 613 614 // no error... 615 return No_Fault; 616} 617 618/** 619 * Check for special simulator handling of specific PAL calls. 620 * If return value is false, actual PAL call will be suppressed. 621 */ 622bool 623ExecContext::simPalCheck(int palFunc) 624{ 625 kernelStats->callpal(palFunc); 626 627 switch (palFunc) { 628 case PAL::halt: 629 halt(); 630 if (--System::numSystemsRunning == 0) 631 new SimExitEvent("all cpus halted"); 632 break; 633 634 case PAL::bpt: 635 case PAL::bugchk: 636 if (system->breakpoint()) 637 return false; 638 break; 639 } 640 641 return true; 642} 643 644//Forward instantiation for FastCPU object 645template 646void AlphaISA::processInterrupts(FastCPU *xc); 647 648//Forward instantiation for FastCPU object 649template 650void AlphaISA::zeroRegisters(FastCPU *xc); 651 652#endif // FULL_SYSTEM 653