table_walker.hh revision 10037:5cac77888310
1/* 2 * Copyright (c) 2010-2013 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 * Giacomo Gabrielli 39 */ 40 41#ifndef __ARCH_ARM_TABLE_WALKER_HH__ 42#define __ARCH_ARM_TABLE_WALKER_HH__ 43 44#include <list> 45 46#include "arch/arm/miscregs.hh" 47#include "arch/arm/system.hh" 48#include "arch/arm/tlb.hh" 49#include "dev/dma_device.hh" 50#include "mem/mem_object.hh" 51#include "mem/request.hh" 52#include "params/ArmTableWalker.hh" 53#include "sim/eventq.hh" 54#include "sim/fault_fwd.hh" 55 56class ThreadContext; 57 58namespace ArmISA { 59class Translation; 60class TLB; 61class Stage2MMU; 62 63class TableWalker : public MemObject 64{ 65 public: 66 class WalkerState; 67 68 class DescriptorBase { 69 public: 70 /** Current lookup level for this descriptor */ 71 LookupLevel lookupLevel; 72 73 virtual Addr pfn() const = 0; 74 virtual TlbEntry::DomainType domain() const = 0; 75 virtual bool xn() const = 0; 76 virtual uint8_t ap() const = 0; 77 virtual bool global(WalkerState *currState) const = 0; 78 virtual uint8_t offsetBits() const = 0; 79 virtual bool secure(bool have_security, WalkerState *currState) const = 0; 80 virtual std::string dbgHeader() const = 0; 81 virtual uint64_t getRawData() const = 0; 82 virtual uint8_t texcb() const 83 { 84 panic("texcb() not implemented for this class\n"); 85 } 86 virtual bool shareable() const 87 { 88 panic("shareable() not implemented for this class\n"); 89 } 90 }; 91 92 class L1Descriptor : public DescriptorBase { 93 public: 94 /** Type of page table entry ARM DDI 0406B: B3-8*/ 95 enum EntryType { 96 Ignore, 97 PageTable, 98 Section, 99 Reserved 100 }; 101 102 /** The raw bits of the entry */ 103 uint32_t data; 104 105 /** This entry has been modified (access flag set) and needs to be 106 * written back to memory */ 107 bool _dirty; 108 109 /** Default ctor */ 110 L1Descriptor() 111 { 112 lookupLevel = L1; 113 } 114 115 virtual uint64_t getRawData() const 116 { 117 return (data); 118 } 119 120 virtual std::string dbgHeader() const 121 { 122 return "Inserting Section Descriptor into TLB\n"; 123 } 124 125 virtual uint8_t offsetBits() const 126 { 127 return 20; 128 } 129 130 EntryType type() const 131 { 132 return (EntryType)(data & 0x3); 133 } 134 135 /** Is the page a Supersection (16MB)?*/ 136 bool supersection() const 137 { 138 return bits(data, 18); 139 } 140 141 /** Return the physcal address of the entry, bits in position*/ 142 Addr paddr() const 143 { 144 if (supersection()) 145 panic("Super sections not implemented\n"); 146 return mbits(data, 31, 20); 147 } 148 /** Return the physcal address of the entry, bits in position*/ 149 Addr paddr(Addr va) const 150 { 151 if (supersection()) 152 panic("Super sections not implemented\n"); 153 return mbits(data, 31, 20) | mbits(va, 19, 0); 154 } 155 156 157 /** Return the physical frame, bits shifted right */ 158 Addr pfn() const 159 { 160 if (supersection()) 161 panic("Super sections not implemented\n"); 162 return bits(data, 31, 20); 163 } 164 165 /** Is the translation global (no asid used)? */ 166 bool global(WalkerState *currState) const 167 { 168 return !bits(data, 17); 169 } 170 171 /** Is the translation not allow execution? */ 172 bool xn() const 173 { 174 return bits(data, 4); 175 } 176 177 /** Three bit access protection flags */ 178 uint8_t ap() const 179 { 180 return (bits(data, 15) << 2) | bits(data, 11, 10); 181 } 182 183 /** Domain Client/Manager: ARM DDI 0406B: B3-31 */ 184 TlbEntry::DomainType domain() const 185 { 186 return static_cast<TlbEntry::DomainType>(bits(data, 8, 5)); 187 } 188 189 /** Address of L2 descriptor if it exists */ 190 Addr l2Addr() const 191 { 192 return mbits(data, 31, 10); 193 } 194 195 /** Memory region attributes: ARM DDI 0406B: B3-32. 196 * These bits are largly ignored by M5 and only used to 197 * provide the illusion that the memory system cares about 198 * anything but cachable vs. uncachable. 199 */ 200 uint8_t texcb() const 201 { 202 return bits(data, 2) | bits(data, 3) << 1 | bits(data, 14, 12) << 2; 203 } 204 205 /** If the section is shareable. See texcb() comment. */ 206 bool shareable() const 207 { 208 return bits(data, 16); 209 } 210 211 /** Set access flag that this entry has been touched. Mark 212 * the entry as requiring a writeback, in the future. 213 */ 214 void setAp0() 215 { 216 data |= 1 << 10; 217 _dirty = true; 218 } 219 220 /** This entry needs to be written back to memory */ 221 bool dirty() const 222 { 223 return _dirty; 224 } 225 226 /** 227 * Returns true if this entry targets the secure physical address 228 * map. 229 */ 230 bool secure(bool have_security, WalkerState *currState) const 231 { 232 if (have_security) { 233 if (type() == PageTable) 234 return !bits(data, 3); 235 else 236 return !bits(data, 19); 237 } 238 return false; 239 } 240 }; 241 242 /** Level 2 page table descriptor */ 243 class L2Descriptor : public DescriptorBase { 244 public: 245 /** The raw bits of the entry. */ 246 uint32_t data; 247 L1Descriptor *l1Parent; 248 249 /** This entry has been modified (access flag set) and needs to be 250 * written back to memory */ 251 bool _dirty; 252 253 /** Default ctor */ 254 L2Descriptor() 255 { 256 lookupLevel = L2; 257 } 258 259 L2Descriptor(L1Descriptor &parent) : l1Parent(&parent) 260 { 261 lookupLevel = L2; 262 } 263 264 virtual uint64_t getRawData() const 265 { 266 return (data); 267 } 268 269 virtual std::string dbgHeader() const 270 { 271 return "Inserting L2 Descriptor into TLB\n"; 272 } 273 274 virtual TlbEntry::DomainType domain() const 275 { 276 return l1Parent->domain(); 277 } 278 279 bool secure(bool have_security, WalkerState *currState) const 280 { 281 return l1Parent->secure(have_security, currState); 282 } 283 284 virtual uint8_t offsetBits() const 285 { 286 return large() ? 16 : 12; 287 } 288 289 /** Is the entry invalid */ 290 bool invalid() const 291 { 292 return bits(data, 1, 0) == 0; 293 } 294 295 /** What is the size of the mapping? */ 296 bool large() const 297 { 298 return bits(data, 1) == 0; 299 } 300 301 /** Is execution allowed on this mapping? */ 302 bool xn() const 303 { 304 return large() ? bits(data, 15) : bits(data, 0); 305 } 306 307 /** Is the translation global (no asid used)? */ 308 bool global(WalkerState *currState) const 309 { 310 return !bits(data, 11); 311 } 312 313 /** Three bit access protection flags */ 314 uint8_t ap() const 315 { 316 return bits(data, 5, 4) | (bits(data, 9) << 2); 317 } 318 319 /** Memory region attributes: ARM DDI 0406B: B3-32 */ 320 uint8_t texcb() const 321 { 322 return large() ? 323 (bits(data, 2) | (bits(data, 3) << 1) | (bits(data, 14, 12) << 2)) : 324 (bits(data, 2) | (bits(data, 3) << 1) | (bits(data, 8, 6) << 2)); 325 } 326 327 /** Return the physical frame, bits shifted right */ 328 Addr pfn() const 329 { 330 return large() ? bits(data, 31, 16) : bits(data, 31, 12); 331 } 332 333 /** Return complete physical address given a VA */ 334 Addr paddr(Addr va) const 335 { 336 if (large()) 337 return mbits(data, 31, 16) | mbits(va, 15, 0); 338 else 339 return mbits(data, 31, 12) | mbits(va, 11, 0); 340 } 341 342 /** If the section is shareable. See texcb() comment. */ 343 bool shareable() const 344 { 345 return bits(data, 10); 346 } 347 348 /** Set access flag that this entry has been touched. Mark 349 * the entry as requiring a writeback, in the future. 350 */ 351 void setAp0() 352 { 353 data |= 1 << 4; 354 _dirty = true; 355 } 356 357 /** This entry needs to be written back to memory */ 358 bool dirty() const 359 { 360 return _dirty; 361 } 362 363 }; 364 365 /** Long-descriptor format (LPAE) */ 366 class LongDescriptor : public DescriptorBase { 367 public: 368 /** Descriptor type */ 369 enum EntryType { 370 Invalid, 371 Table, 372 Block, 373 Page 374 }; 375 376 /** The raw bits of the entry */ 377 uint64_t data; 378 379 /** This entry has been modified (access flag set) and needs to be 380 * written back to memory */ 381 bool _dirty; 382 383 virtual uint64_t getRawData() const 384 { 385 return (data); 386 } 387 388 virtual std::string dbgHeader() const 389 { 390 if (type() == LongDescriptor::Page) { 391 assert(lookupLevel == L3); 392 return "Inserting Page descriptor into TLB\n"; 393 } else { 394 assert(lookupLevel < L3); 395 return "Inserting Block descriptor into TLB\n"; 396 } 397 } 398 399 /** 400 * Returns true if this entry targets the secure physical address 401 * map. 402 */ 403 bool secure(bool have_security, WalkerState *currState) const 404 { 405 assert(type() == Block || type() == Page); 406 return have_security && (currState->secureLookup && !bits(data, 5)); 407 } 408 409 /** True if the current lookup is performed in AArch64 state */ 410 bool aarch64; 411 412 /** True if the granule size is 64 KB (AArch64 only) */ 413 bool largeGrain; 414 415 /** Width of the granule size in bits */ 416 int grainSize; 417 418 /** Return the descriptor type */ 419 EntryType type() const 420 { 421 switch (bits(data, 1, 0)) { 422 case 0x1: 423 // In AArch64 blocks are not allowed at L0 for the 4 KB granule 424 // and at L1 for the 64 KB granule 425 if (largeGrain) 426 return lookupLevel == L2 ? Block : Invalid; 427 return lookupLevel == L0 || lookupLevel == L3 ? Invalid : Block; 428 case 0x3: 429 return lookupLevel == L3 ? Page : Table; 430 default: 431 return Invalid; 432 } 433 } 434 435 /** Return the bit width of the page/block offset */ 436 uint8_t offsetBits() const 437 { 438 assert(type() == Block || type() == Page); 439 if (largeGrain) { 440 if (type() == Block) 441 return 29 /* 512 MB */; 442 return 16 /* 64 KB */; // type() == Page 443 } else { 444 if (type() == Block) 445 return lookupLevel == L1 ? 30 /* 1 GB */ : 21 /* 2 MB */; 446 return 12 /* 4 KB */; // type() == Page 447 } 448 } 449 450 /** Return the physical frame, bits shifted right */ 451 Addr pfn() const 452 { 453 if (aarch64) 454 return bits(data, 47, offsetBits()); 455 return bits(data, 39, offsetBits()); 456 } 457 458 /** Return the complete physical address given a VA */ 459 Addr paddr(Addr va) const 460 { 461 int n = offsetBits(); 462 if (aarch64) 463 return mbits(data, 47, n) | mbits(va, n - 1, 0); 464 return mbits(data, 39, n) | mbits(va, n - 1, 0); 465 } 466 467 /** Return the physical address of the entry */ 468 Addr paddr() const 469 { 470 if (aarch64) 471 return mbits(data, 47, offsetBits()); 472 return mbits(data, 39, offsetBits()); 473 } 474 475 /** Return the address of the next page table */ 476 Addr nextTableAddr() const 477 { 478 assert(type() == Table); 479 if (aarch64) 480 return mbits(data, 47, grainSize); 481 else 482 return mbits(data, 39, 12); 483 } 484 485 /** Return the address of the next descriptor */ 486 Addr nextDescAddr(Addr va) const 487 { 488 assert(type() == Table); 489 Addr pa = 0; 490 if (aarch64) { 491 int stride = grainSize - 3; 492 int va_lo = stride * (3 - (lookupLevel + 1)) + grainSize; 493 int va_hi = va_lo + stride - 1; 494 pa = nextTableAddr() | (bits(va, va_hi, va_lo) << 3); 495 } else { 496 if (lookupLevel == L1) 497 pa = nextTableAddr() | (bits(va, 29, 21) << 3); 498 else // lookupLevel == L2 499 pa = nextTableAddr() | (bits(va, 20, 12) << 3); 500 } 501 return pa; 502 } 503 504 /** Is execution allowed on this mapping? */ 505 bool xn() const 506 { 507 assert(type() == Block || type() == Page); 508 return bits(data, 54); 509 } 510 511 /** Is privileged execution allowed on this mapping? (LPAE only) */ 512 bool pxn() const 513 { 514 assert(type() == Block || type() == Page); 515 return bits(data, 53); 516 } 517 518 /** Contiguous hint bit. */ 519 bool contiguousHint() const 520 { 521 assert(type() == Block || type() == Page); 522 return bits(data, 52); 523 } 524 525 /** Is the translation global (no asid used)? */ 526 bool global(WalkerState *currState) const 527 { 528 assert(currState && (type() == Block || type() == Page)); 529 if (!currState->aarch64 && (currState->isSecure && 530 !currState->secureLookup)) { 531 return false; // ARM ARM issue C B3.6.3 532 } else if (currState->aarch64) { 533 if (currState->el == EL2 || currState->el == EL3) { 534 return true; // By default translations are treated as global 535 // in AArch64 EL2 and EL3 536 } else if (currState->isSecure && !currState->secureLookup) { 537 return false; 538 } 539 } 540 return !bits(data, 11); 541 } 542 543 /** Returns true if the access flag (AF) is set. */ 544 bool af() const 545 { 546 assert(type() == Block || type() == Page); 547 return bits(data, 10); 548 } 549 550 /** 2-bit shareability field */ 551 uint8_t sh() const 552 { 553 assert(type() == Block || type() == Page); 554 return bits(data, 9, 8); 555 } 556 557 /** 2-bit access protection flags */ 558 uint8_t ap() const 559 { 560 assert(type() == Block || type() == Page); 561 // Long descriptors only support the AP[2:1] scheme 562 return bits(data, 7, 6); 563 } 564 565 /** Read/write access protection flag */ 566 bool rw() const 567 { 568 assert(type() == Block || type() == Page); 569 return !bits(data, 7); 570 } 571 572 /** User/privileged level access protection flag */ 573 bool user() const 574 { 575 assert(type() == Block || type() == Page); 576 return bits(data, 6); 577 } 578 579 /** Return the AP bits as compatible with the AP[2:0] format. Utility 580 * function used to simplify the code in the TLB for performing 581 * permission checks. */ 582 static uint8_t ap(bool rw, bool user) 583 { 584 return ((!rw) << 2) | (user << 1); 585 } 586 587 TlbEntry::DomainType domain() const 588 { 589 // Long-desc. format only supports Client domain 590 assert(type() == Block || type() == Page); 591 return TlbEntry::DomainType::Client; 592 } 593 594 /** Attribute index */ 595 uint8_t attrIndx() const 596 { 597 assert(type() == Block || type() == Page); 598 return bits(data, 4, 2); 599 } 600 601 /** Memory attributes, only used by stage 2 translations */ 602 uint8_t memAttr() const 603 { 604 assert(type() == Block || type() == Page); 605 return bits(data, 5, 2); 606 } 607 608 /** Set access flag that this entry has been touched. Mark the entry as 609 * requiring a writeback, in the future. */ 610 void setAf() 611 { 612 data |= 1 << 10; 613 _dirty = true; 614 } 615 616 /** This entry needs to be written back to memory */ 617 bool dirty() const 618 { 619 return _dirty; 620 } 621 622 /** Whether the subsequent levels of lookup are secure */ 623 bool secureTable() const 624 { 625 assert(type() == Table); 626 return !bits(data, 63); 627 } 628 629 /** Two bit access protection flags for subsequent levels of lookup */ 630 uint8_t apTable() const 631 { 632 assert(type() == Table); 633 return bits(data, 62, 61); 634 } 635 636 /** R/W protection flag for subsequent levels of lookup */ 637 uint8_t rwTable() const 638 { 639 assert(type() == Table); 640 return !bits(data, 62); 641 } 642 643 /** User/privileged mode protection flag for subsequent levels of 644 * lookup */ 645 uint8_t userTable() const 646 { 647 assert(type() == Table); 648 return !bits(data, 61); 649 } 650 651 /** Is execution allowed on subsequent lookup levels? */ 652 bool xnTable() const 653 { 654 assert(type() == Table); 655 return bits(data, 60); 656 } 657 658 /** Is privileged execution allowed on subsequent lookup levels? */ 659 bool pxnTable() const 660 { 661 assert(type() == Table); 662 return bits(data, 59); 663 } 664 }; 665 666 class WalkerState 667 { 668 public: 669 /** Thread context that we're doing the walk for */ 670 ThreadContext *tc; 671 672 /** If the access is performed in AArch64 state */ 673 bool aarch64; 674 675 /** Current exception level */ 676 ExceptionLevel el; 677 678 /** Current physical address range in bits */ 679 int physAddrRange; 680 681 /** Request that is currently being serviced */ 682 RequestPtr req; 683 684 /** ASID that we're servicing the request under */ 685 uint16_t asid; 686 uint8_t vmid; 687 bool isHyp; 688 689 /** Translation state for delayed requests */ 690 TLB::Translation *transState; 691 692 /** The fault that we are going to return */ 693 Fault fault; 694 695 /** The virtual address that is being translated with tagging removed.*/ 696 Addr vaddr; 697 698 /** The virtual address that is being translated */ 699 Addr vaddr_tainted; 700 701 /** Cached copy of the sctlr as it existed when translation began */ 702 SCTLR sctlr; 703 704 /** Cached copy of the scr as it existed when translation began */ 705 SCR scr; 706 707 /** Cached copy of the cpsr as it existed when translation began */ 708 CPSR cpsr; 709 710 /** Cached copy of the ttbcr as it existed when translation began. */ 711 TTBCR ttbcr; 712 713 /** Cached copy of the htcr as it existed when translation began. */ 714 HTCR htcr; 715 716 /** Cached copy of the htcr as it existed when translation began. */ 717 HCR hcr; 718 719 /** Cached copy of the vtcr as it existed when translation began. */ 720 VTCR_t vtcr; 721 722 /** If the access is a write */ 723 bool isWrite; 724 725 /** If the access is a fetch (for execution, and no-exec) must be checked?*/ 726 bool isFetch; 727 728 /** If the access comes from the secure state. */ 729 bool isSecure; 730 731 /** Helper variables used to implement hierarchical access permissions 732 * when the long-desc. format is used (LPAE only) */ 733 bool secureLookup; 734 bool rwTable; 735 bool userTable; 736 bool xnTable; 737 bool pxnTable; 738 739 /** Flag indicating if a second stage of lookup is required */ 740 bool stage2Req; 741 742 /** Indicates whether the translation has been passed onto the second 743 * stage mmu, and no more work is required from the first stage. 744 */ 745 bool doingStage2; 746 747 /** A pointer to the stage 2 translation that's in progress */ 748 TLB::Translation *stage2Tran; 749 750 /** If the mode is timing or atomic */ 751 bool timing; 752 753 /** If the atomic mode should be functional */ 754 bool functional; 755 756 /** Save mode for use in delayed response */ 757 BaseTLB::Mode mode; 758 759 /** The translation type that has been requested */ 760 TLB::ArmTranslationType tranType; 761 762 /** Short-format descriptors */ 763 L1Descriptor l1Desc; 764 L2Descriptor l2Desc; 765 766 /** Long-format descriptor (LPAE and AArch64) */ 767 LongDescriptor longDesc; 768 769 /** Whether the response is delayed in timing mode due to additional 770 * lookups */ 771 bool delayed; 772 773 TableWalker *tableWalker; 774 775 void doL1Descriptor(); 776 void doL2Descriptor(); 777 778 void doLongDescriptor(); 779 780 WalkerState(); 781 782 std::string name() const { return tableWalker->name(); } 783 }; 784 785 protected: 786 787 /** 788 * A snooping DMA port that currently does nothing besides 789 * extending the DMA port to accept snoops without complaining. 790 */ 791 class SnoopingDmaPort : public DmaPort 792 { 793 794 protected: 795 796 virtual void recvTimingSnoopReq(PacketPtr pkt) 797 { } 798 799 virtual Tick recvAtomicSnoop(PacketPtr pkt) 800 { return 0; } 801 802 virtual void recvFunctionalSnoop(PacketPtr pkt) 803 { } 804 805 virtual bool isSnooping() const { return true; } 806 807 public: 808 809 /** 810 * A snooping DMA port merely calls the construtor of the DMA 811 * port. 812 */ 813 SnoopingDmaPort(MemObject *dev, System *s) : 814 DmaPort(dev, s) 815 { } 816 }; 817 818 /** Queues of requests for all the different lookup levels */ 819 std::list<WalkerState *> stateQueues[MAX_LOOKUP_LEVELS]; 820 821 /** Queue of requests that have passed are waiting because the walker is 822 * currently busy. */ 823 std::list<WalkerState *> pendingQueue; 824 825 826 /** Port to issue translation requests from */ 827 SnoopingDmaPort port; 828 829 /** If we're draining keep the drain event around until we're drained */ 830 DrainManager *drainManager; 831 832 /** The MMU to forward second stage look upts to */ 833 Stage2MMU *stage2Mmu; 834 835 /** Indicates whether this table walker is part of the stage 2 mmu */ 836 const bool isStage2; 837 838 /** TLB that is initiating these table walks */ 839 TLB *tlb; 840 841 /** Cached copy of the sctlr as it existed when translation began */ 842 SCTLR sctlr; 843 844 WalkerState *currState; 845 846 /** If a timing translation is currently in progress */ 847 bool pending; 848 849 /** Request id for requests generated by this walker */ 850 MasterID masterId; 851 852 /** The number of walks belonging to squashed instructions that can be 853 * removed from the pendingQueue per cycle. */ 854 unsigned numSquashable; 855 856 /** Cached copies of system-level properties */ 857 bool haveSecurity; 858 bool _haveLPAE; 859 bool _haveVirtualization; 860 uint8_t physAddrRange; 861 bool _haveLargeAsid64; 862 ArmSystem *armSys; 863 864 public: 865 typedef ArmTableWalkerParams Params; 866 TableWalker(const Params *p); 867 virtual ~TableWalker(); 868 869 const Params * 870 params() const 871 { 872 return dynamic_cast<const Params *>(_params); 873 } 874 875 bool haveLPAE() const { return _haveLPAE; } 876 bool haveVirtualization() const { return _haveVirtualization; } 877 bool haveLargeAsid64() const { return _haveLargeAsid64; } 878 /** Checks if all state is cleared and if so, completes drain */ 879 void completeDrain(); 880 unsigned int drain(DrainManager *dm); 881 virtual void drainResume(); 882 virtual BaseMasterPort& getMasterPort(const std::string &if_name, 883 PortID idx = InvalidPortID); 884 885 /** 886 * Allow the MMU (overseeing both stage 1 and stage 2 TLBs) to 887 * access the table walker port through the TLB so that it can 888 * orchestrate staged translations. 889 * 890 * @return Our DMA port 891 */ 892 DmaPort& getWalkerPort() { return port; } 893 894 Fault walk(RequestPtr req, ThreadContext *tc, uint16_t asid, uint8_t _vmid, 895 bool _isHyp, TLB::Mode mode, TLB::Translation *_trans, 896 bool timing, bool functional, bool secure, 897 TLB::ArmTranslationType tranType); 898 899 void setTlb(TLB *_tlb) { tlb = _tlb; } 900 TLB* getTlb() { return tlb; } 901 void setMMU(Stage2MMU *m) { stage2Mmu = m; } 902 void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, 903 uint8_t texcb, bool s); 904 void memAttrsLPAE(ThreadContext *tc, TlbEntry &te, 905 LongDescriptor &lDescriptor); 906 void memAttrsAArch64(ThreadContext *tc, TlbEntry &te, uint8_t attrIndx, 907 uint8_t sh); 908 909 static LookupLevel toLookupLevel(uint8_t lookup_level_as_int); 910 911 private: 912 913 void doL1Descriptor(); 914 void doL1DescriptorWrapper(); 915 EventWrapper<TableWalker, 916 &TableWalker::doL1DescriptorWrapper> doL1DescEvent; 917 918 void doL2Descriptor(); 919 void doL2DescriptorWrapper(); 920 EventWrapper<TableWalker, 921 &TableWalker::doL2DescriptorWrapper> doL2DescEvent; 922 923 void doLongDescriptor(); 924 925 void doL0LongDescriptorWrapper(); 926 EventWrapper<TableWalker, 927 &TableWalker::doL0LongDescriptorWrapper> doL0LongDescEvent; 928 void doL1LongDescriptorWrapper(); 929 EventWrapper<TableWalker, 930 &TableWalker::doL1LongDescriptorWrapper> doL1LongDescEvent; 931 void doL2LongDescriptorWrapper(); 932 EventWrapper<TableWalker, 933 &TableWalker::doL2LongDescriptorWrapper> doL2LongDescEvent; 934 void doL3LongDescriptorWrapper(); 935 EventWrapper<TableWalker, 936 &TableWalker::doL3LongDescriptorWrapper> doL3LongDescEvent; 937 938 void doLongDescriptorWrapper(LookupLevel curr_lookup_level); 939 940 bool fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes, 941 Request::Flags flags, int queueIndex, Event *event, 942 void (TableWalker::*doDescriptor)()); 943 944 void insertTableEntry(DescriptorBase &descriptor, bool longDescriptor); 945 946 Fault processWalk(); 947 Fault processWalkLPAE(); 948 static unsigned adjustTableSizeAArch64(unsigned tsz); 949 /// Returns true if the address exceeds the range permitted by the 950 /// system-wide setting or by the TCR_ELx IPS/PS setting 951 static bool checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange); 952 Fault processWalkAArch64(); 953 void processWalkWrapper(); 954 EventWrapper<TableWalker, &TableWalker::processWalkWrapper> doProcessEvent; 955 956 void nextWalk(ThreadContext *tc); 957}; 958 959} // namespace ArmISA 960 961#endif //__ARCH_ARM_TABLE_WALKER_HH__ 962 963