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