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