tlb.cc revision 3825
1/* 2 * Copyright (c) 2001-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: Ali Saidi 29 */ 30 31#include "arch/sparc/asi.hh" 32#include "arch/sparc/miscregfile.hh" 33#include "arch/sparc/tlb.hh" 34#include "base/bitfield.hh" 35#include "base/trace.hh" 36#include "cpu/thread_context.hh" 37#include "cpu/base.hh" 38#include "mem/packet_access.hh" 39#include "mem/request.hh" 40#include "sim/builder.hh" 41 42/* @todo remove some of the magic constants. -- ali 43 * */ 44namespace SparcISA 45{ 46 47TLB::TLB(const std::string &name, int s) 48 : SimObject(name), size(s) 49{ 50 // To make this work you'll have to change the hypervisor and OS 51 if (size > 64) 52 fatal("SPARC T1 TLB registers don't support more than 64 TLB entries."); 53 54 tlb = new TlbEntry[size]; 55 memset(tlb, 0, sizeof(TlbEntry) * size); 56} 57 58void 59TLB::clearUsedBits() 60{ 61 MapIter i; 62 for (i = lookupTable.begin(); i != lookupTable.end();) { 63 TlbEntry *t = i->second; 64 if (!t->pte.locked()) { 65 t->used = false; 66 usedEntries--; 67 } 68 } 69} 70 71 72void 73TLB::insert(Addr va, int partition_id, int context_id, bool real, 74 const PageTableEntry& PTE) 75{ 76 77 78 MapIter i; 79 TlbEntry *new_entry; 80 81 DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x, pid=%d cid=%d r=%d\n", 82 va, partition_id, context_id, (int)real); 83 84 int x = -1; 85 for (x = 0; x < size; x++) { 86 if (!tlb[x].valid || !tlb[x].used) { 87 new_entry = &tlb[x]; 88 break; 89 } 90 } 91 92 // Update the last ently if their all locked 93 if (x == -1) 94 x = size - 1; 95 96 assert(PTE.valid()); 97 new_entry->range.va = va; 98 new_entry->range.size = PTE.size(); 99 new_entry->range.partitionId = partition_id; 100 new_entry->range.contextId = context_id; 101 new_entry->range.real = real; 102 new_entry->pte = PTE; 103 new_entry->used = true;; 104 new_entry->valid = true; 105 usedEntries++; 106 107 108 // Demap any entry that conflicts 109 i = lookupTable.find(new_entry->range); 110 if (i != lookupTable.end()) { 111 i->second->valid = false; 112 if (i->second->used) { 113 i->second->used = false; 114 usedEntries--; 115 } 116 DPRINTF(TLB, "TLB: Found conflicting entry, deleting it\n"); 117 lookupTable.erase(i); 118 } 119 120 lookupTable.insert(new_entry->range, new_entry);; 121 122 // If all entries have there used bit set, clear it on them all, but the 123 // one we just inserted 124 if (usedEntries == size) { 125 clearUsedBits(); 126 new_entry->used = true; 127 usedEntries++; 128 } 129 130} 131 132 133TlbEntry* 134TLB::lookup(Addr va, int partition_id, bool real, int context_id) 135{ 136 MapIter i; 137 TlbRange tr; 138 TlbEntry *t; 139 140 DPRINTF(TLB, "TLB: Looking up entry va=%#x pid=%d cid=%d r=%d\n", 141 va, partition_id, context_id, real); 142 // Assemble full address structure 143 tr.va = va; 144 tr.size = va + MachineBytes; 145 tr.contextId = context_id; 146 tr.partitionId = partition_id; 147 tr.real = real; 148 149 // Try to find the entry 150 i = lookupTable.find(tr); 151 if (i == lookupTable.end()) { 152 DPRINTF(TLB, "TLB: No valid entry found\n"); 153 return NULL; 154 } 155 DPRINTF(TLB, "TLB: Valid entry found\n"); 156 157 // Mark the entries used bit and clear other used bits in needed 158 t = i->second; 159 if (!t->used) { 160 t->used = true; 161 usedEntries++; 162 if (usedEntries == size) { 163 clearUsedBits(); 164 t->used = true; 165 usedEntries++; 166 } 167 } 168 169 return t; 170} 171 172 173void 174TLB::demapPage(Addr va, int partition_id, bool real, int context_id) 175{ 176 TlbRange tr; 177 MapIter i; 178 179 // Assemble full address structure 180 tr.va = va; 181 tr.size = va + MachineBytes; 182 tr.contextId = context_id; 183 tr.partitionId = partition_id; 184 tr.real = real; 185 186 // Demap any entry that conflicts 187 i = lookupTable.find(tr); 188 if (i != lookupTable.end()) { 189 i->second->valid = false; 190 if (i->second->used) { 191 i->second->used = false; 192 usedEntries--; 193 } 194 lookupTable.erase(i); 195 } 196} 197 198void 199TLB::demapContext(int partition_id, int context_id) 200{ 201 int x; 202 for (x = 0; x < size; x++) { 203 if (tlb[x].range.contextId == context_id && 204 tlb[x].range.partitionId == partition_id) { 205 tlb[x].valid = false; 206 if (tlb[x].used) { 207 tlb[x].used = false; 208 usedEntries--; 209 } 210 lookupTable.erase(tlb[x].range); 211 } 212 } 213} 214 215void 216TLB::demapAll(int partition_id) 217{ 218 int x; 219 for (x = 0; x < size; x++) { 220 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { 221 tlb[x].valid = false; 222 if (tlb[x].used) { 223 tlb[x].used = false; 224 usedEntries--; 225 } 226 lookupTable.erase(tlb[x].range); 227 } 228 } 229} 230 231void 232TLB::invalidateAll() 233{ 234 int x; 235 for (x = 0; x < size; x++) { 236 tlb[x].valid = false; 237 } 238 usedEntries = 0; 239} 240 241uint64_t 242TLB::TteRead(int entry) { 243 assert(entry < size); 244 return tlb[entry].pte(); 245} 246 247uint64_t 248TLB::TagRead(int entry) { 249 assert(entry < size); 250 uint64_t tag; 251 252 tag = tlb[entry].range.contextId | tlb[entry].range.va | 253 (uint64_t)tlb[entry].range.partitionId << 61; 254 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; 255 tag |= (uint64_t)~tlb[entry].pte._size() << 56; 256 return tag; 257} 258 259bool 260TLB::validVirtualAddress(Addr va, bool am) 261{ 262 if (am) 263 return true; 264 if (va >= StartVAddrHole && va <= EndVAddrHole) 265 return false; 266 return true; 267} 268 269void 270TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, 271 bool se, FaultTypes ft, int asi) 272{ 273 uint64_t sfsr; 274 sfsr = tc->readMiscReg(reg); 275 276 if (sfsr & 0x1) 277 sfsr = 0x3; 278 else 279 sfsr = 1; 280 281 if (write) 282 sfsr |= 1 << 2; 283 sfsr |= ct << 4; 284 if (se) 285 sfsr |= 1 << 6; 286 sfsr |= ft << 7; 287 sfsr |= asi << 16; 288 tc->setMiscReg(reg, sfsr); 289} 290 291 292void 293ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct, 294 bool se, FaultTypes ft, int asi) 295{ 296 DPRINTF(TLB, "TLB: ITB Fault: w=%d ct=%d ft=%d asi=%d\n", 297 (int)write, ct, ft, asi); 298 TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi); 299} 300 301void 302DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, 303 bool se, FaultTypes ft, int asi) 304{ 305 DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n", 306 a, (int)write, ct, ft, asi); 307 TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi); 308 tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a); 309} 310 311 312Fault 313ITB::translate(RequestPtr &req, ThreadContext *tc) 314{ 315 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE); 316 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE); 317 bool lsuIm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 2 & 0x1; 318 uint64_t tl = tc->readMiscReg(MISCREG_TL); 319 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); 320 bool addr_mask = pstate >> 3 & 0x1; 321 bool priv = pstate >> 2 & 0x1; 322 Addr vaddr = req->getVaddr(); 323 int context; 324 ContextType ct; 325 int asi; 326 bool real = false; 327 TlbEntry *e; 328 329 DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n", 330 vaddr, req->getSize()); 331 DPRINTF(TLB, "TLB: pstate: %#X hpstate: %#X lsudm: %#X part_id: %#X\n", 332 pstate, hpstate, lsuIm, part_id); 333 334 assert(req->getAsi() == ASI_IMPLICIT); 335 336 if (tl > 0) { 337 asi = ASI_N; 338 ct = Nucleus; 339 context = 0; 340 } else { 341 asi = ASI_P; 342 ct = Primary; 343 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 344 } 345 346 if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) { 347 req->setPaddr(req->getVaddr() & PAddrImplMask); 348 return NoFault; 349 } 350 351 // If the asi is unaligned trap 352 if (vaddr & 0x7) { 353 writeSfsr(tc, false, ct, false, OtherFault, asi); 354 return new MemAddressNotAligned; 355 } 356 357 if (addr_mask) 358 vaddr = vaddr & VAddrAMask; 359 360 if (!validVirtualAddress(vaddr, addr_mask)) { 361 writeSfsr(tc, false, ct, false, VaOutOfRange, asi); 362 return new InstructionAccessException; 363 } 364 365 if (!lsuIm) { 366 e = lookup(req->getVaddr(), part_id, true); 367 real = true; 368 context = 0; 369 } else { 370 e = lookup(vaddr, part_id, false, context); 371 } 372 373 if (e == NULL || !e->valid) { 374 tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, 375 vaddr & ~BytesInPageMask | context); 376 if (real) 377 return new InstructionRealTranslationMiss; 378 else 379 return new FastInstructionAccessMMUMiss; 380 } 381 382 // were not priviledged accesing priv page 383 if (!priv && e->pte.priv()) { 384 writeSfsr(tc, false, ct, false, PrivViolation, asi); 385 return new InstructionAccessException; 386 } 387 388 req->setPaddr(e->pte.paddr() & ~e->pte.size() | 389 req->getVaddr() & e->pte.size()); 390 return NoFault; 391} 392 393 394 395Fault 396DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) 397{ 398 /* @todo this could really use some profiling and fixing to make it faster! */ 399 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE); 400 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE); 401 bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1; 402 uint64_t tl = tc->readMiscReg(MISCREG_TL); 403 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); 404 bool hpriv = hpstate >> 2 & 0x1; 405 bool red = hpstate >> 5 >> 0x1; 406 bool addr_mask = pstate >> 3 & 0x1; 407 bool priv = pstate >> 2 & 0x1; 408 bool implicit = false; 409 bool real = false; 410 Addr vaddr = req->getVaddr(); 411 Addr size = req->getSize(); 412 ContextType ct; 413 int context; 414 ASI asi; 415 416 TlbEntry *e; 417 418 asi = (ASI)req->getAsi(); 419 DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n", 420 vaddr, size, asi); 421 DPRINTF(TLB, "TLB: pstate: %#X hpstate: %#X lsudm: %#X part_id: %#X\n", 422 pstate, hpstate, lsuDm, part_id); 423 if (asi == ASI_IMPLICIT) 424 implicit = true; 425 426 if (implicit) { 427 if (tl > 0) { 428 asi = ASI_N; 429 ct = Nucleus; 430 context = 0; 431 } else { 432 asi = ASI_P; 433 ct = Primary; 434 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 435 } 436 } else if (!hpriv && !red) { 437 if (tl > 0 || AsiIsNucleus(asi)) { 438 ct = Nucleus; 439 context = 0; 440 } else if (AsiIsSecondary(asi)) { 441 ct = Secondary; 442 context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT); 443 } else { 444 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); 445 ct = Primary; //??? 446 } 447 448 // We need to check for priv level/asi priv 449 if (!priv && !AsiIsUnPriv(asi)) { 450 // It appears that context should be Nucleus in these cases? 451 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 452 return new PrivilegedAction; 453 } 454 if (priv && AsiIsHPriv(asi)) { 455 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); 456 return new DataAccessException; 457 } 458 459 } 460 461 // If the asi is unaligned trap 462 if (vaddr & size-1) { 463 writeSfr(tc, vaddr, false, ct, false, OtherFault, asi); 464 return new MemAddressNotAligned; 465 } 466 467 if (addr_mask) 468 vaddr = vaddr & VAddrAMask; 469 470 if (!validVirtualAddress(vaddr, addr_mask)) { 471 writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi); 472 return new DataAccessException; 473 } 474 475 if (!implicit) { 476 if (AsiIsLittle(asi)) 477 panic("Little Endian ASIs not supported\n"); 478 if (AsiIsBlock(asi)) 479 panic("Block ASIs not supported\n"); 480 if (AsiIsNoFault(asi)) 481 panic("No Fault ASIs not supported\n"); 482 if (AsiIsTwin(asi)) 483 panic("Twin ASIs not supported\n"); 484 if (AsiIsPartialStore(asi)) 485 panic("Partial Store ASIs not supported\n"); 486 if (AsiIsInterrupt(asi)) 487 panic("Interrupt ASIs not supported\n"); 488 489 if (AsiIsMmu(asi)) 490 goto handleMmuRegAccess; 491 if (AsiIsScratchPad(asi)) 492 goto handleScratchRegAccess; 493 if (AsiIsQueue(asi)) 494 goto handleQueueRegAccess; 495 if (AsiIsSparcError(asi)) 496 goto handleSparcErrorRegAccess; 497 498 if (!AsiIsReal(asi) && !AsiIsNucleus(asi)) 499 panic("Accessing ASI %#X. Should we?\n", asi); 500 } 501 502 if ((!lsuDm && !hpriv) || AsiIsReal(asi)) { 503 real = true; 504 context = 0; 505 }; 506 507 if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) { 508 req->setPaddr(req->getVaddr() & PAddrImplMask); 509 return NoFault; 510 } 511 512 e = lookup(req->getVaddr(), part_id, real, context); 513 514 if (e == NULL || !e->valid) { 515 tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, 516 vaddr & ~BytesInPageMask | context); 517 DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n"); 518 if (real) 519 return new DataRealTranslationMiss; 520 else 521 return new FastDataAccessMMUMiss; 522 523 } 524 525 526 if (write && !e->pte.writable()) { 527 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi); 528 return new FastDataAccessProtection; 529 } 530 531 if (e->pte.nofault() && !AsiIsNoFault(asi)) { 532 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi); 533 return new DataAccessException; 534 } 535 536 if (e->pte.sideffect()) 537 req->setFlags(req->getFlags() | UNCACHEABLE); 538 539 540 if (!priv && e->pte.priv()) { 541 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi); 542 return new DataAccessException; 543 } 544 545 req->setPaddr(e->pte.paddr() & ~e->pte.size() | 546 req->getVaddr() & e->pte.size()); 547 return NoFault; 548 /** Normal flow ends here. */ 549 550handleScratchRegAccess: 551 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { 552 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 553 return new DataAccessException; 554 } 555 goto regAccessOk; 556 557handleQueueRegAccess: 558 if (!priv && !hpriv) { 559 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 560 return new PrivilegedAction; 561 } 562 if (priv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) { 563 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 564 return new DataAccessException; 565 } 566 goto regAccessOk; 567 568handleSparcErrorRegAccess: 569 if (!hpriv) { 570 if (priv) { 571 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 572 return new DataAccessException; 573 } else { 574 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 575 return new PrivilegedAction; 576 } 577 } 578 goto regAccessOk; 579 580 581regAccessOk: 582handleMmuRegAccess: 583 DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n"); 584 req->setMmapedIpr(true); 585 req->setPaddr(req->getVaddr()); 586 return NoFault; 587}; 588 589Tick 590DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) 591{ 592 Addr va = pkt->getAddr(); 593 ASI asi = (ASI)pkt->req->getAsi(); 594 595 DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n", 596 (uint32_t)pkt->req->getAsi(), pkt->getAddr()); 597 598 switch (asi) { 599 case ASI_LSU_CONTROL_REG: 600 assert(va == 0); 601 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_LSU_CTRL)); 602 break; 603 case ASI_MMU: 604 switch (va) { 605 case 0x8: 606 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT)); 607 break; 608 case 0x10: 609 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT)); 610 break; 611 default: 612 goto doMmuReadError; 613 } 614 break; 615 case ASI_QUEUE: 616 pkt->set(tc->readMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + 617 (va >> 4) - 0x3c)); 618 break; 619 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: 620 assert(va == 0); 621 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0)); 622 break; 623 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: 624 assert(va == 0); 625 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1)); 626 break; 627 case ASI_DMMU_CTXT_ZERO_CONFIG: 628 assert(va == 0); 629 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG)); 630 break; 631 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: 632 assert(va == 0); 633 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0)); 634 break; 635 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: 636 assert(va == 0); 637 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1)); 638 break; 639 case ASI_IMMU_CTXT_ZERO_CONFIG: 640 assert(va == 0); 641 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG)); 642 break; 643 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: 644 assert(va == 0); 645 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0)); 646 break; 647 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: 648 assert(va == 0); 649 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1)); 650 break; 651 case ASI_DMMU_CTXT_NONZERO_CONFIG: 652 assert(va == 0); 653 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)); 654 break; 655 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: 656 assert(va == 0); 657 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0)); 658 break; 659 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: 660 assert(va == 0); 661 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1)); 662 break; 663 case ASI_IMMU_CTXT_NONZERO_CONFIG: 664 assert(va == 0); 665 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)); 666 break; 667 case ASI_HYP_SCRATCHPAD: 668 case ASI_SCRATCHPAD: 669 pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3))); 670 break; 671 case ASI_DMMU: 672 switch (va) { 673 case 0x80: 674 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID)); 675 break; 676 default: 677 goto doMmuReadError; 678 } 679 break; 680 default: 681doMmuReadError: 682 panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n", 683 (uint32_t)asi, va); 684 } 685 pkt->result = Packet::Success; 686 return tc->getCpuPtr()->cycles(1); 687} 688 689Tick 690DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) 691{ 692 uint64_t data = gtoh(pkt->get<uint64_t>()); 693 Addr va = pkt->getAddr(); 694 ASI asi = (ASI)pkt->req->getAsi(); 695 696 DPRINTF(IPR, "Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n", 697 (uint32_t)asi, va, data); 698 699 switch (asi) { 700 case ASI_LSU_CONTROL_REG: 701 assert(va == 0); 702 tc->setMiscRegWithEffect(MISCREG_MMU_LSU_CTRL, data); 703 break; 704 case ASI_MMU: 705 switch (va) { 706 case 0x8: 707 tc->setMiscRegWithEffect(MISCREG_MMU_P_CONTEXT, data); 708 break; 709 case 0x10: 710 tc->setMiscRegWithEffect(MISCREG_MMU_S_CONTEXT, data); 711 break; 712 default: 713 goto doMmuWriteError; 714 } 715 break; 716 case ASI_QUEUE: 717 assert(mbits(data,13,6) == data); 718 tc->setMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + 719 (va >> 4) - 0x3c, data); 720 break; 721 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: 722 assert(va == 0); 723 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, data); 724 break; 725 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: 726 assert(va == 0); 727 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, data); 728 break; 729 case ASI_DMMU_CTXT_ZERO_CONFIG: 730 assert(va == 0); 731 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG, data); 732 break; 733 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: 734 assert(va == 0); 735 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, data); 736 break; 737 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: 738 assert(va == 0); 739 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, data); 740 break; 741 case ASI_IMMU_CTXT_ZERO_CONFIG: 742 assert(va == 0); 743 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG, data); 744 break; 745 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: 746 assert(va == 0); 747 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, data); 748 break; 749 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: 750 assert(va == 0); 751 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, data); 752 break; 753 case ASI_DMMU_CTXT_NONZERO_CONFIG: 754 assert(va == 0); 755 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG, data); 756 break; 757 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: 758 assert(va == 0); 759 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, data); 760 break; 761 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: 762 assert(va == 0); 763 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, data); 764 break; 765 case ASI_IMMU_CTXT_NONZERO_CONFIG: 766 assert(va == 0); 767 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG, data); 768 break; 769 case ASI_SPARC_ERROR_EN_REG: 770 case ASI_SPARC_ERROR_STATUS_REG: 771 warn("Ignoring write to SPARC ERROR regsiter\n"); 772 break; 773 case ASI_HYP_SCRATCHPAD: 774 case ASI_SCRATCHPAD: 775 tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data); 776 break; 777 case ASI_DMMU: 778 switch (va) { 779 case 0x80: 780 tc->setMiscRegWithEffect(MISCREG_MMU_PART_ID, data); 781 break; 782 default: 783 goto doMmuWriteError; 784 } 785 break; 786 default: 787doMmuWriteError: 788 panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n", 789 (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data); 790 } 791 pkt->result = Packet::Success; 792 return tc->getCpuPtr()->cycles(1); 793} 794 795void 796TLB::serialize(std::ostream &os) 797{ 798 panic("Need to implement serialize tlb for SPARC\n"); 799} 800 801void 802TLB::unserialize(Checkpoint *cp, const std::string §ion) 803{ 804 panic("Need to implement unserialize tlb for SPARC\n"); 805} 806 807 808DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB) 809 810BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) 811 812 Param<int> size; 813 814END_DECLARE_SIM_OBJECT_PARAMS(ITB) 815 816BEGIN_INIT_SIM_OBJECT_PARAMS(ITB) 817 818 INIT_PARAM_DFLT(size, "TLB size", 48) 819 820END_INIT_SIM_OBJECT_PARAMS(ITB) 821 822 823CREATE_SIM_OBJECT(ITB) 824{ 825 return new ITB(getInstanceName(), size); 826} 827 828REGISTER_SIM_OBJECT("SparcITB", ITB) 829 830BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB) 831 832 Param<int> size; 833 834END_DECLARE_SIM_OBJECT_PARAMS(DTB) 835 836BEGIN_INIT_SIM_OBJECT_PARAMS(DTB) 837 838 INIT_PARAM_DFLT(size, "TLB size", 64) 839 840END_INIT_SIM_OBJECT_PARAMS(DTB) 841 842 843CREATE_SIM_OBJECT(DTB) 844{ 845 return new DTB(getInstanceName(), size); 846} 847 848REGISTER_SIM_OBJECT("SparcDTB", DTB) 849} 850