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 &section)
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 &section)
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 ---