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