228} 229 230Fault 231TableWalker::processWalk() 232{ 233 Addr ttbr = 0; 234 235 // If translation isn't enabled, we shouldn't be here 236 assert(currState->sctlr.m); 237 238 DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n", 239 currState->vaddr, currState->N, mbits(currState->vaddr, 31, 240 32-currState->N)); 241 242 if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) { 243 DPRINTF(TLB, " - Selecting TTBR0\n"); 244 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0); 245 } else { 246 DPRINTF(TLB, " - Selecting TTBR1\n"); 247 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1); 248 currState->N = 0; 249 } 250 251 Addr l1desc_addr = mbits(ttbr, 31, 14-currState->N) | 252 (bits(currState->vaddr,31-currState->N,20) << 2); 253 DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr); 254 255 256 // Trickbox address check 257 Fault f; 258 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t), 259 currState->isFetch, currState->isWrite, 0, true); 260 if (f) { 261 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr); 262 if (currState->timing) { 263 pending = false; 264 nextWalk(currState->tc); 265 currState = NULL; 266 } else { 267 currState->tc = NULL; 268 currState->req = NULL; 269 } 270 return f; 271 } 272 273 Request::Flags flag = 0; 274 if (currState->sctlr.c == 0) { 275 flag = Request::UNCACHEABLE; 276 } 277 278 if (currState->timing) { 279 port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), 280 &doL1DescEvent, (uint8_t*)&currState->l1Desc.data, 281 currState->tc->getCpuPtr()->clockPeriod(), flag); 282 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before " 283 "adding: %d\n", 284 stateQueueL1.size()); 285 stateQueueL1.push_back(currState); 286 currState = NULL; 287 } else if (!currState->functional) { 288 port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), 289 NULL, (uint8_t*)&currState->l1Desc.data, 290 currState->tc->getCpuPtr()->clockPeriod(), flag); 291 doL1Descriptor(); 292 f = currState->fault; 293 } else { 294 RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag, masterId); 295 PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 296 pkt->dataStatic((uint8_t*)&currState->l1Desc.data); 297 port.sendFunctional(pkt); 298 doL1Descriptor(); 299 delete req; 300 delete pkt; 301 f = currState->fault; 302 } 303 304 return f; 305} 306 307void 308TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, 309 uint8_t texcb, bool s) 310{ 311 // Note: tc and sctlr local variables are hiding tc and sctrl class 312 // variables 313 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s); 314 te.shareable = false; // default value 315 te.nonCacheable = false; 316 bool outer_shareable = false; 317 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) { 318 switch(texcb) { 319 case 0: // Stongly-ordered 320 te.nonCacheable = true; 321 te.mtype = TlbEntry::StronglyOrdered; 322 te.shareable = true; 323 te.innerAttrs = 1; 324 te.outerAttrs = 0; 325 break; 326 case 1: // Shareable Device 327 te.nonCacheable = true; 328 te.mtype = TlbEntry::Device; 329 te.shareable = true; 330 te.innerAttrs = 3; 331 te.outerAttrs = 0; 332 break; 333 case 2: // Outer and Inner Write-Through, no Write-Allocate 334 te.mtype = TlbEntry::Normal; 335 te.shareable = s; 336 te.innerAttrs = 6; 337 te.outerAttrs = bits(texcb, 1, 0); 338 break; 339 case 3: // Outer and Inner Write-Back, no Write-Allocate 340 te.mtype = TlbEntry::Normal; 341 te.shareable = s; 342 te.innerAttrs = 7; 343 te.outerAttrs = bits(texcb, 1, 0); 344 break; 345 case 4: // Outer and Inner Non-cacheable 346 te.nonCacheable = true; 347 te.mtype = TlbEntry::Normal; 348 te.shareable = s; 349 te.innerAttrs = 0; 350 te.outerAttrs = bits(texcb, 1, 0); 351 break; 352 case 5: // Reserved 353 panic("Reserved texcb value!\n"); 354 break; 355 case 6: // Implementation Defined 356 panic("Implementation-defined texcb value!\n"); 357 break; 358 case 7: // Outer and Inner Write-Back, Write-Allocate 359 te.mtype = TlbEntry::Normal; 360 te.shareable = s; 361 te.innerAttrs = 5; 362 te.outerAttrs = 1; 363 break; 364 case 8: // Non-shareable Device 365 te.nonCacheable = true; 366 te.mtype = TlbEntry::Device; 367 te.shareable = false; 368 te.innerAttrs = 3; 369 te.outerAttrs = 0; 370 break; 371 case 9 ... 15: // Reserved 372 panic("Reserved texcb value!\n"); 373 break; 374 case 16 ... 31: // Cacheable Memory 375 te.mtype = TlbEntry::Normal; 376 te.shareable = s; 377 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0) 378 te.nonCacheable = true; 379 te.innerAttrs = bits(texcb, 1, 0); 380 te.outerAttrs = bits(texcb, 3, 2); 381 break; 382 default: 383 panic("More than 32 states for 5 bits?\n"); 384 } 385 } else { 386 assert(tc); 387 PRRR prrr = tc->readMiscReg(MISCREG_PRRR); 388 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR); 389 DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr); 390 uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0; 391 switch(bits(texcb, 2,0)) { 392 case 0: 393 curr_tr = prrr.tr0; 394 curr_ir = nmrr.ir0; 395 curr_or = nmrr.or0; 396 outer_shareable = (prrr.nos0 == 0); 397 break; 398 case 1: 399 curr_tr = prrr.tr1; 400 curr_ir = nmrr.ir1; 401 curr_or = nmrr.or1; 402 outer_shareable = (prrr.nos1 == 0); 403 break; 404 case 2: 405 curr_tr = prrr.tr2; 406 curr_ir = nmrr.ir2; 407 curr_or = nmrr.or2; 408 outer_shareable = (prrr.nos2 == 0); 409 break; 410 case 3: 411 curr_tr = prrr.tr3; 412 curr_ir = nmrr.ir3; 413 curr_or = nmrr.or3; 414 outer_shareable = (prrr.nos3 == 0); 415 break; 416 case 4: 417 curr_tr = prrr.tr4; 418 curr_ir = nmrr.ir4; 419 curr_or = nmrr.or4; 420 outer_shareable = (prrr.nos4 == 0); 421 break; 422 case 5: 423 curr_tr = prrr.tr5; 424 curr_ir = nmrr.ir5; 425 curr_or = nmrr.or5; 426 outer_shareable = (prrr.nos5 == 0); 427 break; 428 case 6: 429 panic("Imp defined type\n"); 430 case 7: 431 curr_tr = prrr.tr7; 432 curr_ir = nmrr.ir7; 433 curr_or = nmrr.or7; 434 outer_shareable = (prrr.nos7 == 0); 435 break; 436 } 437 438 switch(curr_tr) { 439 case 0: 440 DPRINTF(TLBVerbose, "StronglyOrdered\n"); 441 te.mtype = TlbEntry::StronglyOrdered; 442 te.nonCacheable = true; 443 te.innerAttrs = 1; 444 te.outerAttrs = 0; 445 te.shareable = true; 446 break; 447 case 1: 448 DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n", 449 prrr.ds1, prrr.ds0, s); 450 te.mtype = TlbEntry::Device; 451 te.nonCacheable = true; 452 te.innerAttrs = 3; 453 te.outerAttrs = 0; 454 if (prrr.ds1 && s) 455 te.shareable = true; 456 if (prrr.ds0 && !s) 457 te.shareable = true; 458 break; 459 case 2: 460 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n", 461 prrr.ns1, prrr.ns0, s); 462 te.mtype = TlbEntry::Normal; 463 if (prrr.ns1 && s) 464 te.shareable = true; 465 if (prrr.ns0 && !s) 466 te.shareable = true; 467 break; 468 case 3: 469 panic("Reserved type"); 470 } 471 472 if (te.mtype == TlbEntry::Normal){ 473 switch(curr_ir) { 474 case 0: 475 te.nonCacheable = true; 476 te.innerAttrs = 0; 477 break; 478 case 1: 479 te.innerAttrs = 5; 480 break; 481 case 2: 482 te.innerAttrs = 6; 483 break; 484 case 3: 485 te.innerAttrs = 7; 486 break; 487 } 488 489 switch(curr_or) { 490 case 0: 491 te.nonCacheable = true; 492 te.outerAttrs = 0; 493 break; 494 case 1: 495 te.outerAttrs = 1; 496 break; 497 case 2: 498 te.outerAttrs = 2; 499 break; 500 case 3: 501 te.outerAttrs = 3; 502 break; 503 } 504 } 505 } 506 DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \ 507 outerAttrs: %d\n", 508 te.shareable, te.innerAttrs, te.outerAttrs); 509 510 /** Formatting for Physical Address Register (PAR) 511 * Only including lower bits (TLB info here) 512 * PAR: 513 * PA [31:12] 514 * Reserved [11] 515 * TLB info [10:1] 516 * NOS [10] (Not Outer Sharable) 517 * NS [9] (Non-Secure) 518 * -- [8] (Implementation Defined) 519 * SH [7] (Sharable) 520 * Inner[6:4](Inner memory attributes) 521 * Outer[3:2](Outer memory attributes) 522 * SS [1] (SuperSection) 523 * F [0] (Fault, Fault Status in [6:1] if faulted) 524 */ 525 te.attributes = ( 526 ((outer_shareable ? 0:1) << 10) | 527 // TODO: NS Bit 528 ((te.shareable ? 1:0) << 7) | 529 (te.innerAttrs << 4) | 530 (te.outerAttrs << 2) 531 // TODO: Supersection bit 532 // TODO: Fault bit 533 ); 534 535 536} 537 538void 539TableWalker::doL1Descriptor() 540{ 541 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", 542 currState->vaddr, currState->l1Desc.data); 543 TlbEntry te; 544 545 switch (currState->l1Desc.type()) { 546 case L1Descriptor::Ignore: 547 case L1Descriptor::Reserved: 548 if (!currState->timing) { 549 currState->tc = NULL; 550 currState->req = NULL; 551 } 552 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n"); 553 if (currState->isFetch) 554 currState->fault = 555 new PrefetchAbort(currState->vaddr, ArmFault::Translation0); 556 else 557 currState->fault = 558 new DataAbort(currState->vaddr, 0, currState->isWrite, 559 ArmFault::Translation0); 560 return; 561 case L1Descriptor::Section: 562 if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) { 563 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is 564 * enabled if set, do l1.Desc.setAp0() instead of generating 565 * AccessFlag0 566 */ 567 568 currState->fault = new DataAbort(currState->vaddr, 569 currState->l1Desc.domain(), currState->isWrite, 570 ArmFault::AccessFlag0); 571 } 572 if (currState->l1Desc.supersection()) { 573 panic("Haven't implemented supersections\n"); 574 } 575 te.N = 20; 576 te.pfn = currState->l1Desc.pfn(); 577 te.size = (1<<te.N) - 1; 578 te.global = !currState->l1Desc.global(); 579 te.valid = true; 580 te.vpn = currState->vaddr >> te.N; 581 te.sNp = true; 582 te.xn = currState->l1Desc.xn(); 583 te.ap = currState->l1Desc.ap(); 584 te.domain = currState->l1Desc.domain(); 585 te.asid = currState->contextId; 586 memAttrs(currState->tc, te, currState->sctlr, 587 currState->l1Desc.texcb(), currState->l1Desc.shareable()); 588 589 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n"); 590 DPRINTF(TLB, " - N:%d pfn:%#x size: %#x global:%d valid: %d\n", 591 te.N, te.pfn, te.size, te.global, te.valid); 592 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d nc:%d\n", 593 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid, 594 te.nonCacheable); 595 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n", 596 currState->l1Desc.domain(), currState->l1Desc.data, 597 (currState->l1Desc.data >> 5) & 0xF ); 598 599 if (!currState->timing) { 600 currState->tc = NULL; 601 currState->req = NULL; 602 } 603 tlb->insert(currState->vaddr, te); 604 605 return; 606 case L1Descriptor::PageTable: 607 Addr l2desc_addr; 608 l2desc_addr = currState->l1Desc.l2Addr() | 609 (bits(currState->vaddr, 19,12) << 2); 610 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n", 611 l2desc_addr); 612 613 // Trickbox address check 614 currState->fault = tlb->walkTrickBoxCheck(l2desc_addr, currState->vaddr, 615 sizeof(uint32_t), currState->isFetch, currState->isWrite, 616 currState->l1Desc.domain(), false); 617 618 if (currState->fault) { 619 if (!currState->timing) { 620 currState->tc = NULL; 621 currState->req = NULL; 622 } 623 return; 624 } 625 626 627 if (currState->timing) { 628 currState->delayed = true; 629 port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), 630 &doL2DescEvent, (uint8_t*)&currState->l2Desc.data, 631 currState->tc->getCpuPtr()->clockPeriod()); 632 } else if (!currState->functional) { 633 port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), 634 NULL, (uint8_t*)&currState->l2Desc.data, 635 currState->tc->getCpuPtr()->clockPeriod()); 636 doL2Descriptor(); 637 } else { 638 RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0, 639 masterId); 640 PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 641 pkt->dataStatic((uint8_t*)&currState->l2Desc.data); 642 port.sendFunctional(pkt); 643 doL2Descriptor(); 644 delete req; 645 delete pkt; 646 } 647 return; 648 default: 649 panic("A new type in a 2 bit field?\n"); 650 } 651} 652 653void 654TableWalker::doL2Descriptor() 655{ 656 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", 657 currState->vaddr, currState->l2Desc.data); 658 TlbEntry te; 659 660 if (currState->l2Desc.invalid()) { 661 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n"); 662 if (!currState->timing) { 663 currState->tc = NULL; 664 currState->req = NULL; 665 } 666 if (currState->isFetch) 667 currState->fault = 668 new PrefetchAbort(currState->vaddr, ArmFault::Translation1); 669 else 670 currState->fault = 671 new DataAbort(currState->vaddr, currState->l1Desc.domain(), 672 currState->isWrite, ArmFault::Translation1); 673 return; 674 } 675 676 if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) { 677 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled 678 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0 679 */ 680 681 currState->fault = 682 new DataAbort(currState->vaddr, 0, currState->isWrite, 683 ArmFault::AccessFlag1); 684 685 } 686 687 if (currState->l2Desc.large()) { 688 te.N = 16; 689 te.pfn = currState->l2Desc.pfn(); 690 } else { 691 te.N = 12; 692 te.pfn = currState->l2Desc.pfn(); 693 } 694 695 te.valid = true; 696 te.size = (1 << te.N) - 1; 697 te.asid = currState->contextId; 698 te.sNp = false; 699 te.vpn = currState->vaddr >> te.N; 700 te.global = currState->l2Desc.global(); 701 te.xn = currState->l2Desc.xn(); 702 te.ap = currState->l2Desc.ap(); 703 te.domain = currState->l1Desc.domain(); 704 memAttrs(currState->tc, te, currState->sctlr, currState->l2Desc.texcb(), 705 currState->l2Desc.shareable()); 706 707 if (!currState->timing) { 708 currState->tc = NULL; 709 currState->req = NULL; 710 } 711 tlb->insert(currState->vaddr, te); 712} 713 714void 715TableWalker::doL1DescriptorWrapper() 716{ 717 currState = stateQueueL1.front(); 718 currState->delayed = false; 719 720 DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data); 721 DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data); 722 723 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr); 724 doL1Descriptor(); 725 726 stateQueueL1.pop_front(); 727 completeDrain(); 728 // Check if fault was generated 729 if (currState->fault != NoFault) { 730 currState->transState->finish(currState->fault, currState->req, 731 currState->tc, currState->mode); 732 733 pending = false; 734 nextWalk(currState->tc); 735 736 currState->req = NULL; 737 currState->tc = NULL; 738 currState->delayed = false; 739 delete currState; 740 } 741 else if (!currState->delayed) { 742 // delay is not set so there is no L2 to do 743 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 744 currState->fault = tlb->translateTiming(currState->req, currState->tc, 745 currState->transState, currState->mode); 746 747 pending = false; 748 nextWalk(currState->tc); 749 750 currState->req = NULL; 751 currState->tc = NULL; 752 currState->delayed = false; 753 delete currState; 754 } else { 755 // need to do L2 descriptor 756 stateQueueL2.push_back(currState); 757 } 758 currState = NULL; 759} 760 761void 762TableWalker::doL2DescriptorWrapper() 763{ 764 currState = stateQueueL2.front(); 765 assert(currState->delayed); 766 767 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n", 768 currState->vaddr); 769 doL2Descriptor(); 770 771 // Check if fault was generated 772 if (currState->fault != NoFault) { 773 currState->transState->finish(currState->fault, currState->req, 774 currState->tc, currState->mode); 775 } 776 else { 777 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 778 currState->fault = tlb->translateTiming(currState->req, currState->tc, 779 currState->transState, currState->mode); 780 } 781 782 783 stateQueueL2.pop_front(); 784 completeDrain(); 785 pending = false; 786 nextWalk(currState->tc); 787 788 currState->req = NULL; 789 currState->tc = NULL; 790 currState->delayed = false; 791 792 delete currState; 793 currState = NULL; 794} 795 796void 797TableWalker::nextWalk(ThreadContext *tc) 798{ 799 if (pendingQueue.size()) 800 schedule(doProcessEvent, tc->getCpuPtr()->clockEdge(Cycles(1))); 801} 802 803 804 805ArmISA::TableWalker * 806ArmTableWalkerParams::create() 807{ 808 return new ArmISA::TableWalker(this); 809} 810
|