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