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