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