table_walker.cc revision 8832:247fee427324
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 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Ali Saidi 38 */ 39 40#include "arch/arm/faults.hh" 41#include "arch/arm/table_walker.hh" 42#include "arch/arm/tlb.hh" 43#include "cpu/base.hh" 44#include "cpu/thread_context.hh" 45#include "debug/Checkpoint.hh" 46#include "debug/TLB.hh" 47#include "debug/TLBVerbose.hh" 48#include "dev/io_device.hh" 49#include "sim/system.hh" 50 51using namespace ArmISA; 52 53TableWalker::TableWalker(const Params *p) 54 : MemObject(p), port(NULL), tlb(NULL), currState(NULL), pending(false), 55 masterId(p->sys->getMasterId(name())), 56 doL1DescEvent(this), doL2DescEvent(this), doProcessEvent(this) 57{ 58 sctlr = 0; 59} 60 61TableWalker::~TableWalker() 62{ 63 ; 64} 65 66unsigned int 67TableWalker::drain(Event *de) 68{ 69 if (stateQueueL1.size() || stateQueueL2.size() || pendingQueue.size()) 70 { 71 changeState(Draining); 72 DPRINTF(Checkpoint, "TableWalker busy, wait to drain\n"); 73 return 1; 74 } 75 else 76 { 77 changeState(Drained); 78 DPRINTF(Checkpoint, "TableWalker free, no need to drain\n"); 79 return 0; 80 } 81} 82 83void 84TableWalker::resume() 85{ 86 MemObject::resume(); 87 if ((params()->sys->getMemoryMode() == Enums::timing) && currState) { 88 delete currState; 89 currState = NULL; 90 } 91} 92 93Port* 94TableWalker::getPort(const std::string &if_name, int idx) 95{ 96 if (if_name == "port") { 97 if (port != NULL) 98 return port; 99 System *sys = params()->sys; 100 Tick minb = params()->min_backoff; 101 Tick maxb = params()->max_backoff; 102 port = new DmaPort(this, sys, minb, maxb, true); 103 return port; 104 } 105 return NULL; 106} 107 108Fault 109TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode, 110 TLB::Translation *_trans, bool _timing, bool _functional) 111{ 112 assert(!(_functional && _timing)); 113 if (!currState) { 114 // For atomic mode, a new WalkerState instance should be only created 115 // once per TLB. For timing mode, a new instance is generated for every 116 // TLB miss. 117 DPRINTF(TLBVerbose, "creating new instance of WalkerState\n"); 118 119 currState = new WalkerState(); 120 currState->tableWalker = this; 121 } else if (_timing) { 122 // This is a translation that was completed and then faulted again 123 // because some underlying parameters that affect the translation 124 // changed out from under us (e.g. asid). It will either be a 125 // misprediction, in which case nothing will happen or we'll use 126 // this fault to re-execute the faulting instruction which should clean 127 // up everything. 128 if (currState->vaddr == _req->getVaddr()) { 129 return new ReExec; 130 } 131 panic("currState should always be empty in timing mode!\n"); 132 } 133 134 currState->tc = _tc; 135 currState->transState = _trans; 136 currState->req = _req; 137 currState->fault = NoFault; 138 currState->contextId = _cid; 139 currState->timing = _timing; 140 currState->functional = _functional; 141 currState->mode = _mode; 142 143 /** @todo These should be cached or grabbed from cached copies in 144 the TLB, all these miscreg reads are expensive */ 145 currState->vaddr = currState->req->getVaddr(); 146 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR); 147 sctlr = currState->sctlr; 148 currState->N = currState->tc->readMiscReg(MISCREG_TTBCR); 149 150 currState->isFetch = (currState->mode == TLB::Execute); 151 currState->isWrite = (currState->mode == TLB::Write); 152 153 154 if (!currState->timing) 155 return processWalk(); 156 157 if (pending || pendingQueue.size()) { 158 pendingQueue.push_back(currState); 159 currState = NULL; 160 } else { 161 pending = true; 162 return processWalk(); 163 } 164 165 return NoFault; 166} 167 168void 169TableWalker::processWalkWrapper() 170{ 171 assert(!currState); 172 assert(pendingQueue.size()); 173 currState = pendingQueue.front(); 174 pendingQueue.pop_front(); 175 pending = true; 176 processWalk(); 177} 178 179Fault 180TableWalker::processWalk() 181{ 182 Addr ttbr = 0; 183 184 // If translation isn't enabled, we shouldn't be here 185 assert(currState->sctlr.m); 186 187 DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n", 188 currState->vaddr, currState->N, mbits(currState->vaddr, 31, 189 32-currState->N)); 190 191 if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) { 192 DPRINTF(TLB, " - Selecting TTBR0\n"); 193 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0); 194 } else { 195 DPRINTF(TLB, " - Selecting TTBR1\n"); 196 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1); 197 currState->N = 0; 198 } 199 200 Addr l1desc_addr = mbits(ttbr, 31, 14-currState->N) | 201 (bits(currState->vaddr,31-currState->N,20) << 2); 202 DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr); 203 204 205 // Trickbox address check 206 Fault f; 207 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t), 208 currState->isFetch, currState->isWrite, 0, true); 209 if (f) { 210 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr); 211 if (currState->timing) { 212 pending = false; 213 nextWalk(currState->tc); 214 currState = NULL; 215 } else { 216 currState->tc = NULL; 217 currState->req = NULL; 218 } 219 return f; 220 } 221 222 Request::Flags flag = 0; 223 if (currState->sctlr.c == 0) { 224 flag = Request::UNCACHEABLE; 225 } 226 227 if (currState->timing) { 228 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), 229 &doL1DescEvent, (uint8_t*)&currState->l1Desc.data, 230 currState->tc->getCpuPtr()->ticks(1), flag); 231 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n", 232 stateQueueL1.size()); 233 stateQueueL1.push_back(currState); 234 currState = NULL; 235 } else if (!currState->functional) { 236 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), 237 NULL, (uint8_t*)&currState->l1Desc.data, 238 currState->tc->getCpuPtr()->ticks(1), flag); 239 doL1Descriptor(); 240 f = currState->fault; 241 } else { 242 RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag, masterId); 243 PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast); 244 pkt->dataStatic((uint8_t*)&currState->l1Desc.data); 245 port->sendFunctional(pkt); 246 doL1Descriptor(); 247 delete req; 248 delete pkt; 249 f = currState->fault; 250 } 251 252 return f; 253} 254 255void 256TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, 257 uint8_t texcb, bool s) 258{ 259 // Note: tc and sctlr local variables are hiding tc and sctrl class 260 // variables 261 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s); 262 te.shareable = false; // default value 263 te.nonCacheable = false; 264 bool outer_shareable = false; 265 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) { 266 switch(texcb) { 267 case 0: // Stongly-ordered 268 te.nonCacheable = true; 269 te.mtype = TlbEntry::StronglyOrdered; 270 te.shareable = true; 271 te.innerAttrs = 1; 272 te.outerAttrs = 0; 273 break; 274 case 1: // Shareable Device 275 te.nonCacheable = true; 276 te.mtype = TlbEntry::Device; 277 te.shareable = true; 278 te.innerAttrs = 3; 279 te.outerAttrs = 0; 280 break; 281 case 2: // Outer and Inner Write-Through, no Write-Allocate 282 te.mtype = TlbEntry::Normal; 283 te.shareable = s; 284 te.innerAttrs = 6; 285 te.outerAttrs = bits(texcb, 1, 0); 286 break; 287 case 3: // Outer and Inner Write-Back, no Write-Allocate 288 te.mtype = TlbEntry::Normal; 289 te.shareable = s; 290 te.innerAttrs = 7; 291 te.outerAttrs = bits(texcb, 1, 0); 292 break; 293 case 4: // Outer and Inner Non-cacheable 294 te.nonCacheable = true; 295 te.mtype = TlbEntry::Normal; 296 te.shareable = s; 297 te.innerAttrs = 0; 298 te.outerAttrs = bits(texcb, 1, 0); 299 break; 300 case 5: // Reserved 301 panic("Reserved texcb value!\n"); 302 break; 303 case 6: // Implementation Defined 304 panic("Implementation-defined texcb value!\n"); 305 break; 306 case 7: // Outer and Inner Write-Back, Write-Allocate 307 te.mtype = TlbEntry::Normal; 308 te.shareable = s; 309 te.innerAttrs = 5; 310 te.outerAttrs = 1; 311 break; 312 case 8: // Non-shareable Device 313 te.nonCacheable = true; 314 te.mtype = TlbEntry::Device; 315 te.shareable = false; 316 te.innerAttrs = 3; 317 te.outerAttrs = 0; 318 break; 319 case 9 ... 15: // Reserved 320 panic("Reserved texcb value!\n"); 321 break; 322 case 16 ... 31: // Cacheable Memory 323 te.mtype = TlbEntry::Normal; 324 te.shareable = s; 325 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0) 326 te.nonCacheable = true; 327 te.innerAttrs = bits(texcb, 1, 0); 328 te.outerAttrs = bits(texcb, 3, 2); 329 break; 330 default: 331 panic("More than 32 states for 5 bits?\n"); 332 } 333 } else { 334 assert(tc); 335 PRRR prrr = tc->readMiscReg(MISCREG_PRRR); 336 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR); 337 DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr); 338 uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0; 339 switch(bits(texcb, 2,0)) { 340 case 0: 341 curr_tr = prrr.tr0; 342 curr_ir = nmrr.ir0; 343 curr_or = nmrr.or0; 344 outer_shareable = (prrr.nos0 == 0); 345 break; 346 case 1: 347 curr_tr = prrr.tr1; 348 curr_ir = nmrr.ir1; 349 curr_or = nmrr.or1; 350 outer_shareable = (prrr.nos1 == 0); 351 break; 352 case 2: 353 curr_tr = prrr.tr2; 354 curr_ir = nmrr.ir2; 355 curr_or = nmrr.or2; 356 outer_shareable = (prrr.nos2 == 0); 357 break; 358 case 3: 359 curr_tr = prrr.tr3; 360 curr_ir = nmrr.ir3; 361 curr_or = nmrr.or3; 362 outer_shareable = (prrr.nos3 == 0); 363 break; 364 case 4: 365 curr_tr = prrr.tr4; 366 curr_ir = nmrr.ir4; 367 curr_or = nmrr.or4; 368 outer_shareable = (prrr.nos4 == 0); 369 break; 370 case 5: 371 curr_tr = prrr.tr5; 372 curr_ir = nmrr.ir5; 373 curr_or = nmrr.or5; 374 outer_shareable = (prrr.nos5 == 0); 375 break; 376 case 6: 377 panic("Imp defined type\n"); 378 case 7: 379 curr_tr = prrr.tr7; 380 curr_ir = nmrr.ir7; 381 curr_or = nmrr.or7; 382 outer_shareable = (prrr.nos7 == 0); 383 break; 384 } 385 386 switch(curr_tr) { 387 case 0: 388 DPRINTF(TLBVerbose, "StronglyOrdered\n"); 389 te.mtype = TlbEntry::StronglyOrdered; 390 te.nonCacheable = true; 391 te.innerAttrs = 1; 392 te.outerAttrs = 0; 393 te.shareable = true; 394 break; 395 case 1: 396 DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n", 397 prrr.ds1, prrr.ds0, s); 398 te.mtype = TlbEntry::Device; 399 te.nonCacheable = true; 400 te.innerAttrs = 3; 401 te.outerAttrs = 0; 402 if (prrr.ds1 && s) 403 te.shareable = true; 404 if (prrr.ds0 && !s) 405 te.shareable = true; 406 break; 407 case 2: 408 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n", 409 prrr.ns1, prrr.ns0, s); 410 te.mtype = TlbEntry::Normal; 411 if (prrr.ns1 && s) 412 te.shareable = true; 413 if (prrr.ns0 && !s) 414 te.shareable = true; 415 break; 416 case 3: 417 panic("Reserved type"); 418 } 419 420 if (te.mtype == TlbEntry::Normal){ 421 switch(curr_ir) { 422 case 0: 423 te.nonCacheable = true; 424 te.innerAttrs = 0; 425 break; 426 case 1: 427 te.innerAttrs = 5; 428 break; 429 case 2: 430 te.innerAttrs = 6; 431 break; 432 case 3: 433 te.innerAttrs = 7; 434 break; 435 } 436 437 switch(curr_or) { 438 case 0: 439 te.nonCacheable = true; 440 te.outerAttrs = 0; 441 break; 442 case 1: 443 te.outerAttrs = 1; 444 break; 445 case 2: 446 te.outerAttrs = 2; 447 break; 448 case 3: 449 te.outerAttrs = 3; 450 break; 451 } 452 } 453 } 454 DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \ 455 outerAttrs: %d\n", 456 te.shareable, te.innerAttrs, te.outerAttrs); 457 458 /** Formatting for Physical Address Register (PAR) 459 * Only including lower bits (TLB info here) 460 * PAR: 461 * PA [31:12] 462 * Reserved [11] 463 * TLB info [10:1] 464 * NOS [10] (Not Outer Sharable) 465 * NS [9] (Non-Secure) 466 * -- [8] (Implementation Defined) 467 * SH [7] (Sharable) 468 * Inner[6:4](Inner memory attributes) 469 * Outer[3:2](Outer memory attributes) 470 * SS [1] (SuperSection) 471 * F [0] (Fault, Fault Status in [6:1] if faulted) 472 */ 473 te.attributes = ( 474 ((outer_shareable ? 0:1) << 10) | 475 // TODO: NS Bit 476 ((te.shareable ? 1:0) << 7) | 477 (te.innerAttrs << 4) | 478 (te.outerAttrs << 2) 479 // TODO: Supersection bit 480 // TODO: Fault bit 481 ); 482 483 484} 485 486void 487TableWalker::doL1Descriptor() 488{ 489 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", 490 currState->vaddr, currState->l1Desc.data); 491 TlbEntry te; 492 493 switch (currState->l1Desc.type()) { 494 case L1Descriptor::Ignore: 495 case L1Descriptor::Reserved: 496 if (!currState->timing) { 497 currState->tc = NULL; 498 currState->req = NULL; 499 } 500 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n"); 501 if (currState->isFetch) 502 currState->fault = 503 new PrefetchAbort(currState->vaddr, ArmFault::Translation0); 504 else 505 currState->fault = 506 new DataAbort(currState->vaddr, 0, currState->isWrite, 507 ArmFault::Translation0); 508 return; 509 case L1Descriptor::Section: 510 if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) { 511 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is 512 * enabled if set, do l1.Desc.setAp0() instead of generating 513 * AccessFlag0 514 */ 515 516 currState->fault = new DataAbort(currState->vaddr, 517 currState->l1Desc.domain(), currState->isWrite, 518 ArmFault::AccessFlag0); 519 } 520 if (currState->l1Desc.supersection()) { 521 panic("Haven't implemented supersections\n"); 522 } 523 te.N = 20; 524 te.pfn = currState->l1Desc.pfn(); 525 te.size = (1<<te.N) - 1; 526 te.global = !currState->l1Desc.global(); 527 te.valid = true; 528 te.vpn = currState->vaddr >> te.N; 529 te.sNp = true; 530 te.xn = currState->l1Desc.xn(); 531 te.ap = currState->l1Desc.ap(); 532 te.domain = currState->l1Desc.domain(); 533 te.asid = currState->contextId; 534 memAttrs(currState->tc, te, currState->sctlr, 535 currState->l1Desc.texcb(), currState->l1Desc.shareable()); 536 537 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n"); 538 DPRINTF(TLB, " - N:%d pfn:%#x size: %#x global:%d valid: %d\n", 539 te.N, te.pfn, te.size, te.global, te.valid); 540 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d nc:%d\n", 541 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid, 542 te.nonCacheable); 543 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n", 544 currState->l1Desc.domain(), currState->l1Desc.data, 545 (currState->l1Desc.data >> 5) & 0xF ); 546 547 if (!currState->timing) { 548 currState->tc = NULL; 549 currState->req = NULL; 550 } 551 tlb->insert(currState->vaddr, te); 552 553 return; 554 case L1Descriptor::PageTable: 555 Addr l2desc_addr; 556 l2desc_addr = currState->l1Desc.l2Addr() | 557 (bits(currState->vaddr, 19,12) << 2); 558 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n", 559 l2desc_addr); 560 561 // Trickbox address check 562 currState->fault = tlb->walkTrickBoxCheck(l2desc_addr, currState->vaddr, 563 sizeof(uint32_t), currState->isFetch, currState->isWrite, 564 currState->l1Desc.domain(), false); 565 566 if (currState->fault) { 567 if (!currState->timing) { 568 currState->tc = NULL; 569 currState->req = NULL; 570 } 571 return; 572 } 573 574 575 if (currState->timing) { 576 currState->delayed = true; 577 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), 578 &doL2DescEvent, (uint8_t*)&currState->l2Desc.data, 579 currState->tc->getCpuPtr()->ticks(1)); 580 } else if (!currState->functional) { 581 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), 582 NULL, (uint8_t*)&currState->l2Desc.data, 583 currState->tc->getCpuPtr()->ticks(1)); 584 doL2Descriptor(); 585 } else { 586 RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0, masterId); 587 PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast); 588 pkt->dataStatic((uint8_t*)&currState->l2Desc.data); 589 port->sendFunctional(pkt); 590 doL2Descriptor(); 591 delete req; 592 delete pkt; 593 } 594 return; 595 default: 596 panic("A new type in a 2 bit field?\n"); 597 } 598} 599 600void 601TableWalker::doL2Descriptor() 602{ 603 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", 604 currState->vaddr, currState->l2Desc.data); 605 TlbEntry te; 606 607 if (currState->l2Desc.invalid()) { 608 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n"); 609 if (!currState->timing) { 610 currState->tc = NULL; 611 currState->req = NULL; 612 } 613 if (currState->isFetch) 614 currState->fault = 615 new PrefetchAbort(currState->vaddr, ArmFault::Translation1); 616 else 617 currState->fault = 618 new DataAbort(currState->vaddr, currState->l1Desc.domain(), 619 currState->isWrite, ArmFault::Translation1); 620 return; 621 } 622 623 if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) { 624 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled 625 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0 626 */ 627 628 currState->fault = 629 new DataAbort(currState->vaddr, 0, currState->isWrite, 630 ArmFault::AccessFlag1); 631 632 } 633 634 if (currState->l2Desc.large()) { 635 te.N = 16; 636 te.pfn = currState->l2Desc.pfn(); 637 } else { 638 te.N = 12; 639 te.pfn = currState->l2Desc.pfn(); 640 } 641 642 te.valid = true; 643 te.size = (1 << te.N) - 1; 644 te.asid = currState->contextId; 645 te.sNp = false; 646 te.vpn = currState->vaddr >> te.N; 647 te.global = currState->l2Desc.global(); 648 te.xn = currState->l2Desc.xn(); 649 te.ap = currState->l2Desc.ap(); 650 te.domain = currState->l1Desc.domain(); 651 memAttrs(currState->tc, te, currState->sctlr, currState->l2Desc.texcb(), 652 currState->l2Desc.shareable()); 653 654 if (!currState->timing) { 655 currState->tc = NULL; 656 currState->req = NULL; 657 } 658 tlb->insert(currState->vaddr, te); 659} 660 661void 662TableWalker::doL1DescriptorWrapper() 663{ 664 currState = stateQueueL1.front(); 665 currState->delayed = false; 666 667 DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data); 668 DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data); 669 670 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr); 671 doL1Descriptor(); 672 673 stateQueueL1.pop_front(); 674 // Check if fault was generated 675 if (currState->fault != NoFault) { 676 currState->transState->finish(currState->fault, currState->req, 677 currState->tc, currState->mode); 678 679 pending = false; 680 nextWalk(currState->tc); 681 682 currState->req = NULL; 683 currState->tc = NULL; 684 currState->delayed = false; 685 delete currState; 686 } 687 else if (!currState->delayed) { 688 // delay is not set so there is no L2 to do 689 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 690 currState->fault = tlb->translateTiming(currState->req, currState->tc, 691 currState->transState, currState->mode); 692 693 pending = false; 694 nextWalk(currState->tc); 695 696 currState->req = NULL; 697 currState->tc = NULL; 698 currState->delayed = false; 699 delete currState; 700 } else { 701 // need to do L2 descriptor 702 stateQueueL2.push_back(currState); 703 } 704 currState = NULL; 705} 706 707void 708TableWalker::doL2DescriptorWrapper() 709{ 710 currState = stateQueueL2.front(); 711 assert(currState->delayed); 712 713 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n", 714 currState->vaddr); 715 doL2Descriptor(); 716 717 // Check if fault was generated 718 if (currState->fault != NoFault) { 719 currState->transState->finish(currState->fault, currState->req, 720 currState->tc, currState->mode); 721 } 722 else { 723 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 724 currState->fault = tlb->translateTiming(currState->req, currState->tc, 725 currState->transState, currState->mode); 726 } 727 728 729 stateQueueL2.pop_front(); 730 pending = false; 731 nextWalk(currState->tc); 732 733 currState->req = NULL; 734 currState->tc = NULL; 735 currState->delayed = false; 736 737 delete currState; 738 currState = NULL; 739} 740 741void 742TableWalker::nextWalk(ThreadContext *tc) 743{ 744 if (pendingQueue.size()) 745 schedule(doProcessEvent, tc->getCpuPtr()->nextCycle(curTick()+1)); 746} 747 748 749 750ArmISA::TableWalker * 751ArmTableWalkerParams::create() 752{ 753 return new ArmISA::TableWalker(this); 754} 755 756