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