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