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