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