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