tlb.cc (7734:85a8198aa2ff) | tlb.cc (7749:859e8bc1cdc2) |
---|---|
1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 55 unchanged lines hidden (view full) --- 64using namespace std; 65using namespace ArmISA; 66 67TLB::TLB(const Params *p) 68 : BaseTLB(p), size(p->size) 69#if FULL_SYSTEM 70 , tableWalker(p->walker) 71#endif | 1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 55 unchanged lines hidden (view full) --- 64using namespace std; 65using namespace ArmISA; 66 67TLB::TLB(const Params *p) 68 : BaseTLB(p), size(p->size) 69#if FULL_SYSTEM 70 , tableWalker(p->walker) 71#endif |
72 , rangeMRU(1) | 72 , rangeMRU(1), miscRegValid(false) |
73{ 74 table = new TlbEntry[size]; 75 memset(table, 0, sizeof(TlbEntry[size])); 76 77#if FULL_SYSTEM 78 tableWalker->setTlb(this); 79#endif 80} 81 82TLB::~TLB() 83{ 84 if (table) 85 delete [] table; 86} 87 88bool 89TLB::translateFunctional(ThreadContext *tc, Addr va, Addr &pa) 90{ | 73{ 74 table = new TlbEntry[size]; 75 memset(table, 0, sizeof(TlbEntry[size])); 76 77#if FULL_SYSTEM 78 tableWalker->setTlb(this); 79#endif 80} 81 82TLB::~TLB() 83{ 84 if (table) 85 delete [] table; 86} 87 88bool 89TLB::translateFunctional(ThreadContext *tc, Addr va, Addr &pa) 90{ |
91 uint32_t context_id = tc->readMiscReg(MISCREG_CONTEXTIDR); 92 TlbEntry *e = lookup(va, context_id, true); | 91 if (!miscRegValid) 92 updateMiscReg(tc); 93 TlbEntry *e = lookup(va, contextId, true); |
93 if (!e) 94 return false; 95 pa = e->pAddr(va); 96 return true; 97} 98 99TlbEntry* 100TLB::lookup(Addr va, uint8_t cid, bool functional) --- 169 unchanged lines hidden (view full) --- 270TLB::unserialize(Checkpoint *cp, const string §ion) 271{ 272 DPRINTF(Checkpoint, "Unserializing Arm TLB\n"); 273 274 UNSERIALIZE_SCALAR(_attr); 275 for(int i = 0; i < size; i++){ 276 table[i].unserialize(cp, csprintf("%s.TlbEntry%d", section, i)); 277 } | 94 if (!e) 95 return false; 96 pa = e->pAddr(va); 97 return true; 98} 99 100TlbEntry* 101TLB::lookup(Addr va, uint8_t cid, bool functional) --- 169 unchanged lines hidden (view full) --- 271TLB::unserialize(Checkpoint *cp, const string §ion) 272{ 273 DPRINTF(Checkpoint, "Unserializing Arm TLB\n"); 274 275 UNSERIALIZE_SCALAR(_attr); 276 for(int i = 0; i < size; i++){ 277 table[i].unserialize(cp, csprintf("%s.TlbEntry%d", section, i)); 278 } |
279 miscRegValid = false; |
|
278} 279 280void 281TLB::regStats() 282{ 283 instHits 284 .name(name() + ".inst_hits") 285 .desc("ITB inst hits") --- 107 unchanged lines hidden (view full) --- 393 accesses = readAccesses + writeAccesses + instAccesses; 394} 395 396#if !FULL_SYSTEM 397Fault 398TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode, 399 Translation *translation, bool &delay, bool timing) 400{ | 280} 281 282void 283TLB::regStats() 284{ 285 instHits 286 .name(name() + ".inst_hits") 287 .desc("ITB inst hits") --- 107 unchanged lines hidden (view full) --- 395 accesses = readAccesses + writeAccesses + instAccesses; 396} 397 398#if !FULL_SYSTEM 399Fault 400TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode, 401 Translation *translation, bool &delay, bool timing) 402{ |
401 // XXX Cache misc registers and have miscreg write function inv cache | 403 if (!miscRegValid) 404 updateMiscReg(tc); |
402 Addr vaddr = req->getVaddr(); | 405 Addr vaddr = req->getVaddr(); |
403 SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); | |
404 uint32_t flags = req->getFlags(); 405 406 bool is_fetch = (mode == Execute); 407 bool is_write = (mode == Write); 408 409 if (!is_fetch) { 410 assert(flags & MustBeOne); 411 if (sctlr.a || !(flags & AllowUnaligned)) { --- 27 unchanged lines hidden (view full) --- 439{ 440 return NoFault; 441} 442 443Fault 444TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode, 445 Translation *translation, bool &delay, bool timing) 446{ | 406 uint32_t flags = req->getFlags(); 407 408 bool is_fetch = (mode == Execute); 409 bool is_write = (mode == Write); 410 411 if (!is_fetch) { 412 assert(flags & MustBeOne); 413 if (sctlr.a || !(flags & AllowUnaligned)) { --- 27 unchanged lines hidden (view full) --- 441{ 442 return NoFault; 443} 444 445Fault 446TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode, 447 Translation *translation, bool &delay, bool timing) 448{ |
447 // XXX Cache misc registers and have miscreg write function inv cache | 449 if (!miscRegValid) 450 updateMiscReg(tc); 451 |
448 Addr vaddr = req->getVaddr(); | 452 Addr vaddr = req->getVaddr(); |
449 SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); 450 CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); | |
451 uint32_t flags = req->getFlags(); 452 453 bool is_fetch = (mode == Execute); 454 bool is_write = (mode == Write); | 453 uint32_t flags = req->getFlags(); 454 455 bool is_fetch = (mode == Execute); 456 bool is_write = (mode == Write); |
455 bool is_priv = (cpsr.mode != MODE_USER) && !(flags & UserMode); | 457 bool is_priv = isPriv && !(flags & UserMode); |
456 | 458 |
457 DPRINTF(TLBVerbose, "CPSR is user:%d UserMode:%d\n", cpsr.mode == MODE_USER, flags 458 & UserMode); | 459 DPRINTF(TLBVerbose, "CPSR is user:%d UserMode:%d\n", 460 isPriv, flags & UserMode); |
459 // If this is a clrex instruction, provide a PA of 0 with no fault 460 // This will force the monitor to set the tracked address to 0 461 // a bit of a hack but this effectively clrears this processors monitor 462 if (flags & Request::CLEAR_LL){ 463 req->setPaddr(0); 464 req->setFlags(Request::UNCACHEABLE); 465 req->setFlags(Request::CLEAR_LL); 466 return NoFault; --- 7 unchanged lines hidden (view full) --- 474 if (sctlr.a || !(flags & AllowUnaligned)) { 475 if (vaddr & flags & AlignmentMask) { 476 alignFaults++; 477 return new DataAbort(vaddr, 0, is_write, ArmFault::AlignmentFault); 478 } 479 } 480 } 481 | 461 // If this is a clrex instruction, provide a PA of 0 with no fault 462 // This will force the monitor to set the tracked address to 0 463 // a bit of a hack but this effectively clrears this processors monitor 464 if (flags & Request::CLEAR_LL){ 465 req->setPaddr(0); 466 req->setFlags(Request::UNCACHEABLE); 467 req->setFlags(Request::CLEAR_LL); 468 return NoFault; --- 7 unchanged lines hidden (view full) --- 476 if (sctlr.a || !(flags & AllowUnaligned)) { 477 if (vaddr & flags & AlignmentMask) { 478 alignFaults++; 479 return new DataAbort(vaddr, 0, is_write, ArmFault::AlignmentFault); 480 } 481 } 482 } 483 |
482 uint32_t context_id = tc->readMiscReg(MISCREG_CONTEXTIDR); | |
483 Fault fault; 484 | 484 Fault fault; 485 |
485 | |
486 if (!sctlr.m) { 487 req->setPaddr(vaddr); 488 if (sctlr.tre == 0) { 489 req->setFlags(Request::UNCACHEABLE); 490 } else { | 486 if (!sctlr.m) { 487 req->setPaddr(vaddr); 488 if (sctlr.tre == 0) { 489 req->setFlags(Request::UNCACHEABLE); 490 } else { |
491 PRRR prrr = tc->readMiscReg(MISCREG_PRRR); 492 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR); 493 | |
494 if (nmrr.ir0 == 0 || nmrr.or0 == 0 || prrr.tr0 != 0x2) 495 req->setFlags(Request::UNCACHEABLE); 496 } 497 498 // Set memory attributes 499 TlbEntry temp_te; 500 tableWalker->memAttrs(tc, temp_te, sctlr, 0, 1); 501 temp_te.shareable = true; 502 DPRINTF(TLBVerbose, "(No MMU) setting memory attributes: shareable:\ 503 %d, innerAttrs: %d, outerAttrs: %d\n", temp_te.shareable, 504 temp_te.innerAttrs, temp_te.outerAttrs); 505 setAttr(temp_te.attributes); 506 507 return trickBoxCheck(req, mode, 0, false); 508 } 509 | 491 if (nmrr.ir0 == 0 || nmrr.or0 == 0 || prrr.tr0 != 0x2) 492 req->setFlags(Request::UNCACHEABLE); 493 } 494 495 // Set memory attributes 496 TlbEntry temp_te; 497 tableWalker->memAttrs(tc, temp_te, sctlr, 0, 1); 498 temp_te.shareable = true; 499 DPRINTF(TLBVerbose, "(No MMU) setting memory attributes: shareable:\ 500 %d, innerAttrs: %d, outerAttrs: %d\n", temp_te.shareable, 501 temp_te.innerAttrs, temp_te.outerAttrs); 502 setAttr(temp_te.attributes); 503 504 return trickBoxCheck(req, mode, 0, false); 505 } 506 |
510 DPRINTF(TLBVerbose, "Translating vaddr=%#x context=%d\n", vaddr, context_id); | 507 DPRINTF(TLBVerbose, "Translating vaddr=%#x context=%d\n", vaddr, contextId); |
511 // Translation enabled 512 | 508 // Translation enabled 509 |
513 TlbEntry *te = lookup(vaddr, context_id); | 510 TlbEntry *te = lookup(vaddr, contextId); |
514 if (te == NULL) { 515 if (req->isPrefetch()){ 516 //if the request is a prefetch don't attempt to fill the TLB 517 //or go any further with the memory access 518 prefetchFaults++; 519 return new PrefetchAbort(vaddr, ArmFault::PrefetchTLBMiss); 520 } 521 522 if (is_fetch) 523 instMisses++; 524 else if (is_write) 525 writeMisses++; 526 else 527 readMisses++; 528 529 // start translation table walk, pass variables rather than 530 // re-retreaving in table walker for speed 531 DPRINTF(TLB, "TLB Miss: Starting hardware table walker for %#x(%d)\n", | 511 if (te == NULL) { 512 if (req->isPrefetch()){ 513 //if the request is a prefetch don't attempt to fill the TLB 514 //or go any further with the memory access 515 prefetchFaults++; 516 return new PrefetchAbort(vaddr, ArmFault::PrefetchTLBMiss); 517 } 518 519 if (is_fetch) 520 instMisses++; 521 else if (is_write) 522 writeMisses++; 523 else 524 readMisses++; 525 526 // start translation table walk, pass variables rather than 527 // re-retreaving in table walker for speed 528 DPRINTF(TLB, "TLB Miss: Starting hardware table walker for %#x(%d)\n", |
532 vaddr, context_id); 533 fault = tableWalker->walk(req, tc, context_id, mode, translation, | 529 vaddr, contextId); 530 fault = tableWalker->walk(req, tc, contextId, mode, translation, |
534 timing); 535 if (timing) { 536 delay = true; 537 // for timing mode, return and wait for table walk 538 return fault; 539 } 540 if (fault) 541 return fault; 542 | 531 timing); 532 if (timing) { 533 delay = true; 534 // for timing mode, return and wait for table walk 535 return fault; 536 } 537 if (fault) 538 return fault; 539 |
543 te = lookup(vaddr, context_id); | 540 te = lookup(vaddr, contextId); |
544 if (!te) 545 printTlb(); 546 assert(te); 547 } else { 548 if (is_fetch) 549 instHits++; 550 else if (is_write) 551 writeHits++; --- 4 unchanged lines hidden (view full) --- 556 // Set memory attributes 557 DPRINTF(TLBVerbose, 558 "Setting memory attributes: shareable: %d, innerAttrs: %d, \ 559 outerAttrs: %d\n", 560 te->shareable, te->innerAttrs, te->outerAttrs); 561 setAttr(te->attributes); 562 if (te->nonCacheable) 563 req->setFlags(Request::UNCACHEABLE); | 541 if (!te) 542 printTlb(); 543 assert(te); 544 } else { 545 if (is_fetch) 546 instHits++; 547 else if (is_write) 548 writeHits++; --- 4 unchanged lines hidden (view full) --- 553 // Set memory attributes 554 DPRINTF(TLBVerbose, 555 "Setting memory attributes: shareable: %d, innerAttrs: %d, \ 556 outerAttrs: %d\n", 557 te->shareable, te->innerAttrs, te->outerAttrs); 558 setAttr(te->attributes); 559 if (te->nonCacheable) 560 req->setFlags(Request::UNCACHEABLE); |
564 uint32_t dacr = tc->readMiscReg(MISCREG_DACR); | 561 |
565 switch ( (dacr >> (te->domain * 2)) & 0x3) { 566 case 0: 567 domainFaults++; 568 DPRINTF(TLB, "TLB Fault: Data abort on domain. DACR: %#x domain: %#x" 569 " write:%d sNp:%d\n", dacr, te->domain, is_write, te->sNp); 570 if (is_fetch) 571 return new PrefetchAbort(vaddr, 572 (te->sNp ? ArmFault::Domain0 : ArmFault::Domain1)); --- 131 unchanged lines hidden --- | 562 switch ( (dacr >> (te->domain * 2)) & 0x3) { 563 case 0: 564 domainFaults++; 565 DPRINTF(TLB, "TLB Fault: Data abort on domain. DACR: %#x domain: %#x" 566 " write:%d sNp:%d\n", dacr, te->domain, is_write, te->sNp); 567 if (is_fetch) 568 return new PrefetchAbort(vaddr, 569 (te->sNp ? ArmFault::Domain0 : ArmFault::Domain1)); --- 131 unchanged lines hidden --- |