tlb.cc (3863:adf3ddd4bcde) | tlb.cc (3881:f06ef65cd746) |
---|---|
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; --- 31 unchanged lines hidden (view full) --- 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) | 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; --- 31 unchanged lines hidden (view full) --- 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), usedEntries(0), cacheValid(false) | 48 : SimObject(name), size(s), usedEntries(0), lastReplaced(0), 49 cacheValid(false) |
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); | 50{ 51 // To make this work you'll have to change the hypervisor and OS 52 if (size > 64) 53 fatal("SPARC T1 TLB registers don't support more than 64 TLB entries."); 54 55 tlb = new TlbEntry[size]; 56 memset(tlb, 0, sizeof(TlbEntry) * size); |
57 58 for (int x = 0; x < size; x++) 59 freeList.push_back(&tlb[x]); |
|
56} 57 58void 59TLB::clearUsedBits() 60{ 61 MapIter i; | 60} 61 62void 63TLB::clearUsedBits() 64{ 65 MapIter i; |
62 for (i = lookupTable.begin(); i != lookupTable.end();) { | 66 for (i = lookupTable.begin(); i != lookupTable.end(); i++) { |
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, int entry) 75{ 76 77 78 MapIter i; 79 TlbEntry *new_entry = NULL; | 67 TlbEntry *t = i->second; 68 if (!t->pte.locked()) { 69 t->used = false; 70 usedEntries--; 71 } 72 } 73} 74 75 76void 77TLB::insert(Addr va, int partition_id, int context_id, bool real, 78 const PageTableEntry& PTE, int entry) 79{ 80 81 82 MapIter i; 83 TlbEntry *new_entry = NULL; |
84 TlbRange tr; |
|
80 int x; 81 82 cacheValid = false; | 85 int x; 86 87 cacheValid = false; |
88 tr.va = va; 89 tr.size = PTE.size() - 1; 90 tr.contextId = context_id; 91 tr.partitionId = partition_id; 92 tr.real = real; |
|
83 | 93 |
84 DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d\n", 85 va, PTE.paddr(), partition_id, context_id, (int)real); | |
86 | 94 |
95 DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d entryid=%d\n", 96 va, PTE.paddr(), partition_id, context_id, (int)real, entry); 97 98 // Demap any entry that conflicts 99 i = lookupTable.find(tr); 100 if (i != lookupTable.end()) { 101 i->second->valid = false; 102 if (i->second->used) { 103 i->second->used = false; 104 usedEntries--; 105 } 106 freeList.push_front(i->second); 107 DPRINTF(TLB, "TLB: Found conflicting entry %#X , deleting it\n", 108 i->second); 109 lookupTable.erase(i); 110 } 111 112 |
|
87 if (entry != -1) { 88 assert(entry < size && entry >= 0); 89 new_entry = &tlb[entry]; 90 } else { | 113 if (entry != -1) { 114 assert(entry < size && entry >= 0); 115 new_entry = &tlb[entry]; 116 } else { |
117 if (!freeList.empty()) { 118 new_entry = freeList.front(); 119 } else { 120 x = lastReplaced; 121 do { 122 ++x; 123 if (x == size) 124 x = 0; 125 if (x == lastReplaced) 126 goto insertAllLocked; 127 } while (tlb[x].pte.locked()); 128 lastReplaced = x; 129 new_entry = &tlb[x]; 130 lookupTable.erase(new_entry->range); 131 } 132 /* |
|
91 for (x = 0; x < size; x++) { 92 if (!tlb[x].valid || !tlb[x].used) { 93 new_entry = &tlb[x]; 94 break; 95 } | 133 for (x = 0; x < size; x++) { 134 if (!tlb[x].valid || !tlb[x].used) { 135 new_entry = &tlb[x]; 136 break; 137 } |
96 } | 138 }*/ |
97 } 98 | 139 } 140 |
141insertAllLocked: |
|
99 // Update the last ently if their all locked | 142 // Update the last ently if their all locked |
100 if (!new_entry) | 143 if (!new_entry) { |
101 new_entry = &tlb[size-1]; | 144 new_entry = &tlb[size-1]; |
145 lookupTable.erase(new_entry->range); 146 } |
|
102 | 147 |
148 freeList.remove(new_entry); 149 DPRINTF(TLB, "Using entry: %#X\n", new_entry); 150 |
|
103 assert(PTE.valid()); 104 new_entry->range.va = va; | 151 assert(PTE.valid()); 152 new_entry->range.va = va; |
105 new_entry->range.size = PTE.size(); | 153 new_entry->range.size = PTE.size() - 1; |
106 new_entry->range.partitionId = partition_id; 107 new_entry->range.contextId = context_id; 108 new_entry->range.real = real; 109 new_entry->pte = PTE; 110 new_entry->used = true;; 111 new_entry->valid = true; 112 usedEntries++; 113 114 | 154 new_entry->range.partitionId = partition_id; 155 new_entry->range.contextId = context_id; 156 new_entry->range.real = real; 157 new_entry->pte = PTE; 158 new_entry->used = true;; 159 new_entry->valid = true; 160 usedEntries++; 161 162 |
115 // Demap any entry that conflicts 116 i = lookupTable.find(new_entry->range); 117 if (i != lookupTable.end()) { 118 i->second->valid = false; 119 if (i->second->used) { 120 i->second->used = false; 121 usedEntries--; 122 } 123 DPRINTF(TLB, "TLB: Found conflicting entry, deleting it\n"); 124 lookupTable.erase(i); 125 } | |
126 127 i = lookupTable.insert(new_entry->range, new_entry); 128 assert(i != lookupTable.end()); 129 130 // If all entries have there used bit set, clear it on them all, but the 131 // one we just inserted 132 if (usedEntries == size) { 133 clearUsedBits(); --- 80 unchanged lines hidden (view full) --- 214 i = lookupTable.find(tr); 215 if (i != lookupTable.end()) { 216 DPRINTF(IPR, "TLB: Demapped page\n"); 217 i->second->valid = false; 218 if (i->second->used) { 219 i->second->used = false; 220 usedEntries--; 221 } | 163 164 i = lookupTable.insert(new_entry->range, new_entry); 165 assert(i != lookupTable.end()); 166 167 // If all entries have there used bit set, clear it on them all, but the 168 // one we just inserted 169 if (usedEntries == size) { 170 clearUsedBits(); --- 80 unchanged lines hidden (view full) --- 251 i = lookupTable.find(tr); 252 if (i != lookupTable.end()) { 253 DPRINTF(IPR, "TLB: Demapped page\n"); 254 i->second->valid = false; 255 if (i->second->used) { 256 i->second->used = false; 257 usedEntries--; 258 } |
259 freeList.push_front(i->second); 260 DPRINTF(TLB, "Freeing TLB entry : %#X\n", i->second); |
|
222 lookupTable.erase(i); 223 } 224} 225 226void 227TLB::demapContext(int partition_id, int context_id) 228{ 229 int x; 230 DPRINTF(IPR, "TLB: Demapping Context pid=%#d cid=%d\n", 231 partition_id, context_id); 232 cacheValid = false; 233 for (x = 0; x < size; x++) { 234 if (tlb[x].range.contextId == context_id && 235 tlb[x].range.partitionId == partition_id) { | 261 lookupTable.erase(i); 262 } 263} 264 265void 266TLB::demapContext(int partition_id, int context_id) 267{ 268 int x; 269 DPRINTF(IPR, "TLB: Demapping Context pid=%#d cid=%d\n", 270 partition_id, context_id); 271 cacheValid = false; 272 for (x = 0; x < size; x++) { 273 if (tlb[x].range.contextId == context_id && 274 tlb[x].range.partitionId == partition_id) { |
275 if (tlb[x].valid == true) { 276 freeList.push_front(&tlb[x]); 277 DPRINTF(TLB, "Freeing TLB entry : %#X\n", &tlb[x]); 278 } |
|
236 tlb[x].valid = false; 237 if (tlb[x].used) { 238 tlb[x].used = false; 239 usedEntries--; 240 } 241 lookupTable.erase(tlb[x].range); 242 } 243 } 244} 245 246void 247TLB::demapAll(int partition_id) 248{ 249 int x; 250 DPRINTF(TLB, "TLB: Demapping All pid=%#d\n", partition_id); 251 cacheValid = false; 252 for (x = 0; x < size; x++) { 253 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { | 279 tlb[x].valid = false; 280 if (tlb[x].used) { 281 tlb[x].used = false; 282 usedEntries--; 283 } 284 lookupTable.erase(tlb[x].range); 285 } 286 } 287} 288 289void 290TLB::demapAll(int partition_id) 291{ 292 int x; 293 DPRINTF(TLB, "TLB: Demapping All pid=%#d\n", partition_id); 294 cacheValid = false; 295 for (x = 0; x < size; x++) { 296 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { |
297 if (tlb[x].valid == true){ 298 freeList.push_front(&tlb[x]); 299 DPRINTF(TLB, "Freeing TLB entry : %#X\n", &tlb[x]); 300 } |
|
254 tlb[x].valid = false; 255 if (tlb[x].used) { 256 tlb[x].used = false; 257 usedEntries--; 258 } 259 lookupTable.erase(tlb[x].range); 260 } 261 } 262} 263 264void 265TLB::invalidateAll() 266{ 267 int x; 268 cacheValid = false; 269 | 301 tlb[x].valid = false; 302 if (tlb[x].used) { 303 tlb[x].used = false; 304 usedEntries--; 305 } 306 lookupTable.erase(tlb[x].range); 307 } 308 } 309} 310 311void 312TLB::invalidateAll() 313{ 314 int x; 315 cacheValid = false; 316 |
317 freeList.clear(); |
|
270 for (x = 0; x < size; x++) { | 318 for (x = 0; x < size; x++) { |
319 if (tlb[x].valid == true) 320 freeList.push_back(&tlb[x]); |
|
271 tlb[x].valid = false; 272 } 273 usedEntries = 0; 274} 275 276uint64_t 277TLB::TteRead(int entry) { | 321 tlb[x].valid = false; 322 } 323 usedEntries = 0; 324} 325 326uint64_t 327TLB::TteRead(int entry) { |
328 if (entry >= size) 329 panic("entry: %d\n", entry); 330 |
|
278 assert(entry < size); | 331 assert(entry < size); |
279 return tlb[entry].pte(); | 332 if (tlb[entry].valid) 333 return tlb[entry].pte(); 334 else 335 return (uint64_t)-1ll; |
280} 281 282uint64_t 283TLB::TagRead(int entry) { 284 assert(entry < size); 285 uint64_t tag; | 336} 337 338uint64_t 339TLB::TagRead(int entry) { 340 assert(entry < size); 341 uint64_t tag; |
342 if (!tlb[entry].valid) 343 return (uint64_t)-1ll; |
|
286 | 344 |
287 tag = tlb[entry].range.contextId | tlb[entry].range.va | 288 (uint64_t)tlb[entry].range.partitionId << 61; | 345 tag = tlb[entry].range.contextId; 346 tag |= tlb[entry].range.va; 347 tag |= (uint64_t)tlb[entry].range.partitionId << 61; |
289 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; 290 tag |= (uint64_t)~tlb[entry].pte._size() << 56; 291 return tag; 292} 293 294bool 295TLB::validVirtualAddress(Addr va, bool am) 296{ --- 199 unchanged lines hidden (view full) --- 496 if (hpriv && implicit) { 497 req->setPaddr(vaddr & PAddrImplMask); 498 return NoFault; 499 } 500 501 // Be fast if we can! 502 if (cacheValid && cacheState == tlbdata) { 503 if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size && | 348 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; 349 tag |= (uint64_t)~tlb[entry].pte._size() << 56; 350 return tag; 351} 352 353bool 354TLB::validVirtualAddress(Addr va, bool am) 355{ --- 199 unchanged lines hidden (view full) --- 555 if (hpriv && implicit) { 556 req->setPaddr(vaddr & PAddrImplMask); 557 return NoFault; 558 } 559 560 // Be fast if we can! 561 if (cacheValid && cacheState == tlbdata) { 562 if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size && |
504 cacheEntry[0]->range.va + cacheEntry[0]->range.size >= vaddr) { | 563 cacheEntry[0]->range.va + cacheEntry[0]->range.size > vaddr) { |
505 req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) | 506 vaddr & cacheEntry[0]->pte.size()-1 ); 507 return NoFault; 508 } 509 if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size && | 564 req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) | 565 vaddr & cacheEntry[0]->pte.size()-1 ); 566 return NoFault; 567 } 568 if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size && |
510 cacheEntry[1]->range.va + cacheEntry[1]->range.size >= vaddr) { | 569 cacheEntry[1]->range.va + cacheEntry[1]->range.size > vaddr) { |
511 req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) | 512 vaddr & cacheEntry[1]->pte.size()-1 ); 513 return NoFault; 514 } 515 } 516 517 bool red = bits(tlbdata,1,1); 518 bool priv = bits(tlbdata,2,2); --- 143 unchanged lines hidden (view full) --- 662 663 664 if (!priv && e->pte.priv()) { 665 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi); 666 return new DataAccessException; 667 } 668 669 // cache translation date for next translation | 570 req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) | 571 vaddr & cacheEntry[1]->pte.size()-1 ); 572 return NoFault; 573 } 574 } 575 576 bool red = bits(tlbdata,1,1); 577 bool priv = bits(tlbdata,2,2); --- 143 unchanged lines hidden (view full) --- 721 722 723 if (!priv && e->pte.priv()) { 724 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi); 725 return new DataAccessException; 726 } 727 728 // cache translation date for next translation |
670 cacheValid = true; | |
671 cacheState = tlbdata; | 729 cacheState = tlbdata; |
730 if (!cacheValid) { 731 cacheEntry[1] = NULL; 732 cacheEntry[0] = NULL; 733 } 734 |
|
672 if (cacheEntry[0] != e && cacheEntry[1] != e) { 673 cacheEntry[1] = cacheEntry[0]; 674 cacheEntry[0] = e; 675 cacheAsi[1] = cacheAsi[0]; 676 cacheAsi[0] = asi; 677 if (implicit) 678 cacheAsi[0] = (ASI)0; 679 } | 735 if (cacheEntry[0] != e && cacheEntry[1] != e) { 736 cacheEntry[1] = cacheEntry[0]; 737 cacheEntry[0] = e; 738 cacheAsi[1] = cacheAsi[0]; 739 cacheAsi[0] = asi; 740 if (implicit) 741 cacheAsi[0] = (ASI)0; 742 } |
680 | 743 cacheValid = true; |
681 req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) | 682 vaddr & e->pte.size()-1); 683 DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); 684 return NoFault; 685 /** Normal flow ends here. */ 686 687handleScratchRegAccess: 688 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { 689 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 690 return new DataAccessException; 691 } 692 goto regAccessOk; 693 694handleQueueRegAccess: 695 if (!priv && !hpriv) { 696 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 697 return new PrivilegedAction; 698 } | 744 req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) | 745 vaddr & e->pte.size()-1); 746 DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); 747 return NoFault; 748 /** Normal flow ends here. */ 749 750handleScratchRegAccess: 751 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { 752 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 753 return new DataAccessException; 754 } 755 goto regAccessOk; 756 757handleQueueRegAccess: 758 if (!priv && !hpriv) { 759 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 760 return new PrivilegedAction; 761 } |
699 if (priv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) { | 762 if (!hpriv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) { |
700 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 701 return new DataAccessException; 702 } 703 goto regAccessOk; 704 705handleSparcErrorRegAccess: 706 if (!hpriv) { 707 if (priv) { --- 455 unchanged lines hidden --- | 763 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); 764 return new DataAccessException; 765 } 766 goto regAccessOk; 767 768handleSparcErrorRegAccess: 769 if (!hpriv) { 770 if (priv) { --- 455 unchanged lines hidden --- |