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