gpu_tlb.cc (12663:565c16ffe1d1) | gpu_tlb.cc (12717:2e2c211644d2) |
---|---|
1/* 2 * Copyright (c) 2011-2015 Advanced Micro Devices, Inc. 3 * All rights reserved. 4 * 5 * For use for simulation and test purposes only 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: --- 59 unchanged lines hidden (view full) --- 68 assoc = p->assoc; 69 assert(assoc <= size); 70 numSets = size/assoc; 71 allocationPolicy = p->allocationPolicy; 72 hasMemSidePort = false; 73 accessDistance = p->accessDistance; 74 clock = p->clk_domain->clockPeriod(); 75 | 1/* 2 * Copyright (c) 2011-2015 Advanced Micro Devices, Inc. 3 * All rights reserved. 4 * 5 * For use for simulation and test purposes only 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: --- 59 unchanged lines hidden (view full) --- 68 assoc = p->assoc; 69 assert(assoc <= size); 70 numSets = size/assoc; 71 allocationPolicy = p->allocationPolicy; 72 hasMemSidePort = false; 73 accessDistance = p->accessDistance; 74 clock = p->clk_domain->clockPeriod(); 75 |
76 tlb.assign(size, GpuTlbEntry()); | 76 tlb.assign(size, TlbEntry()); |
77 78 freeList.resize(numSets); 79 entryList.resize(numSets); 80 81 for (int set = 0; set < numSets; ++set) { 82 for (int way = 0; way < assoc; ++way) { 83 int x = set * assoc + way; 84 freeList[set].push_back(&tlb.at(x)); --- 76 unchanged lines hidden (view full) --- 161 hasMemSidePort = true; 162 163 return *memSidePort[idx]; 164 } else { 165 panic("TLBCoalescer::getMasterPort: unknown port %s\n", if_name); 166 } 167 } 168 | 77 78 freeList.resize(numSets); 79 entryList.resize(numSets); 80 81 for (int set = 0; set < numSets; ++set) { 82 for (int way = 0; way < assoc; ++way) { 83 int x = set * assoc + way; 84 freeList[set].push_back(&tlb.at(x)); --- 76 unchanged lines hidden (view full) --- 161 hasMemSidePort = true; 162 163 return *memSidePort[idx]; 164 } else { 165 panic("TLBCoalescer::getMasterPort: unknown port %s\n", if_name); 166 } 167 } 168 |
169 GpuTlbEntry* 170 GpuTLB::insert(Addr vpn, GpuTlbEntry &entry) | 169 TlbEntry* 170 GpuTLB::insert(Addr vpn, TlbEntry &entry) |
171 { | 171 { |
172 GpuTlbEntry *newEntry = nullptr; | 172 TlbEntry *newEntry = nullptr; |
173 174 /** 175 * vpn holds the virtual page address 176 * The least significant bits are simply masked 177 */ 178 int set = (vpn >> TheISA::PageShift) & setMask; 179 180 if (!freeList[set].empty()) { --- 36 unchanged lines hidden (view full) --- 217 218 break; 219 } 220 } 221 222 return entry; 223 } 224 | 173 174 /** 175 * vpn holds the virtual page address 176 * The least significant bits are simply masked 177 */ 178 int set = (vpn >> TheISA::PageShift) & setMask; 179 180 if (!freeList[set].empty()) { --- 36 unchanged lines hidden (view full) --- 217 218 break; 219 } 220 } 221 222 return entry; 223 } 224 |
225 GpuTlbEntry* | 225 TlbEntry* |
226 GpuTLB::lookup(Addr va, bool update_lru) 227 { 228 int set = (va >> TheISA::PageShift) & setMask; 229 230 auto entry = lookupIt(va, update_lru); 231 232 if (entry == entryList[set].end()) 233 return nullptr; 234 else 235 return *entry; 236 } 237 238 void 239 GpuTLB::invalidateAll() 240 { 241 DPRINTF(GPUTLB, "Invalidating all entries.\n"); 242 243 for (int i = 0; i < numSets; ++i) { 244 while (!entryList[i].empty()) { | 226 GpuTLB::lookup(Addr va, bool update_lru) 227 { 228 int set = (va >> TheISA::PageShift) & setMask; 229 230 auto entry = lookupIt(va, update_lru); 231 232 if (entry == entryList[set].end()) 233 return nullptr; 234 else 235 return *entry; 236 } 237 238 void 239 GpuTLB::invalidateAll() 240 { 241 DPRINTF(GPUTLB, "Invalidating all entries.\n"); 242 243 for (int i = 0; i < numSets; ++i) { 244 while (!entryList[i].empty()) { |
245 GpuTlbEntry *entry = entryList[i].front(); | 245 TlbEntry *entry = entryList[i].front(); |
246 entryList[i].pop_front(); 247 freeList[i].push_back(entry); 248 } 249 } 250 } 251 252 void 253 GpuTLB::setConfigAddress(uint32_t addr) --- 425 unchanged lines hidden (view full) --- 679 DPRINTF(GPUTLB, "In protected mode.\n"); 680 // make sure we are in 64-bit mode 681 assert(m5Reg.mode == LongMode); 682 683 // If paging is enabled, do the translation. 684 if (m5Reg.paging) { 685 DPRINTF(GPUTLB, "Paging enabled.\n"); 686 //update LRU stack on a hit | 246 entryList[i].pop_front(); 247 freeList[i].push_back(entry); 248 } 249 } 250 } 251 252 void 253 GpuTLB::setConfigAddress(uint32_t addr) --- 425 unchanged lines hidden (view full) --- 679 DPRINTF(GPUTLB, "In protected mode.\n"); 680 // make sure we are in 64-bit mode 681 assert(m5Reg.mode == LongMode); 682 683 // If paging is enabled, do the translation. 684 if (m5Reg.paging) { 685 DPRINTF(GPUTLB, "Paging enabled.\n"); 686 //update LRU stack on a hit |
687 GpuTlbEntry *entry = lookup(vaddr, true); | 687 TlbEntry *entry = lookup(vaddr, true); |
688 689 if (entry) 690 tlb_hit = true; 691 692 if (!update_stats) { 693 // functional tlb access for memory initialization 694 // i.e., memory seeding or instr. seeding -> don't update 695 // TLB and stats --- 91 unchanged lines hidden (view full) --- 787 return std::make_shared<GeneralProtection>(0); 788 } 789 } 790 791 // If paging is enabled, do the translation. 792 if (m5Reg.paging) { 793 DPRINTF(GPUTLB, "Paging enabled.\n"); 794 // The vaddr already has the segment base applied. | 688 689 if (entry) 690 tlb_hit = true; 691 692 if (!update_stats) { 693 // functional tlb access for memory initialization 694 // i.e., memory seeding or instr. seeding -> don't update 695 // TLB and stats --- 91 unchanged lines hidden (view full) --- 787 return std::make_shared<GeneralProtection>(0); 788 } 789 } 790 791 // If paging is enabled, do the translation. 792 if (m5Reg.paging) { 793 DPRINTF(GPUTLB, "Paging enabled.\n"); 794 // The vaddr already has the segment base applied. |
795 GpuTlbEntry *entry = lookup(vaddr); | 795 TlbEntry *entry = lookup(vaddr); |
796 localNumTLBAccesses++; 797 798 if (!entry) { 799 localNumTLBMisses++; 800 if (timing) { 801 latency = missLatency1; 802 } 803 --- 21 unchanged lines hidden (view full) --- 825 mode, true, 826 false); 827 } else { 828 Addr alignedVaddr = p->pTable->pageAlign(vaddr); 829 830 DPRINTF(GPUTLB, "Mapping %#x to %#x\n", 831 alignedVaddr, pte->paddr); 832 | 796 localNumTLBAccesses++; 797 798 if (!entry) { 799 localNumTLBMisses++; 800 if (timing) { 801 latency = missLatency1; 802 } 803 --- 21 unchanged lines hidden (view full) --- 825 mode, true, 826 false); 827 } else { 828 Addr alignedVaddr = p->pTable->pageAlign(vaddr); 829 830 DPRINTF(GPUTLB, "Mapping %#x to %#x\n", 831 alignedVaddr, pte->paddr); 832 |
833 GpuTlbEntry gpuEntry( 834 p->pTable->pid(), alignedVaddr, 835 pte->paddr, true); | 833 TlbEntry gpuEntry(p->pid(), alignedVaddr, 834 pte->paddr, false, false); |
836 entry = insert(alignedVaddr, gpuEntry); 837 } 838 839 DPRINTF(GPUTLB, "Miss was serviced.\n"); 840 } 841 } else { 842 localNumTLBHits++; 843 --- 229 unchanged lines hidden (view full) --- 1073 RequestPtr tmp_req = pkt->req; 1074 1075 // Access the TLB and figure out if it's a hit or a miss. 1076 bool success = tlbLookup(tmp_req, tmp_tc, update_stats); 1077 1078 if (success) { 1079 lookup_outcome = TLB_HIT; 1080 // Put the entry in SenderState | 835 entry = insert(alignedVaddr, gpuEntry); 836 } 837 838 DPRINTF(GPUTLB, "Miss was serviced.\n"); 839 } 840 } else { 841 localNumTLBHits++; 842 --- 229 unchanged lines hidden (view full) --- 1072 RequestPtr tmp_req = pkt->req; 1073 1074 // Access the TLB and figure out if it's a hit or a miss. 1075 bool success = tlbLookup(tmp_req, tmp_tc, update_stats); 1076 1077 if (success) { 1078 lookup_outcome = TLB_HIT; 1079 // Put the entry in SenderState |
1081 GpuTlbEntry *entry = lookup(tmp_req->getVaddr(), false); | 1080 TlbEntry *entry = lookup(tmp_req->getVaddr(), false); |
1082 assert(entry); 1083 | 1081 assert(entry); 1082 |
1083 auto p = sender_state->tc->getProcessPtr(); |
|
1084 sender_state->tlbEntry = | 1084 sender_state->tlbEntry = |
1085 new GpuTlbEntry(0, entry->vaddr, entry->paddr, entry->valid); | 1085 new TlbEntry(p->pid(), entry->vaddr, entry->paddr, 1086 false, false); |
1086 1087 if (update_stats) { 1088 // the reqCnt has an entry per level, so its size tells us 1089 // which level we are in 1090 sender_state->hitLevel = sender_state->reqCnt.size(); 1091 globalNumTLBHits += req_cnt; 1092 } 1093 } else { --- 35 unchanged lines hidden (view full) --- 1129 } 1130 1131 /** 1132 * Do Paging protection checks. If we encounter a page fault, then 1133 * an assertion is fired. 1134 */ 1135 void 1136 GpuTLB::pagingProtectionChecks(ThreadContext *tc, PacketPtr pkt, | 1087 1088 if (update_stats) { 1089 // the reqCnt has an entry per level, so its size tells us 1090 // which level we are in 1091 sender_state->hitLevel = sender_state->reqCnt.size(); 1092 globalNumTLBHits += req_cnt; 1093 } 1094 } else { --- 35 unchanged lines hidden (view full) --- 1130 } 1131 1132 /** 1133 * Do Paging protection checks. If we encounter a page fault, then 1134 * an assertion is fired. 1135 */ 1136 void 1137 GpuTLB::pagingProtectionChecks(ThreadContext *tc, PacketPtr pkt, |
1137 GpuTlbEntry * tlb_entry, Mode mode) | 1138 TlbEntry * tlb_entry, Mode mode) |
1138 { 1139 HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 1140 uint32_t flags = pkt->req->getFlags(); 1141 bool storeCheck = flags & (StoreCheck << FlagShift); 1142 1143 // Do paging protection checks. 1144 bool inUser = (m5Reg.cpl == 3 && !(flags & (CPL0FlagBit << FlagShift))); 1145 CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0); --- 29 unchanged lines hidden (view full) --- 1175 Addr vaddr = pkt->req->getVaddr(); 1176 1177 TranslationState *sender_state = 1178 safe_cast<TranslationState*>(pkt->senderState); 1179 1180 ThreadContext *tc = sender_state->tc; 1181 Mode mode = sender_state->tlbMode; 1182 | 1139 { 1140 HandyM5Reg m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG); 1141 uint32_t flags = pkt->req->getFlags(); 1142 bool storeCheck = flags & (StoreCheck << FlagShift); 1143 1144 // Do paging protection checks. 1145 bool inUser = (m5Reg.cpl == 3 && !(flags & (CPL0FlagBit << FlagShift))); 1146 CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0); --- 29 unchanged lines hidden (view full) --- 1176 Addr vaddr = pkt->req->getVaddr(); 1177 1178 TranslationState *sender_state = 1179 safe_cast<TranslationState*>(pkt->senderState); 1180 1181 ThreadContext *tc = sender_state->tc; 1182 Mode mode = sender_state->tlbMode; 1183 |
1183 GpuTlbEntry *local_entry, *new_entry; | 1184 TlbEntry *local_entry, *new_entry; |
1184 1185 if (tlb_outcome == TLB_HIT) { 1186 DPRINTF(GPUTLB, "Translation Done - TLB Hit for addr %#x\n", vaddr); 1187 local_entry = sender_state->tlbEntry; 1188 } else { 1189 DPRINTF(GPUTLB, "Translation Done - TLB Miss for addr %#x\n", 1190 vaddr); 1191 --- 150 unchanged lines hidden (view full) --- 1342 pte = p->pTable->lookup(vaddr); 1343 } 1344 1345 if (pte) { 1346 DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, 1347 pte->paddr); 1348 1349 sender_state->tlbEntry = | 1185 1186 if (tlb_outcome == TLB_HIT) { 1187 DPRINTF(GPUTLB, "Translation Done - TLB Hit for addr %#x\n", vaddr); 1188 local_entry = sender_state->tlbEntry; 1189 } else { 1190 DPRINTF(GPUTLB, "Translation Done - TLB Miss for addr %#x\n", 1191 vaddr); 1192 --- 150 unchanged lines hidden (view full) --- 1343 pte = p->pTable->lookup(vaddr); 1344 } 1345 1346 if (pte) { 1347 DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, 1348 pte->paddr); 1349 1350 sender_state->tlbEntry = |
1350 new GpuTlbEntry(0, virtPageAddr, pte->paddr, true); | 1351 new TlbEntry(p->pid(), virtPageAddr, pte->paddr, false, 1352 false); |
1351 } else { | 1353 } else { |
1352 sender_state->tlbEntry = 1353 new GpuTlbEntry(0, 0, 0, false); | 1354 sender_state->tlbEntry = nullptr; |
1354 } 1355 1356 handleTranslationReturn(virtPageAddr, TLB_MISS, pkt); 1357 } else if (outcome == MISS_RETURN) { 1358 /** we add an extra cycle in the return path of the translation 1359 * requests in between the various TLB levels. 1360 */ 1361 handleTranslationReturn(virtPageAddr, TLB_MISS, pkt); --- 60 unchanged lines hidden (view full) --- 1422 { 1423 TranslationState *sender_state = 1424 safe_cast<TranslationState*>(pkt->senderState); 1425 1426 ThreadContext *tc = sender_state->tc; 1427 Mode mode = sender_state->tlbMode; 1428 Addr vaddr = pkt->req->getVaddr(); 1429 | 1355 } 1356 1357 handleTranslationReturn(virtPageAddr, TLB_MISS, pkt); 1358 } else if (outcome == MISS_RETURN) { 1359 /** we add an extra cycle in the return path of the translation 1360 * requests in between the various TLB levels. 1361 */ 1362 handleTranslationReturn(virtPageAddr, TLB_MISS, pkt); --- 60 unchanged lines hidden (view full) --- 1423 { 1424 TranslationState *sender_state = 1425 safe_cast<TranslationState*>(pkt->senderState); 1426 1427 ThreadContext *tc = sender_state->tc; 1428 Mode mode = sender_state->tlbMode; 1429 Addr vaddr = pkt->req->getVaddr(); 1430 |
1430 GpuTlbEntry *local_entry, *new_entry; | 1431 TlbEntry *local_entry, *new_entry; |
1431 1432 if (tlb_outcome == TLB_HIT) { 1433 DPRINTF(GPUTLB, "Functional Translation Done - TLB hit for addr " 1434 "%#x\n", vaddr); 1435 1436 local_entry = sender_state->tlbEntry; 1437 } else { 1438 DPRINTF(GPUTLB, "Functional Translation Done - TLB miss for addr " --- 17 unchanged lines hidden (view full) --- 1456 1457 assert(local_entry); 1458 } 1459 1460 DPRINTF(GPUTLB, "Entry found with vaddr %#x, doing protection checks " 1461 "while paddr was %#x.\n", local_entry->vaddr, 1462 local_entry->paddr); 1463 | 1432 1433 if (tlb_outcome == TLB_HIT) { 1434 DPRINTF(GPUTLB, "Functional Translation Done - TLB hit for addr " 1435 "%#x\n", vaddr); 1436 1437 local_entry = sender_state->tlbEntry; 1438 } else { 1439 DPRINTF(GPUTLB, "Functional Translation Done - TLB miss for addr " --- 17 unchanged lines hidden (view full) --- 1457 1458 assert(local_entry); 1459 } 1460 1461 DPRINTF(GPUTLB, "Entry found with vaddr %#x, doing protection checks " 1462 "while paddr was %#x.\n", local_entry->vaddr, 1463 local_entry->paddr); 1464 |
1464 // Do paging checks if it's a normal functional access. If it's for a 1465 // prefetch, then sometimes you can try to prefetch something that won't 1466 // pass protection. We don't actually want to fault becuase there is no 1467 // demand access to deem this a violation. Just put it in the TLB and 1468 // it will fault if indeed a future demand access touches it in 1469 // violation. 1470 if (!sender_state->prefetch && sender_state->tlbEntry->valid) | 1465 /** 1466 * Do paging checks if it's a normal functional access. If it's for a 1467 * prefetch, then sometimes you can try to prefetch something that 1468 * won't pass protection. We don't actually want to fault becuase there 1469 * is no demand access to deem this a violation. Just put it in the 1470 * TLB and it will fault if indeed a future demand access touches it in 1471 * violation. 1472 * 1473 * This feature could be used to explore security issues around 1474 * speculative memory accesses. 1475 */ 1476 if (!sender_state->prefetch && sender_state->tlbEntry) |
1471 pagingProtectionChecks(tc, pkt, local_entry, mode); 1472 1473 int page_size = local_entry->size(); 1474 Addr paddr = local_entry->paddr | (vaddr & (page_size - 1)); 1475 DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, paddr); 1476 1477 pkt->req->setPaddr(paddr); 1478 --- 66 unchanged lines hidden (view full) --- 1545 // no PageFaults are permitted after 1546 // the second page table lookup 1547 assert(pte); 1548 1549 DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, 1550 pte->paddr); 1551 1552 sender_state->tlbEntry = | 1477 pagingProtectionChecks(tc, pkt, local_entry, mode); 1478 1479 int page_size = local_entry->size(); 1480 Addr paddr = local_entry->paddr | (vaddr & (page_size - 1)); 1481 DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, paddr); 1482 1483 pkt->req->setPaddr(paddr); 1484 --- 66 unchanged lines hidden (view full) --- 1551 // no PageFaults are permitted after 1552 // the second page table lookup 1553 assert(pte); 1554 1555 DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, 1556 pte->paddr); 1557 1558 sender_state->tlbEntry = |
1553 new GpuTlbEntry(0, virt_page_addr, 1554 pte->paddr, true); | 1559 new TlbEntry(p->pid(), virt_page_addr, 1560 pte->paddr, false, false); |
1555 } else { 1556 // If this was a prefetch, then do the normal thing if it 1557 // was a successful translation. Otherwise, send an empty 1558 // TLB entry back so that it can be figured out as empty and 1559 // handled accordingly. 1560 if (pte) { 1561 DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, 1562 pte->paddr); 1563 1564 sender_state->tlbEntry = | 1561 } else { 1562 // If this was a prefetch, then do the normal thing if it 1563 // was a successful translation. Otherwise, send an empty 1564 // TLB entry back so that it can be figured out as empty and 1565 // handled accordingly. 1566 if (pte) { 1567 DPRINTF(GPUTLB, "Mapping %#x to %#x\n", alignedVaddr, 1568 pte->paddr); 1569 1570 sender_state->tlbEntry = |
1565 new GpuTlbEntry(0, virt_page_addr, 1566 pte->paddr, true); | 1571 new TlbEntry(p->pid(), virt_page_addr, 1572 pte->paddr, false, false); |
1567 } else { 1568 DPRINTF(GPUPrefetch, "Prefetch failed %#x\n", 1569 alignedVaddr); 1570 | 1573 } else { 1574 DPRINTF(GPUPrefetch, "Prefetch failed %#x\n", 1575 alignedVaddr); 1576 |
1571 sender_state->tlbEntry = new GpuTlbEntry(); | 1577 sender_state->tlbEntry = nullptr; |
1572 1573 return; 1574 } 1575 } 1576 } 1577 } else { 1578 DPRINTF(GPUPrefetch, "Functional Hit for vaddr %#x\n", 1579 tlb->lookup(pkt->req->getVaddr())); 1580 | 1578 1579 return; 1580 } 1581 } 1582 } 1583 } else { 1584 DPRINTF(GPUPrefetch, "Functional Hit for vaddr %#x\n", 1585 tlb->lookup(pkt->req->getVaddr())); 1586 |
1581 GpuTlbEntry *entry = tlb->lookup(pkt->req->getVaddr(), | 1587 TlbEntry *entry = tlb->lookup(pkt->req->getVaddr(), |
1582 update_stats); 1583 1584 assert(entry); 1585 | 1588 update_stats); 1589 1590 assert(entry); 1591 |
1592 auto p = sender_state->tc->getProcessPtr(); |
|
1586 sender_state->tlbEntry = | 1593 sender_state->tlbEntry = |
1587 new GpuTlbEntry(0, entry->vaddr, entry->paddr, entry->valid); | 1594 new TlbEntry(p->pid(), entry->vaddr, entry->paddr, 1595 false, false); |
1588 } 1589 // This is the function that would populate pkt->req with the paddr of 1590 // the translation. But if no translation happens (i.e Prefetch fails) 1591 // then the early returns in the above code wiill keep this function 1592 // from executing. 1593 tlb->handleFuncTranslationReturn(pkt, tlb_outcome); 1594 } 1595 --- 208 unchanged lines hidden --- | 1596 } 1597 // This is the function that would populate pkt->req with the paddr of 1598 // the translation. But if no translation happens (i.e Prefetch fails) 1599 // then the early returns in the above code wiill keep this function 1600 // from executing. 1601 tlb->handleFuncTranslationReturn(pkt, tlb_outcome); 1602 } 1603 --- 208 unchanged lines hidden --- |