tlb.cc revision 237
110152Satgutier@umich.edu/* 210152Satgutier@umich.edu * Copyright (c) 2003 The Regents of The University of Michigan 310152Satgutier@umich.edu * All rights reserved. 410152Satgutier@umich.edu * 510234Syasuko.eckert@amd.com * Redistribution and use in source and binary forms, with or without 610152Satgutier@umich.edu * modification, are permitted provided that the following conditions are 710152Satgutier@umich.edu * met: redistributions of source code must retain the above copyright 810152Satgutier@umich.edu * notice, this list of conditions and the following disclaimer; 910152Satgutier@umich.edu * redistributions in binary form must reproduce the above copyright 1010152Satgutier@umich.edu * notice, this list of conditions and the following disclaimer in the 1110152Satgutier@umich.edu * documentation and/or other materials provided with the distribution; 1210152Satgutier@umich.edu * neither the name of the copyright holders nor the names of its 1310152Satgutier@umich.edu * contributors may be used to endorse or promote products derived from 1410152Satgutier@umich.edu * this software without specific prior written permission. 1510152Satgutier@umich.edu * 1610152Satgutier@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710152Satgutier@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1810152Satgutier@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1910152Satgutier@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2010152Satgutier@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110152Satgutier@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2210152Satgutier@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310152Satgutier@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410152Satgutier@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510152Satgutier@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610152Satgutier@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710152Satgutier@umich.edu */ 2810152Satgutier@umich.edu 2910234Syasuko.eckert@amd.com#include <sstream> 3010152Satgutier@umich.edu#include <string> 3110152Satgutier@umich.edu#include <vector> 3210152Satgutier@umich.edu 3310152Satgutier@umich.edu#include "base/inifile.hh" 3410152Satgutier@umich.edu#include "base/str.hh" 3510234Syasuko.eckert@amd.com#include "base/trace.hh" 3610152Satgutier@umich.edu#include "cpu/exec_context.hh" 3710152Satgutier@umich.edu#include "sim/builder.hh" 3810152Satgutier@umich.edu#include "targetarch/alpha_memory.hh" 3910152Satgutier@umich.edu#include "targetarch/ev5.hh" 4010152Satgutier@umich.edu 4110152Satgutier@umich.eduusing namespace std; 4210152Satgutier@umich.edu 4310234Syasuko.eckert@amd.com/////////////////////////////////////////////////////////////////////// 4410234Syasuko.eckert@amd.com// 4510234Syasuko.eckert@amd.com// Alpha TLB 4610234Syasuko.eckert@amd.com// 4710234Syasuko.eckert@amd.comAlphaTlb::AlphaTlb(const string &name, int s) 4810234Syasuko.eckert@amd.com : SimObject(name), size(s), nlu(0) 4910234Syasuko.eckert@amd.com{ 5010234Syasuko.eckert@amd.com table = new AlphaISA::PTE[size]; 5110234Syasuko.eckert@amd.com memset(table, 0, sizeof(AlphaISA::PTE[size])); 5210234Syasuko.eckert@amd.com} 5310234Syasuko.eckert@amd.com 5410234Syasuko.eckert@amd.comAlphaTlb::~AlphaTlb() 5510234Syasuko.eckert@amd.com{ 5610234Syasuko.eckert@amd.com if (table) 5710234Syasuko.eckert@amd.com delete [] table; 5810234Syasuko.eckert@amd.com} 5910234Syasuko.eckert@amd.com 6010234Syasuko.eckert@amd.com// look up an entry in the TLB 6110234Syasuko.eckert@amd.comAlphaISA::PTE * 6210234Syasuko.eckert@amd.comAlphaTlb::lookup(Addr vpn, uint8_t asn) const 6310234Syasuko.eckert@amd.com{ 6410234Syasuko.eckert@amd.com DPRINTF(TLB, "lookup %#x\n", vpn); 6510234Syasuko.eckert@amd.com 6610234Syasuko.eckert@amd.com PageTable::const_iterator i = lookupTable.find(vpn); 6710152Satgutier@umich.edu if (i == lookupTable.end()) 6810234Syasuko.eckert@amd.com return NULL; 6910234Syasuko.eckert@amd.com 7010234Syasuko.eckert@amd.com while (i->first == vpn) { 7110234Syasuko.eckert@amd.com int index = i->second; 7210234Syasuko.eckert@amd.com AlphaISA::PTE *pte = &table[index]; 7310234Syasuko.eckert@amd.com assert(pte->valid); 7410234Syasuko.eckert@amd.com if (vpn == pte->tag && (pte->asma || pte->asn == asn)) 7510234Syasuko.eckert@amd.com return pte; 7610234Syasuko.eckert@amd.com 7710234Syasuko.eckert@amd.com ++i; 7810234Syasuko.eckert@amd.com } 7910234Syasuko.eckert@amd.com 8010234Syasuko.eckert@amd.com // not found... 8110234Syasuko.eckert@amd.com return NULL; 8210234Syasuko.eckert@amd.com} 8310234Syasuko.eckert@amd.com 8410234Syasuko.eckert@amd.com 8510234Syasuko.eckert@amd.comvoid 8610234Syasuko.eckert@amd.comAlphaTlb::checkCacheability(MemReqPtr req) 8710234Syasuko.eckert@amd.com{ 8810234Syasuko.eckert@amd.com // in Alpha, cacheability is controlled by upper-level bits of the 8910234Syasuko.eckert@amd.com // physical address 9010234Syasuko.eckert@amd.com if (req->paddr & PA_UNCACHED_BIT) { 9110234Syasuko.eckert@amd.com if (PA_IPR_SPACE(req->paddr)) { 9210234Syasuko.eckert@amd.com // IPR memory space not implemented 9310234Syasuko.eckert@amd.com if (!req->xc->misspeculating()) 9410234Syasuko.eckert@amd.com panic("IPR memory space not implemented! PA=%x\n", req->paddr); 9510234Syasuko.eckert@amd.com } else { 9610234Syasuko.eckert@amd.com // mark request as uncacheable 9710234Syasuko.eckert@amd.com req->flags |= UNCACHEABLE; 9810234Syasuko.eckert@amd.com } 9910152Satgutier@umich.edu } 10010152Satgutier@umich.edu} 10110152Satgutier@umich.edu 102 103// insert a new TLB entry 104void 105AlphaTlb::insert(Addr vaddr, AlphaISA::PTE &pte) 106{ 107 if (table[nlu].valid) { 108 Addr oldvpn = table[nlu].tag; 109 PageTable::iterator i = lookupTable.find(oldvpn); 110 111 if (i == lookupTable.end()) 112 panic("TLB entry not found in lookupTable"); 113 114 int index; 115 while ((index = i->second) != nlu) { 116 if (table[index].tag != oldvpn) 117 panic("TLB entry not found in lookupTable"); 118 119 ++i; 120 } 121 122 DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn); 123 124 lookupTable.erase(i); 125 } 126 127 Addr vpn = VA_VPN(vaddr); 128 DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vpn, pte.ppn); 129 130 table[nlu] = pte; 131 table[nlu].tag = vpn; 132 table[nlu].valid = true; 133 134 lookupTable.insert(make_pair(vpn, nlu)); 135 nextnlu(); 136} 137 138void 139AlphaTlb::flushAll() 140{ 141 memset(table, 0, sizeof(AlphaISA::PTE[size])); 142 lookupTable.clear(); 143 nlu = 0; 144} 145 146void 147AlphaTlb::flushProcesses() 148{ 149 PageTable::iterator i = lookupTable.begin(); 150 PageTable::iterator end = lookupTable.end(); 151 while (i != end) { 152 int index = i->second; 153 AlphaISA::PTE *pte = &table[index]; 154 assert(pte->valid); 155 156 if (!pte->asma) { 157 DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn); 158 pte->valid = false; 159 lookupTable.erase(i); 160 } 161 162 ++i; 163 } 164} 165 166void 167AlphaTlb::flushAddr(Addr vaddr, uint8_t asn) 168{ 169 Addr vpn = VA_VPN(vaddr); 170 171 PageTable::iterator i = lookupTable.find(vpn); 172 if (i == lookupTable.end()) 173 return; 174 175 while (i->first == vpn) { 176 int index = i->second; 177 AlphaISA::PTE *pte = &table[index]; 178 assert(pte->valid); 179 180 if (vpn == pte->tag && (pte->asma || pte->asn == asn)) { 181 DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vpn, pte->ppn); 182 183 // invalidate this entry 184 pte->valid = false; 185 186 lookupTable.erase(i); 187 } 188 189 ++i; 190 } 191} 192 193 194void 195AlphaTlb::serialize(ostream &os) 196{ 197 SERIALIZE_SCALAR(size); 198 SERIALIZE_SCALAR(nlu); 199 200 for (int i = 0; i < size; i++) { 201 nameOut(os, csprintf("%s.PTE%d", name(), i)); 202 table[i].serialize(os); 203 } 204} 205 206void 207AlphaTlb::unserialize(Checkpoint *cp, const string §ion) 208{ 209 UNSERIALIZE_SCALAR(size); 210 UNSERIALIZE_SCALAR(nlu); 211 212 for (int i = 0; i < size; i++) { 213 table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); 214 if (table[i].valid) { 215 lookupTable.insert(make_pair(table[i].tag, i)); 216 } 217 } 218} 219 220 221/////////////////////////////////////////////////////////////////////// 222// 223// Alpha ITB 224// 225AlphaItb::AlphaItb(const std::string &name, int size) 226 : AlphaTlb(name, size) 227{} 228 229 230void 231AlphaItb::regStats() 232{ 233 hits 234 .name(name() + ".hits") 235 .desc("ITB hits"); 236 misses 237 .name(name() + ".misses") 238 .desc("ITB misses"); 239 acv 240 .name(name() + ".acv") 241 .desc("ITB acv"); 242 accesses 243 .name(name() + ".accesses") 244 .desc("ITB accesses"); 245 246 accesses = hits + misses; 247} 248 249void 250AlphaItb::fault(Addr pc, ExecContext *xc) const 251{ 252 uint64_t *ipr = xc->regs.ipr; 253 254 if (!xc->misspeculating()) { 255 ipr[AlphaISA::IPR_ITB_TAG] = pc; 256 ipr[AlphaISA::IPR_IFAULT_VA_FORM] = 257 ipr[AlphaISA::IPR_IVPTBR] | (VA_VPN(pc) << 3); 258 } 259} 260 261 262Fault 263AlphaItb::translate(MemReqPtr req) const 264{ 265 InternalProcReg *ipr = req->xc->regs.ipr; 266 267 if (PC_PAL(req->vaddr)) { 268 // strip off PAL PC marker (lsb is 1) 269 req->paddr = (req->vaddr & ~3) & PA_IMPL_MASK; 270 hits++; 271 return No_Fault; 272 } 273 274 // verify that this is a good virtual address 275 if (!validVirtualAddress(req->vaddr)) { 276 fault(req->vaddr, req->xc); 277 acv++; 278 return Itb_Acv_Fault; 279 } 280 281 // Check for "superpage" mapping: when SP<1> is set, and 282 // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13>. 283 if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && 284 VA_SPACE(req->vaddr) == 2) { 285 // only valid in kernel mode 286 if (ICM_CM(ipr[AlphaISA::IPR_ICM]) != AlphaISA::mode_kernel) { 287 fault(req->vaddr, req->xc); 288 acv++; 289 return Itb_Acv_Fault; 290 } 291 292 req->flags |= PHYSICAL; 293 } 294 295 if (req->flags & PHYSICAL) { 296 req->paddr = req->vaddr & PA_IMPL_MASK; 297 } else { 298 // not a physical address: need to look up pte 299 300 AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr), 301 DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); 302 303 if (!pte) { 304 fault(req->vaddr, req->xc); 305 misses++; 306 return Itb_Fault_Fault; 307 } 308 309 req->paddr = PA_PFN2PA(pte->ppn) + VA_POFS(req->vaddr & ~3); 310 311 // check permissions for this access 312 if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) { 313 // instruction access fault 314 fault(req->vaddr, req->xc); 315 acv++; 316 return Itb_Acv_Fault; 317 } 318 } 319 320 checkCacheability(req); 321 322 hits++; 323 return No_Fault; 324} 325 326/////////////////////////////////////////////////////////////////////// 327// 328// Alpha DTB 329// 330AlphaDtb::AlphaDtb(const std::string &name, int size) 331 : AlphaTlb(name, size) 332{} 333 334void 335AlphaDtb::regStats() 336{ 337 read_hits 338 .name(name() + ".read_hits") 339 .desc("DTB read hits") 340 ; 341 342 read_misses 343 .name(name() + ".read_misses") 344 .desc("DTB read misses") 345 ; 346 347 read_acv 348 .name(name() + ".read_acv") 349 .desc("DTB read access violations") 350 ; 351 352 read_accesses 353 .name(name() + ".read_accesses") 354 .desc("DTB read accesses") 355 ; 356 357 write_hits 358 .name(name() + ".write_hits") 359 .desc("DTB write hits") 360 ; 361 362 write_misses 363 .name(name() + ".write_misses") 364 .desc("DTB write misses") 365 ; 366 367 write_acv 368 .name(name() + ".write_acv") 369 .desc("DTB write access violations") 370 ; 371 372 write_accesses 373 .name(name() + ".write_accesses") 374 .desc("DTB write accesses") 375 ; 376 377 hits 378 .name(name() + ".hits") 379 .desc("DTB hits") 380 ; 381 382 misses 383 .name(name() + ".misses") 384 .desc("DTB misses") 385 ; 386 387 acv 388 .name(name() + ".acv") 389 .desc("DTB access violations") 390 ; 391 392 accesses 393 .name(name() + ".accesses") 394 .desc("DTB accesses") 395 ; 396 397 hits = read_hits + write_hits; 398 misses = read_misses + write_misses; 399 acv = read_acv + write_acv; 400 accesses = read_accesses + write_accesses; 401} 402 403void 404AlphaDtb::fault(Addr vaddr, uint64_t flags, ExecContext *xc) const 405{ 406 uint64_t *ipr = xc->regs.ipr; 407 408 // set fault address and flags 409 if (!xc->misspeculating() && !xc->regs.intrlock) { 410 // set VA register with faulting address 411 ipr[AlphaISA::IPR_VA] = vaddr; 412 413 // set MM_STAT register flags 414 ipr[AlphaISA::IPR_MM_STAT] = (((xc->regs.opcode & 0x3f) << 11) 415 | ((xc->regs.ra & 0x1f) << 6) 416 | (flags & 0x3f)); 417 418 // set VA_FORM register with faulting formatted address 419 ipr[AlphaISA::IPR_VA_FORM] = 420 ipr[AlphaISA::IPR_MVPTBR] | (VA_VPN(vaddr) << 3); 421 422 // lock these registers until the VA register is read 423 xc->regs.intrlock = true; 424 } 425} 426 427Fault 428AlphaDtb::translate(MemReqPtr req, bool write) const 429{ 430 RegFile *regs = &req->xc->regs; 431 Addr pc = regs->pc; 432 InternalProcReg *ipr = regs->ipr; 433 434 if (write) 435 write_accesses++; 436 else 437 read_accesses++; 438 439 AlphaISA::md_mode_type mode = 440 (AlphaISA::md_mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]); 441 442 if (PC_PAL(pc)) { 443 mode = (req->flags & ALTMODE) ? (AlphaISA::md_mode_type) 444 (ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE])) 445 : AlphaISA::mode_kernel; 446 } 447 448 // verify that this is a good virtual address 449 if (!validVirtualAddress(req->vaddr)) { 450 fault(req->vaddr, 451 ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_BAD_VA_MASK | 452 MM_STAT_ACV_MASK), 453 req->xc); 454 455 if (write) { write_acv++; } else { read_acv++; } 456 return Dtb_Fault_Fault; 457 } 458 459 // Check for "superpage" mapping: when SP<1> is set, and 460 // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13>. 461 if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) && VA_SPACE(req->vaddr) == 2) { 462 // only valid in kernel mode 463 if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) != AlphaISA::mode_kernel) { 464 fault(req->vaddr, 465 ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_ACV_MASK), 466 req->xc); 467 if (write) { write_acv++; } else { read_acv++; } 468 return Dtb_Acv_Fault; 469 } 470 471 req->flags |= PHYSICAL; 472 } 473 474 if (req->flags & PHYSICAL) { 475 req->paddr = req->vaddr & PA_IMPL_MASK; 476 } else { 477 // not a physical address: need to look up pte 478 479 AlphaISA::PTE *pte = lookup(VA_VPN(req->vaddr), 480 DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN])); 481 482 if (!pte) { 483 // page fault 484 fault(req->vaddr, 485 ((write ? MM_STAT_WR_MASK : 0) | MM_STAT_DTB_MISS_MASK), 486 req->xc); 487 if (write) { write_misses++; } else { read_misses++; } 488 return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault; 489 } 490 491 req->paddr = PA_PFN2PA(pte->ppn) | VA_POFS(req->vaddr); 492 493 if (write) { 494 if (!(pte->xwe & MODE2MASK(mode))) { 495 // declare the instruction access fault 496 fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_ACV_MASK | 497 (pte->fonw ? MM_STAT_FONW_MASK : 0), 498 req->xc); 499 write_acv++; 500 return Dtb_Fault_Fault; 501 } 502 if (pte->fonw) { 503 fault(req->vaddr, MM_STAT_WR_MASK | MM_STAT_FONW_MASK, 504 req->xc); 505 write_acv++; 506 return Dtb_Fault_Fault; 507 } 508 } else { 509 if (!(pte->xre & MODE2MASK(mode))) { 510 fault(req->vaddr, 511 MM_STAT_ACV_MASK | (pte->fonr ? MM_STAT_FONR_MASK : 0), 512 req->xc); 513 read_acv++; 514 return Dtb_Acv_Fault; 515 } 516 if (pte->fonr) { 517 fault(req->vaddr, MM_STAT_FONR_MASK, req->xc); 518 read_acv++; 519 return Dtb_Fault_Fault; 520 } 521 } 522 } 523 524 checkCacheability(req); 525 526 if (write) 527 write_hits++; 528 else 529 read_hits++; 530 531 return No_Fault; 532} 533 534AlphaISA::PTE & 535AlphaTlb::index() 536{ 537 AlphaISA::PTE *pte = &table[nlu]; 538 nextnlu(); 539 540 return *pte; 541} 542 543BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaItb) 544 545 Param<int> size; 546 547END_DECLARE_SIM_OBJECT_PARAMS(AlphaItb) 548 549BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaItb) 550 551 INIT_PARAM_DFLT(size, "TLB size", 48) 552 553END_INIT_SIM_OBJECT_PARAMS(AlphaItb) 554 555 556CREATE_SIM_OBJECT(AlphaItb) 557{ 558 return new AlphaItb(getInstanceName(), size); 559} 560 561REGISTER_SIM_OBJECT("AlphaITB", AlphaItb) 562 563BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDtb) 564 565 Param<int> size; 566 567END_DECLARE_SIM_OBJECT_PARAMS(AlphaDtb) 568 569BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDtb) 570 571 INIT_PARAM_DFLT(size, "TLB size", 64) 572 573END_INIT_SIM_OBJECT_PARAMS(AlphaDtb) 574 575 576CREATE_SIM_OBJECT(AlphaDtb) 577{ 578 return new AlphaDtb(getInstanceName(), size); 579} 580 581REGISTER_SIM_OBJECT("AlphaDTB", AlphaDtb) 582 583