tlb.cc revision 6185:9925b3e83e06
12929Sktlim@umich.edu/* 211504Sandreas.sandberg@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan 311504Sandreas.sandberg@arm.com * All rights reserved. 411504Sandreas.sandberg@arm.com * 511504Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without 611504Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are 711504Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright 811504Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer; 911504Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright 1011504Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the 1111504Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution; 1211504Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its 1311504Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from 1411504Sandreas.sandberg@arm.com * this software without specific prior written permission. 152932Sktlim@umich.edu * 162929Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172929Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182929Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192929Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202929Sktlim@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212929Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222929Sktlim@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232929Sktlim@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242929Sktlim@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252929Sktlim@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262929Sktlim@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272929Sktlim@umich.edu * 282929Sktlim@umich.edu * Authors: Nathan Binkert 292929Sktlim@umich.edu * Steve Reinhardt 302929Sktlim@umich.edu * Andrew Schultz 312929Sktlim@umich.edu */ 322929Sktlim@umich.edu 332929Sktlim@umich.edu#include <string> 342929Sktlim@umich.edu#include <vector> 352929Sktlim@umich.edu 362929Sktlim@umich.edu#include "arch/alpha/pagetable.hh" 372929Sktlim@umich.edu#include "arch/alpha/tlb.hh" 382929Sktlim@umich.edu#include "arch/alpha/faults.hh" 392929Sktlim@umich.edu#include "base/inifile.hh" 402932Sktlim@umich.edu#include "base/str.hh" 412932Sktlim@umich.edu#include "base/trace.hh" 422932Sktlim@umich.edu#include "cpu/thread_context.hh" 4311504Sandreas.sandberg@arm.com 442929Sktlim@umich.eduusing namespace std; 452929Sktlim@umich.edu 4611504Sandreas.sandberg@arm.comnamespace AlphaISA { 4711504Sandreas.sandberg@arm.com 4811504Sandreas.sandberg@arm.com/////////////////////////////////////////////////////////////////////// 4911504Sandreas.sandberg@arm.com// 5011504Sandreas.sandberg@arm.com// Alpha TLB 5111504Sandreas.sandberg@arm.com// 5211504Sandreas.sandberg@arm.com 532929Sktlim@umich.edu#ifdef DEBUG 542929Sktlim@umich.edubool uncacheBit39 = false; 552929Sktlim@umich.edubool uncacheBit40 = false; 568947Sandreas.hansson@arm.com#endif 578947Sandreas.hansson@arm.com 588947Sandreas.hansson@arm.com#define MODE2MASK(X) (1 << (X)) 592929Sktlim@umich.edu 602929Sktlim@umich.eduTLB::TLB(const Params *p) 6111504Sandreas.sandberg@arm.com : BaseTLB(p), size(p->size), nlu(0) 6211504Sandreas.sandberg@arm.com{ 6311504Sandreas.sandberg@arm.com table = new TlbEntry[size]; 6411504Sandreas.sandberg@arm.com memset(table, 0, sizeof(TlbEntry[size])); 6511504Sandreas.sandberg@arm.com flushCache(); 6611504Sandreas.sandberg@arm.com} 6711504Sandreas.sandberg@arm.com 682929Sktlim@umich.eduTLB::~TLB() 6911504Sandreas.sandberg@arm.com{ 7011504Sandreas.sandberg@arm.com if (table) 716007Ssteve.reinhardt@amd.com delete [] table; 726007Ssteve.reinhardt@amd.com} 7311504Sandreas.sandberg@arm.com 742929Sktlim@umich.eduvoid 752929Sktlim@umich.eduTLB::regStats() 7611504Sandreas.sandberg@arm.com{ 776007Ssteve.reinhardt@amd.com fetch_hits 786007Ssteve.reinhardt@amd.com .name(name() + ".fetch_hits") 799781Sandreas.hansson@arm.com .desc("ITB hits"); 806007Ssteve.reinhardt@amd.com fetch_misses 8111504Sandreas.sandberg@arm.com .name(name() + ".fetch_misses") 822929Sktlim@umich.edu .desc("ITB misses"); 832929Sktlim@umich.edu fetch_acv 8411504Sandreas.sandberg@arm.com .name(name() + ".fetch_acv") 8511504Sandreas.sandberg@arm.com .desc("ITB acv"); 8611504Sandreas.sandberg@arm.com fetch_accesses 8711504Sandreas.sandberg@arm.com .name(name() + ".fetch_accesses") 8811504Sandreas.sandberg@arm.com .desc("ITB accesses"); 896007Ssteve.reinhardt@amd.com 9011504Sandreas.sandberg@arm.com fetch_accesses = fetch_hits + fetch_misses; 9111504Sandreas.sandberg@arm.com 9211504Sandreas.sandberg@arm.com read_hits 9311504Sandreas.sandberg@arm.com .name(name() + ".read_hits") 946007Ssteve.reinhardt@amd.com .desc("DTB read hits") 9511504Sandreas.sandberg@arm.com ; 9611504Sandreas.sandberg@arm.com 9711504Sandreas.sandberg@arm.com read_misses 986007Ssteve.reinhardt@amd.com .name(name() + ".read_misses") 992929Sktlim@umich.edu .desc("DTB read misses") 1002929Sktlim@umich.edu ; 1016007Ssteve.reinhardt@amd.com 1026007Ssteve.reinhardt@amd.com read_acv 1032929Sktlim@umich.edu .name(name() + ".read_acv") 1042929Sktlim@umich.edu .desc("DTB read access violations") 1056007Ssteve.reinhardt@amd.com ; 1062929Sktlim@umich.edu 1072929Sktlim@umich.edu read_accesses 10811504Sandreas.sandberg@arm.com .name(name() + ".read_accesses") 1098947Sandreas.hansson@arm.com .desc("DTB read accesses") 11011504Sandreas.sandberg@arm.com ; 11111504Sandreas.sandberg@arm.com 1128947Sandreas.hansson@arm.com write_hits 11311504Sandreas.sandberg@arm.com .name(name() + ".write_hits") 11411504Sandreas.sandberg@arm.com .desc("DTB write hits") 1158947Sandreas.hansson@arm.com ; 11611504Sandreas.sandberg@arm.com 11711504Sandreas.sandberg@arm.com write_misses 11811504Sandreas.sandberg@arm.com .name(name() + ".write_misses") 1198947Sandreas.hansson@arm.com .desc("DTB write misses") 12011504Sandreas.sandberg@arm.com ; 12111504Sandreas.sandberg@arm.com 12211504Sandreas.sandberg@arm.com write_acv 12311504Sandreas.sandberg@arm.com .name(name() + ".write_acv") 12411542Sandreas.sandberg@arm.com .desc("DTB write access violations") 12511542Sandreas.sandberg@arm.com ; 12611542Sandreas.sandberg@arm.com 12711542Sandreas.sandberg@arm.com write_accesses 12811504Sandreas.sandberg@arm.com .name(name() + ".write_accesses") 12911504Sandreas.sandberg@arm.com .desc("DTB write accesses") 13011504Sandreas.sandberg@arm.com ; 13111504Sandreas.sandberg@arm.com 13211542Sandreas.sandberg@arm.com data_hits 13311504Sandreas.sandberg@arm.com .name(name() + ".data_hits") 13411504Sandreas.sandberg@arm.com .desc("DTB hits") 13511504Sandreas.sandberg@arm.com ; 13611504Sandreas.sandberg@arm.com 13711504Sandreas.sandberg@arm.com data_misses 13811504Sandreas.sandberg@arm.com .name(name() + ".data_misses") 1392929Sktlim@umich.edu .desc("DTB misses") 1402929Sktlim@umich.edu ; 14111504Sandreas.sandberg@arm.com 1424937Sstever@gmail.com data_acv 1432929Sktlim@umich.edu .name(name() + ".data_acv") 14411504Sandreas.sandberg@arm.com .desc("DTB access violations") 1452929Sktlim@umich.edu ; 14611504Sandreas.sandberg@arm.com 14711504Sandreas.sandberg@arm.com data_accesses 1482929Sktlim@umich.edu .name(name() + ".data_accesses") 14911504Sandreas.sandberg@arm.com .desc("DTB accesses") 15011504Sandreas.sandberg@arm.com ; 1512929Sktlim@umich.edu 15211504Sandreas.sandberg@arm.com data_hits = read_hits + write_hits; 15311504Sandreas.sandberg@arm.com data_misses = read_misses + write_misses; 15411504Sandreas.sandberg@arm.com data_acv = read_acv + write_acv; 15511504Sandreas.sandberg@arm.com data_accesses = read_accesses + write_accesses; 15611504Sandreas.sandberg@arm.com} 15711504Sandreas.sandberg@arm.com 15811504Sandreas.sandberg@arm.com// look up an entry in the TLB 15911504Sandreas.sandberg@arm.comTlbEntry * 16011504Sandreas.sandberg@arm.comTLB::lookup(Addr vpn, uint8_t asn) 16111504Sandreas.sandberg@arm.com{ 16211504Sandreas.sandberg@arm.com // assume not found... 16311504Sandreas.sandberg@arm.com TlbEntry *retval = NULL; 16411542Sandreas.sandberg@arm.com 16511504Sandreas.sandberg@arm.com if (EntryCache[0]) { 16611504Sandreas.sandberg@arm.com if (vpn == EntryCache[0]->tag && 16711504Sandreas.sandberg@arm.com (EntryCache[0]->asma || EntryCache[0]->asn == asn)) 16811504Sandreas.sandberg@arm.com retval = EntryCache[0]; 16911504Sandreas.sandberg@arm.com else if (EntryCache[1]) { 17011504Sandreas.sandberg@arm.com if (vpn == EntryCache[1]->tag && 17111504Sandreas.sandberg@arm.com (EntryCache[1]->asma || EntryCache[1]->asn == asn)) 17211542Sandreas.sandberg@arm.com retval = EntryCache[1]; 17311504Sandreas.sandberg@arm.com else if (EntryCache[2] && vpn == EntryCache[2]->tag && 17411504Sandreas.sandberg@arm.com (EntryCache[2]->asma || EntryCache[2]->asn == asn)) 17511504Sandreas.sandberg@arm.com retval = EntryCache[2]; 17611504Sandreas.sandberg@arm.com } 17711504Sandreas.sandberg@arm.com } 17811504Sandreas.sandberg@arm.com 17911504Sandreas.sandberg@arm.com if (retval == NULL) { 1802929Sktlim@umich.edu PageTable::const_iterator i = lookupTable.find(vpn); 1812929Sktlim@umich.edu if (i != lookupTable.end()) { 1822929Sktlim@umich.edu while (i->first == vpn) { 18311504Sandreas.sandberg@arm.com int index = i->second; 1842929Sktlim@umich.edu TlbEntry *entry = &table[index]; 1852929Sktlim@umich.edu assert(entry->valid); 1862929Sktlim@umich.edu if (vpn == entry->tag && (entry->asma || entry->asn == asn)) { 1872929Sktlim@umich.edu retval = updateCache(entry); 18811504Sandreas.sandberg@arm.com break; 1892997Sstever@eecs.umich.edu } 1902929Sktlim@umich.edu 19111504Sandreas.sandberg@arm.com ++i; 19211504Sandreas.sandberg@arm.com } 19311504Sandreas.sandberg@arm.com } 1942929Sktlim@umich.edu } 19511504Sandreas.sandberg@arm.com 19611504Sandreas.sandberg@arm.com DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, 1972929Sktlim@umich.edu retval ? "hit" : "miss", retval ? retval->ppn : 0); 19811504Sandreas.sandberg@arm.com return retval; 19911504Sandreas.sandberg@arm.com} 2002997Sstever@eecs.umich.edu 20111504Sandreas.sandberg@arm.comFault 20211504Sandreas.sandberg@arm.comTLB::checkCacheability(RequestPtr &req, bool itb) 20311504Sandreas.sandberg@arm.com{ 20411504Sandreas.sandberg@arm.com // in Alpha, cacheability is controlled by upper-level bits of the 2052997Sstever@eecs.umich.edu // physical address 20611504Sandreas.sandberg@arm.com 20711504Sandreas.sandberg@arm.com /* 20811504Sandreas.sandberg@arm.com * We support having the uncacheable bit in either bit 39 or bit 20911504Sandreas.sandberg@arm.com * 40. The Turbolaser platform (and EV5) support having the bit 21011504Sandreas.sandberg@arm.com * in 39, but Tsunami (which Linux assumes uses an EV6) generates 21111504Sandreas.sandberg@arm.com * accesses with the bit in 40. So we must check for both, but we 2122929Sktlim@umich.edu * have debug flags to catch a weird case where both are used, 2132997Sstever@eecs.umich.edu * which shouldn't happen. 2148120Sgblack@eecs.umich.edu */ 21511504Sandreas.sandberg@arm.com 2162997Sstever@eecs.umich.edu 21711504Sandreas.sandberg@arm.com if (req->getPaddr() & PAddrUncachedBit43) { 2182929Sktlim@umich.edu // IPR memory space not implemented 2192997Sstever@eecs.umich.edu if (PAddrIprSpace(req->getPaddr())) { 2202929Sktlim@umich.edu return new UnimpFault("IPR memory space not implemented!"); 22111504Sandreas.sandberg@arm.com } else { 22211504Sandreas.sandberg@arm.com // mark request as uncacheable 2232929Sktlim@umich.edu req->setFlags(Request::UNCACHEABLE); 22411504Sandreas.sandberg@arm.com 22511504Sandreas.sandberg@arm.com // Clear bits 42:35 of the physical address (10-2 in 2263691Shsul@eecs.umich.edu // Tsunami manual) 22711504Sandreas.sandberg@arm.com req->setPaddr(req->getPaddr() & PAddrUncachedMask); 2283005Sstever@eecs.umich.edu } 22911504Sandreas.sandberg@arm.com // We shouldn't be able to read from an uncachable address in Alpha as 23011105Spower.jg@gmail.com // we don't have a ROM and we don't want to try to fetch from a device 23111504Sandreas.sandberg@arm.com // register as we destroy any data that is clear-on-read. 23211504Sandreas.sandberg@arm.com if (req->isUncacheable() && itb) 23311504Sandreas.sandberg@arm.com return new UnimpFault("CPU trying to fetch from uncached I/O"); 2346166Ssteve.reinhardt@amd.com 23511504Sandreas.sandberg@arm.com } 23611504Sandreas.sandberg@arm.com return NoFault; 23711504Sandreas.sandberg@arm.com} 23811504Sandreas.sandberg@arm.com 23911504Sandreas.sandberg@arm.com 24011504Sandreas.sandberg@arm.com// insert a new TLB entry 24111504Sandreas.sandberg@arm.comvoid 24211504Sandreas.sandberg@arm.comTLB::insert(Addr addr, TlbEntry &entry) 24311504Sandreas.sandberg@arm.com{ 24411504Sandreas.sandberg@arm.com flushCache(); 24511504Sandreas.sandberg@arm.com VAddr vaddr = addr; 24611504Sandreas.sandberg@arm.com if (table[nlu].valid) { 24711504Sandreas.sandberg@arm.com Addr oldvpn = table[nlu].tag; 24811504Sandreas.sandberg@arm.com PageTable::iterator i = lookupTable.find(oldvpn); 249 250 if (i == lookupTable.end()) 251 panic("TLB entry not found in lookupTable"); 252 253 int index; 254 while ((index = i->second) != nlu) { 255 if (table[index].tag != oldvpn) 256 panic("TLB entry not found in lookupTable"); 257 258 ++i; 259 } 260 261 DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn); 262 263 lookupTable.erase(i); 264 } 265 266 DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), entry.ppn); 267 268 table[nlu] = entry; 269 table[nlu].tag = vaddr.vpn(); 270 table[nlu].valid = true; 271 272 lookupTable.insert(make_pair(vaddr.vpn(), nlu)); 273 nextnlu(); 274} 275 276void 277TLB::flushAll() 278{ 279 DPRINTF(TLB, "flushAll\n"); 280 memset(table, 0, sizeof(TlbEntry[size])); 281 flushCache(); 282 lookupTable.clear(); 283 nlu = 0; 284} 285 286void 287TLB::flushProcesses() 288{ 289 flushCache(); 290 PageTable::iterator i = lookupTable.begin(); 291 PageTable::iterator end = lookupTable.end(); 292 while (i != end) { 293 int index = i->second; 294 TlbEntry *entry = &table[index]; 295 assert(entry->valid); 296 297 // we can't increment i after we erase it, so save a copy and 298 // increment it to get the next entry now 299 PageTable::iterator cur = i; 300 ++i; 301 302 if (!entry->asma) { 303 DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, 304 entry->tag, entry->ppn); 305 entry->valid = false; 306 lookupTable.erase(cur); 307 } 308 } 309} 310 311void 312TLB::flushAddr(Addr addr, uint8_t asn) 313{ 314 flushCache(); 315 VAddr vaddr = addr; 316 317 PageTable::iterator i = lookupTable.find(vaddr.vpn()); 318 if (i == lookupTable.end()) 319 return; 320 321 while (i != lookupTable.end() && i->first == vaddr.vpn()) { 322 int index = i->second; 323 TlbEntry *entry = &table[index]; 324 assert(entry->valid); 325 326 if (vaddr.vpn() == entry->tag && (entry->asma || entry->asn == asn)) { 327 DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(), 328 entry->ppn); 329 330 // invalidate this entry 331 entry->valid = false; 332 333 lookupTable.erase(i++); 334 } else { 335 ++i; 336 } 337 } 338} 339 340 341void 342TLB::serialize(ostream &os) 343{ 344 SERIALIZE_SCALAR(size); 345 SERIALIZE_SCALAR(nlu); 346 347 for (int i = 0; i < size; i++) { 348 nameOut(os, csprintf("%s.Entry%d", name(), i)); 349 table[i].serialize(os); 350 } 351} 352 353void 354TLB::unserialize(Checkpoint *cp, const string §ion) 355{ 356 UNSERIALIZE_SCALAR(size); 357 UNSERIALIZE_SCALAR(nlu); 358 359 for (int i = 0; i < size; i++) { 360 table[i].unserialize(cp, csprintf("%s.Entry%d", section, i)); 361 if (table[i].valid) { 362 lookupTable.insert(make_pair(table[i].tag, i)); 363 } 364 } 365} 366 367Fault 368TLB::translateInst(RequestPtr req, ThreadContext *tc) 369{ 370 //If this is a pal pc, then set PHYSICAL 371 if (FULL_SYSTEM && PcPAL(req->getPC())) 372 req->setFlags(Request::PHYSICAL); 373 374 if (PcPAL(req->getPC())) { 375 // strip off PAL PC marker (lsb is 1) 376 req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask); 377 fetch_hits++; 378 return NoFault; 379 } 380 381 if (req->getFlags() & Request::PHYSICAL) { 382 req->setPaddr(req->getVaddr()); 383 } else { 384 // verify that this is a good virtual address 385 if (!validVirtualAddress(req->getVaddr())) { 386 fetch_acv++; 387 return new ItbAcvFault(req->getVaddr()); 388 } 389 390 391 // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5 392 // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6 393 if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) { 394 // only valid in kernel mode 395 if (ICM_CM(tc->readMiscRegNoEffect(IPR_ICM)) != 396 mode_kernel) { 397 fetch_acv++; 398 return new ItbAcvFault(req->getVaddr()); 399 } 400 401 req->setPaddr(req->getVaddr() & PAddrImplMask); 402 403 // sign extend the physical address properly 404 if (req->getPaddr() & PAddrUncachedBit40) 405 req->setPaddr(req->getPaddr() | ULL(0xf0000000000)); 406 else 407 req->setPaddr(req->getPaddr() & ULL(0xffffffffff)); 408 } else { 409 // not a physical address: need to look up pte 410 int asn = DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN)); 411 TlbEntry *entry = lookup(VAddr(req->getVaddr()).vpn(), 412 asn); 413 414 if (!entry) { 415 fetch_misses++; 416 return new ItbPageFault(req->getVaddr()); 417 } 418 419 req->setPaddr((entry->ppn << PageShift) + 420 (VAddr(req->getVaddr()).offset() 421 & ~3)); 422 423 // check permissions for this access 424 if (!(entry->xre & 425 (1 << ICM_CM(tc->readMiscRegNoEffect(IPR_ICM))))) { 426 // instruction access fault 427 fetch_acv++; 428 return new ItbAcvFault(req->getVaddr()); 429 } 430 431 fetch_hits++; 432 } 433 } 434 435 // check that the physical address is ok (catch bad physical addresses) 436 if (req->getPaddr() & ~PAddrImplMask) 437 return genMachineCheckFault(); 438 439 return checkCacheability(req, true); 440 441} 442 443Fault 444TLB::translateData(RequestPtr req, ThreadContext *tc, bool write) 445{ 446 Addr pc = tc->readPC(); 447 448 mode_type mode = 449 (mode_type)DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)); 450 451 /** 452 * Check for alignment faults 453 */ 454 if (req->getVaddr() & (req->getSize() - 1)) { 455 DPRINTF(TLB, "Alignment Fault on %#x, size = %d\n", req->getVaddr(), 456 req->getSize()); 457 uint64_t flags = write ? MM_STAT_WR_MASK : 0; 458 return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags); 459 } 460 461 if (PcPAL(pc)) { 462 mode = (req->getFlags() & Request::ALTMODE) ? 463 (mode_type)ALT_MODE_AM( 464 tc->readMiscRegNoEffect(IPR_ALT_MODE)) 465 : mode_kernel; 466 } 467 468 if (req->getFlags() & Request::PHYSICAL) { 469 req->setPaddr(req->getVaddr()); 470 } else { 471 // verify that this is a good virtual address 472 if (!validVirtualAddress(req->getVaddr())) { 473 if (write) { write_acv++; } else { read_acv++; } 474 uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | 475 MM_STAT_BAD_VA_MASK | 476 MM_STAT_ACV_MASK; 477 return new DtbPageFault(req->getVaddr(), req->getFlags(), flags); 478 } 479 480 // Check for "superpage" mapping 481 if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) { 482 // only valid in kernel mode 483 if (DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)) != 484 mode_kernel) { 485 if (write) { write_acv++; } else { read_acv++; } 486 uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) | 487 MM_STAT_ACV_MASK); 488 489 return new DtbAcvFault(req->getVaddr(), req->getFlags(), 490 flags); 491 } 492 493 req->setPaddr(req->getVaddr() & PAddrImplMask); 494 495 // sign extend the physical address properly 496 if (req->getPaddr() & PAddrUncachedBit40) 497 req->setPaddr(req->getPaddr() | ULL(0xf0000000000)); 498 else 499 req->setPaddr(req->getPaddr() & ULL(0xffffffffff)); 500 } else { 501 if (write) 502 write_accesses++; 503 else 504 read_accesses++; 505 506 int asn = DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN)); 507 508 // not a physical address: need to look up pte 509 TlbEntry *entry = lookup(VAddr(req->getVaddr()).vpn(), asn); 510 511 if (!entry) { 512 // page fault 513 if (write) { write_misses++; } else { read_misses++; } 514 uint64_t flags = (write ? MM_STAT_WR_MASK : 0) | 515 MM_STAT_DTB_MISS_MASK; 516 return (req->getFlags() & Request::VPTE) ? 517 (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(), 518 flags)) : 519 (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(), 520 flags)); 521 } 522 523 req->setPaddr((entry->ppn << PageShift) + 524 VAddr(req->getVaddr()).offset()); 525 526 if (write) { 527 if (!(entry->xwe & MODE2MASK(mode))) { 528 // declare the instruction access fault 529 write_acv++; 530 uint64_t flags = MM_STAT_WR_MASK | 531 MM_STAT_ACV_MASK | 532 (entry->fonw ? MM_STAT_FONW_MASK : 0); 533 return new DtbPageFault(req->getVaddr(), req->getFlags(), 534 flags); 535 } 536 if (entry->fonw) { 537 write_acv++; 538 uint64_t flags = MM_STAT_WR_MASK | MM_STAT_FONW_MASK; 539 return new DtbPageFault(req->getVaddr(), req->getFlags(), 540 flags); 541 } 542 } else { 543 if (!(entry->xre & MODE2MASK(mode))) { 544 read_acv++; 545 uint64_t flags = MM_STAT_ACV_MASK | 546 (entry->fonr ? MM_STAT_FONR_MASK : 0); 547 return new DtbAcvFault(req->getVaddr(), req->getFlags(), 548 flags); 549 } 550 if (entry->fonr) { 551 read_acv++; 552 uint64_t flags = MM_STAT_FONR_MASK; 553 return new DtbPageFault(req->getVaddr(), req->getFlags(), 554 flags); 555 } 556 } 557 } 558 559 if (write) 560 write_hits++; 561 else 562 read_hits++; 563 } 564 565 // check that the physical address is ok (catch bad physical addresses) 566 if (req->getPaddr() & ~PAddrImplMask) 567 return genMachineCheckFault(); 568 569 return checkCacheability(req); 570} 571 572TlbEntry & 573TLB::index(bool advance) 574{ 575 TlbEntry *entry = &table[nlu]; 576 577 if (advance) 578 nextnlu(); 579 580 return *entry; 581} 582 583Fault 584TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode) 585{ 586 if (mode == Execute) 587 return translateInst(req, tc); 588 else 589 return translateData(req, tc, mode == Write); 590} 591 592void 593TLB::translateTiming(RequestPtr req, ThreadContext *tc, 594 Translation *translation, Mode mode) 595{ 596 assert(translation); 597 translation->finish(translateAtomic(req, tc, mode), req, tc, mode); 598} 599 600/* end namespace AlphaISA */ } 601 602AlphaISA::TLB * 603AlphaTLBParams::create() 604{ 605 return new AlphaISA::TLB(this); 606} 607