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