ev5.cc revision 7460:41550bb10e08
1/* 2 * Copyright (c) 2002-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: Steve Reinhardt 29 * Nathan Binkert 30 */ 31 32#include "arch/alpha/faults.hh" 33#include "arch/alpha/isa_traits.hh" 34#include "arch/alpha/kernel_stats.hh" 35#include "arch/alpha/osfpal.hh" 36#include "arch/alpha/tlb.hh" 37#include "base/cp_annotate.hh" 38#include "base/debug.hh" 39#include "config/full_system.hh" 40#include "cpu/base.hh" 41#include "cpu/simple_thread.hh" 42#include "cpu/thread_context.hh" 43#include "sim/sim_exit.hh" 44 45namespace AlphaISA { 46 47#if FULL_SYSTEM 48 49//////////////////////////////////////////////////////////////////////// 50// 51// Machine dependent functions 52// 53void 54initCPU(ThreadContext *tc, int cpuId) 55{ 56 initIPRs(tc, cpuId); 57 58 tc->setIntReg(16, cpuId); 59 tc->setIntReg(0, cpuId); 60 61 AlphaFault *reset = new ResetFault; 62 63 tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect()); 64 tc->setNextPC(tc->readPC() + sizeof(MachInst)); 65 66 delete reset; 67} 68 69 70template <class CPU> 71void 72processInterrupts(CPU *cpu) 73{ 74 //Check if there are any outstanding interrupts 75 //Handle the interrupts 76 int ipl = 0; 77 int summary = 0; 78 79 if (cpu->readMiscRegNoEffect(IPR_ASTRR)) 80 panic("asynchronous traps not implemented\n"); 81 82 if (cpu->readMiscRegNoEffect(IPR_SIRR)) { 83 for (int i = INTLEVEL_SOFTWARE_MIN; 84 i < INTLEVEL_SOFTWARE_MAX; i++) { 85 if (cpu->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) { 86 // See table 4-19 of the 21164 hardware reference 87 ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; 88 summary |= (ULL(1) << i); 89 } 90 } 91 } 92 93 uint64_t interrupts = cpu->intr_status(); 94 95 if (interrupts) { 96 for (int i = INTLEVEL_EXTERNAL_MIN; 97 i < INTLEVEL_EXTERNAL_MAX; i++) { 98 if (interrupts & (ULL(1) << i)) { 99 // See table 4-19 of the 21164 hardware reference 100 ipl = i; 101 summary |= (ULL(1) << i); 102 } 103 } 104 } 105 106 if (ipl && ipl > cpu->readMiscRegNoEffect(IPR_IPLR)) { 107 cpu->setMiscRegNoEffect(IPR_ISR, summary); 108 cpu->setMiscRegNoEffect(IPR_INTID, ipl); 109 cpu->trap(new InterruptFault); 110 DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", 111 cpu->readMiscRegNoEffect(IPR_IPLR), ipl, summary); 112 } 113 114} 115 116template <class CPU> 117void 118zeroRegisters(CPU *cpu) 119{ 120 // Insure ISA semantics 121 // (no longer very clean due to the change in setIntReg() in the 122 // cpu model. Consider changing later.) 123 cpu->thread->setIntReg(ZeroReg, 0); 124 cpu->thread->setFloatReg(ZeroReg, 0.0); 125} 126 127#endif 128 129//////////////////////////////////////////////////////////////////////// 130// 131// 132// 133void 134initIPRs(ThreadContext *tc, int cpuId) 135{ 136 for (int i = 0; i < NumInternalProcRegs; ++i) { 137 tc->setMiscRegNoEffect(i, 0); 138 } 139 140 tc->setMiscRegNoEffect(IPR_PAL_BASE, PalBase); 141 tc->setMiscRegNoEffect(IPR_MCSR, 0x6); 142 tc->setMiscRegNoEffect(IPR_PALtemp16, cpuId); 143} 144 145MiscReg 146ISA::readIpr(int idx, ThreadContext *tc) 147{ 148 uint64_t retval = 0; // return value, default 0 149 150 switch (idx) { 151 case IPR_PALtemp0: 152 case IPR_PALtemp1: 153 case IPR_PALtemp2: 154 case IPR_PALtemp3: 155 case IPR_PALtemp4: 156 case IPR_PALtemp5: 157 case IPR_PALtemp6: 158 case IPR_PALtemp7: 159 case IPR_PALtemp8: 160 case IPR_PALtemp9: 161 case IPR_PALtemp10: 162 case IPR_PALtemp11: 163 case IPR_PALtemp12: 164 case IPR_PALtemp13: 165 case IPR_PALtemp14: 166 case IPR_PALtemp15: 167 case IPR_PALtemp16: 168 case IPR_PALtemp17: 169 case IPR_PALtemp18: 170 case IPR_PALtemp19: 171 case IPR_PALtemp20: 172 case IPR_PALtemp21: 173 case IPR_PALtemp22: 174 case IPR_PALtemp23: 175 case IPR_PAL_BASE: 176 177 case IPR_IVPTBR: 178 case IPR_DC_MODE: 179 case IPR_MAF_MODE: 180 case IPR_ISR: 181 case IPR_EXC_ADDR: 182 case IPR_IC_PERR_STAT: 183 case IPR_DC_PERR_STAT: 184 case IPR_MCSR: 185 case IPR_ASTRR: 186 case IPR_ASTER: 187 case IPR_SIRR: 188 case IPR_ICSR: 189 case IPR_ICM: 190 case IPR_DTB_CM: 191 case IPR_IPLR: 192 case IPR_INTID: 193 case IPR_PMCTR: 194 // no side-effect 195 retval = ipr[idx]; 196 break; 197 198 case IPR_CC: 199 retval |= ipr[idx] & ULL(0xffffffff00000000); 200 retval |= tc->getCpuPtr()->curCycle() & ULL(0x00000000ffffffff); 201 break; 202 203 case IPR_VA: 204 retval = ipr[idx]; 205 break; 206 207 case IPR_VA_FORM: 208 case IPR_MM_STAT: 209 case IPR_IFAULT_VA_FORM: 210 case IPR_EXC_MASK: 211 case IPR_EXC_SUM: 212 retval = ipr[idx]; 213 break; 214 215 case IPR_DTB_PTE: 216 { 217 TlbEntry &entry 218 = tc->getDTBPtr()->index(!tc->misspeculating()); 219 220 retval |= ((uint64_t)entry.ppn & ULL(0x7ffffff)) << 32; 221 retval |= ((uint64_t)entry.xre & ULL(0xf)) << 8; 222 retval |= ((uint64_t)entry.xwe & ULL(0xf)) << 12; 223 retval |= ((uint64_t)entry.fonr & ULL(0x1)) << 1; 224 retval |= ((uint64_t)entry.fonw & ULL(0x1))<< 2; 225 retval |= ((uint64_t)entry.asma & ULL(0x1)) << 4; 226 retval |= ((uint64_t)entry.asn & ULL(0x7f)) << 57; 227 } 228 break; 229 230 // write only registers 231 case IPR_HWINT_CLR: 232 case IPR_SL_XMIT: 233 case IPR_DC_FLUSH: 234 case IPR_IC_FLUSH: 235 case IPR_ALT_MODE: 236 case IPR_DTB_IA: 237 case IPR_DTB_IAP: 238 case IPR_ITB_IA: 239 case IPR_ITB_IAP: 240 panic("Tried to read write only register %d\n", idx); 241 break; 242 243 default: 244 // invalid IPR 245 panic("Tried to read from invalid ipr %d\n", idx); 246 break; 247 } 248 249 return retval; 250} 251 252#ifdef DEBUG 253// Cause the simulator to break when changing to the following IPL 254int break_ipl = -1; 255#endif 256 257void 258ISA::setIpr(int idx, uint64_t val, ThreadContext *tc) 259{ 260 uint64_t old; 261 262 if (tc->misspeculating()) 263 return; 264 265 switch (idx) { 266 case IPR_PALtemp0: 267 case IPR_PALtemp1: 268 case IPR_PALtemp2: 269 case IPR_PALtemp3: 270 case IPR_PALtemp4: 271 case IPR_PALtemp5: 272 case IPR_PALtemp6: 273 case IPR_PALtemp7: 274 case IPR_PALtemp8: 275 case IPR_PALtemp9: 276 case IPR_PALtemp10: 277 case IPR_PALtemp11: 278 case IPR_PALtemp12: 279 case IPR_PALtemp13: 280 case IPR_PALtemp14: 281 case IPR_PALtemp15: 282 case IPR_PALtemp16: 283 case IPR_PALtemp17: 284 case IPR_PALtemp18: 285 case IPR_PALtemp19: 286 case IPR_PALtemp20: 287 case IPR_PALtemp21: 288 case IPR_PALtemp22: 289 case IPR_PAL_BASE: 290 case IPR_IC_PERR_STAT: 291 case IPR_DC_PERR_STAT: 292 case IPR_PMCTR: 293 // write entire quad w/ no side-effect 294 ipr[idx] = val; 295 break; 296 297 case IPR_CC_CTL: 298 // This IPR resets the cycle counter. We assume this only 299 // happens once... let's verify that. 300 assert(ipr[idx] == 0); 301 ipr[idx] = 1; 302 break; 303 304 case IPR_CC: 305 // This IPR only writes the upper 64 bits. It's ok to write 306 // all 64 here since we mask out the lower 32 in rpcc (see 307 // isa_desc). 308 ipr[idx] = val; 309 break; 310 311 case IPR_PALtemp23: 312 // write entire quad w/ no side-effect 313 old = ipr[idx]; 314 ipr[idx] = val; 315#if FULL_SYSTEM 316 if (tc->getKernelStats()) 317 tc->getKernelStats()->context(old, val, tc); 318#endif 319 break; 320 321 case IPR_DTB_PTE: 322 // write entire quad w/ no side-effect, tag is forthcoming 323 ipr[idx] = val; 324 break; 325 326 case IPR_EXC_ADDR: 327 // second least significant bit in PC is always zero 328 ipr[idx] = val & ~2; 329 break; 330 331 case IPR_ASTRR: 332 case IPR_ASTER: 333 // only write least significant four bits - privilege mask 334 ipr[idx] = val & 0xf; 335 break; 336 337 case IPR_IPLR: 338#ifdef DEBUG 339 if (break_ipl != -1 && break_ipl == (int)(val & 0x1f)) 340 debug_break(); 341#endif 342 343 // only write least significant five bits - interrupt level 344 ipr[idx] = val & 0x1f; 345#if FULL_SYSTEM 346 if (tc->getKernelStats()) 347 tc->getKernelStats()->swpipl(ipr[idx]); 348#endif 349 break; 350 351 case IPR_DTB_CM: 352#if FULL_SYSTEM 353 if (val & 0x18) { 354 if (tc->getKernelStats()) 355 tc->getKernelStats()->mode(Kernel::user, tc); 356 } else { 357 if (tc->getKernelStats()) 358 tc->getKernelStats()->mode(Kernel::kernel, tc); 359 } 360#endif 361 362 case IPR_ICM: 363 // only write two mode bits - processor mode 364 ipr[idx] = val & 0x18; 365 break; 366 367 case IPR_ALT_MODE: 368 // only write two mode bits - processor mode 369 ipr[idx] = val & 0x18; 370 break; 371 372 case IPR_MCSR: 373 // more here after optimization... 374 ipr[idx] = val; 375 break; 376 377 case IPR_SIRR: 378 // only write software interrupt mask 379 ipr[idx] = val & 0x7fff0; 380 break; 381 382 case IPR_ICSR: 383 ipr[idx] = val & ULL(0xffffff0300); 384 break; 385 386 case IPR_IVPTBR: 387 case IPR_MVPTBR: 388 ipr[idx] = val & ULL(0xffffffffc0000000); 389 break; 390 391 case IPR_DC_TEST_CTL: 392 ipr[idx] = val & 0x1ffb; 393 break; 394 395 case IPR_DC_MODE: 396 case IPR_MAF_MODE: 397 ipr[idx] = val & 0x3f; 398 break; 399 400 case IPR_ITB_ASN: 401 ipr[idx] = val & 0x7f0; 402 break; 403 404 case IPR_DTB_ASN: 405 ipr[idx] = val & ULL(0xfe00000000000000); 406 break; 407 408 case IPR_EXC_SUM: 409 case IPR_EXC_MASK: 410 // any write to this register clears it 411 ipr[idx] = 0; 412 break; 413 414 case IPR_INTID: 415 case IPR_SL_RCV: 416 case IPR_MM_STAT: 417 case IPR_ITB_PTE_TEMP: 418 case IPR_DTB_PTE_TEMP: 419 // read-only registers 420 panic("Tried to write read only ipr %d\n", idx); 421 422 case IPR_HWINT_CLR: 423 case IPR_SL_XMIT: 424 case IPR_DC_FLUSH: 425 case IPR_IC_FLUSH: 426 // the following are write only 427 ipr[idx] = val; 428 break; 429 430 case IPR_DTB_IA: 431 // really a control write 432 ipr[idx] = 0; 433 434 tc->getDTBPtr()->flushAll(); 435 break; 436 437 case IPR_DTB_IAP: 438 // really a control write 439 ipr[idx] = 0; 440 441 tc->getDTBPtr()->flushProcesses(); 442 break; 443 444 case IPR_DTB_IS: 445 // really a control write 446 ipr[idx] = val; 447 448 tc->getDTBPtr()->flushAddr(val, DTB_ASN_ASN(ipr[IPR_DTB_ASN])); 449 break; 450 451 case IPR_DTB_TAG: { 452 struct TlbEntry entry; 453 454 // FIXME: granularity hints NYI... 455 if (DTB_PTE_GH(ipr[IPR_DTB_PTE]) != 0) 456 panic("PTE GH field != 0"); 457 458 // write entire quad 459 ipr[idx] = val; 460 461 // construct PTE for new entry 462 entry.ppn = DTB_PTE_PPN(ipr[IPR_DTB_PTE]); 463 entry.xre = DTB_PTE_XRE(ipr[IPR_DTB_PTE]); 464 entry.xwe = DTB_PTE_XWE(ipr[IPR_DTB_PTE]); 465 entry.fonr = DTB_PTE_FONR(ipr[IPR_DTB_PTE]); 466 entry.fonw = DTB_PTE_FONW(ipr[IPR_DTB_PTE]); 467 entry.asma = DTB_PTE_ASMA(ipr[IPR_DTB_PTE]); 468 entry.asn = DTB_ASN_ASN(ipr[IPR_DTB_ASN]); 469 470 // insert new TAG/PTE value into data TLB 471 tc->getDTBPtr()->insert(val, entry); 472 } 473 break; 474 475 case IPR_ITB_PTE: { 476 struct TlbEntry entry; 477 478 // FIXME: granularity hints NYI... 479 if (ITB_PTE_GH(val) != 0) 480 panic("PTE GH field != 0"); 481 482 // write entire quad 483 ipr[idx] = val; 484 485 // construct PTE for new entry 486 entry.ppn = ITB_PTE_PPN(val); 487 entry.xre = ITB_PTE_XRE(val); 488 entry.xwe = 0; 489 entry.fonr = ITB_PTE_FONR(val); 490 entry.fonw = ITB_PTE_FONW(val); 491 entry.asma = ITB_PTE_ASMA(val); 492 entry.asn = ITB_ASN_ASN(ipr[IPR_ITB_ASN]); 493 494 // insert new TAG/PTE value into data TLB 495 tc->getITBPtr()->insert(ipr[IPR_ITB_TAG], entry); 496 } 497 break; 498 499 case IPR_ITB_IA: 500 // really a control write 501 ipr[idx] = 0; 502 503 tc->getITBPtr()->flushAll(); 504 break; 505 506 case IPR_ITB_IAP: 507 // really a control write 508 ipr[idx] = 0; 509 510 tc->getITBPtr()->flushProcesses(); 511 break; 512 513 case IPR_ITB_IS: 514 // really a control write 515 ipr[idx] = val; 516 517 tc->getITBPtr()->flushAddr(val, ITB_ASN_ASN(ipr[IPR_ITB_ASN])); 518 break; 519 520 default: 521 // invalid IPR 522 panic("Tried to write to invalid ipr %d\n", idx); 523 } 524 525 // no error... 526} 527 528void 529copyIprs(ThreadContext *src, ThreadContext *dest) 530{ 531 for (int i = 0; i < NumInternalProcRegs; ++i) 532 dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i)); 533} 534 535} // namespace AlphaISA 536 537#if FULL_SYSTEM 538 539using namespace AlphaISA; 540 541Fault 542SimpleThread::hwrei() 543{ 544 if (!(readPC() & 0x3)) 545 return new UnimplementedOpcodeFault; 546 547 setNextPC(readMiscRegNoEffect(IPR_EXC_ADDR)); 548 549 CPA::cpa()->swAutoBegin(tc, readNextPC()); 550 551 if (!misspeculating()) { 552 if (kernelStats) 553 kernelStats->hwrei(); 554 } 555 556 // FIXME: XXX check for interrupts? XXX 557 return NoFault; 558} 559 560/** 561 * Check for special simulator handling of specific PAL calls. 562 * If return value is false, actual PAL call will be suppressed. 563 */ 564bool 565SimpleThread::simPalCheck(int palFunc) 566{ 567 if (kernelStats) 568 kernelStats->callpal(palFunc, tc); 569 570 switch (palFunc) { 571 case PAL::halt: 572 halt(); 573 if (--System::numSystemsRunning == 0) 574 exitSimLoop("all cpus halted"); 575 break; 576 577 case PAL::bpt: 578 case PAL::bugchk: 579 if (system->breakpoint()) 580 return false; 581 break; 582 } 583 584 return true; 585} 586 587#endif // FULL_SYSTEM 588