2 * Copyright (c) 2010-2013 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #ifndef __ARCH_ARM_TABLE_WALKER_HH__
42 #define __ARCH_ARM_TABLE_WALKER_HH__
46 #include "arch/arm/miscregs.hh"
47 #include "arch/arm/system.hh"
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"
63 class TableWalker : public MemObject
68 class DescriptorBase {
70 /** Current lookup level for this descriptor */
71 LookupLevel lookupLevel;
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
84 panic("texcb() not implemented for this class\n");
86 virtual bool shareable() const
88 panic("shareable() not implemented for this class\n");
92 class L1Descriptor : public DescriptorBase {
94 /** Type of page table entry ARM DDI 0406B: B3-8*/
102 /** The raw bits of the entry */
105 /** This entry has been modified (access flag set) and needs to be
106 * written back to memory */
115 virtual uint64_t getRawData() const
120 virtual std::string dbgHeader() const
122 return "Inserting Section Descriptor into TLB\n";
125 virtual uint8_t offsetBits() const
130 EntryType type() const
132 return (EntryType)(data & 0x3);
135 /** Is the page a Supersection (16MB)?*/
136 bool supersection() const
138 return bits(data, 18);
141 /** Return the physcal address of the entry, bits in position*/
145 panic("Super sections not implemented\n");
146 return mbits(data, 31, 20);
148 /** Return the physcal address of the entry, bits in position*/
149 Addr paddr(Addr va) const
152 panic("Super sections not implemented\n");
153 return mbits(data, 31, 20) | mbits(va, 19, 0);
157 /** Return the physical frame, bits shifted right */
161 panic("Super sections not implemented\n");
162 return bits(data, 31, 20);
165 /** Is the translation global (no asid used)? */
166 bool global(WalkerState *currState) const
168 return !bits(data, 17);
171 /** Is the translation not allow execution? */
174 return bits(data, 4);
177 /** Three bit access protection flags */
180 return (bits(data, 15) << 2) | bits(data, 11, 10);
183 /** Domain Client/Manager: ARM DDI 0406B: B3-31 */
184 TlbEntry::DomainType domain() const
186 return static_cast<TlbEntry::DomainType>(bits(data, 8, 5));
189 /** Address of L2 descriptor if it exists */
192 return mbits(data, 31, 10);
195 /** Memory region attributes: ARM DDI 0406B: B3-32.
196 * These bits are largly ignored by M5 and only used to
197 * provide the illusion that the memory system cares about
198 * anything but cachable vs. uncachable.
200 uint8_t texcb() const
202 return bits(data, 2) | bits(data, 3) << 1 | bits(data, 14, 12) << 2;
205 /** If the section is shareable. See texcb() comment. */
206 bool shareable() const
208 return bits(data, 16);
211 /** Set access flag that this entry has been touched. Mark
212 * the entry as requiring a writeback, in the future.
220 /** This entry needs to be written back to memory */
227 * Returns true if this entry targets the secure physical address
230 bool secure(bool have_security, WalkerState *currState) const
233 if (type() == PageTable)
234 return !bits(data, 3);
236 return !bits(data, 19);
242 /** Level 2 page table descriptor */
243 class L2Descriptor : public DescriptorBase {
245 /** The raw bits of the entry. */
247 L1Descriptor *l1Parent;
249 /** This entry has been modified (access flag set) and needs to be
250 * written back to memory */
259 L2Descriptor(L1Descriptor &parent) : l1Parent(&parent)
264 virtual uint64_t getRawData() const
269 virtual std::string dbgHeader() const
271 return "Inserting L2 Descriptor into TLB\n";
274 virtual TlbEntry::DomainType domain() const
276 return l1Parent->domain();
279 bool secure(bool have_security, WalkerState *currState) const
281 return l1Parent->secure(have_security, currState);
284 virtual uint8_t offsetBits() const
286 return large() ? 16 : 12;
289 /** Is the entry invalid */
292 return bits(data, 1, 0) == 0;
295 /** What is the size of the mapping? */
298 return bits(data, 1) == 0;
301 /** Is execution allowed on this mapping? */
304 return large() ? bits(data, 15) : bits(data, 0);
307 /** Is the translation global (no asid used)? */
308 bool global(WalkerState *currState) const
310 return !bits(data, 11);
313 /** Three bit access protection flags */
316 return bits(data, 5, 4) | (bits(data, 9) << 2);
319 /** Memory region attributes: ARM DDI 0406B: B3-32 */
320 uint8_t texcb() const
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));
327 /** Return the physical frame, bits shifted right */
330 return large() ? bits(data, 31, 16) : bits(data, 31, 12);
333 /** Return complete physical address given a VA */
334 Addr paddr(Addr va) const
337 return mbits(data, 31, 16) | mbits(va, 15, 0);
339 return mbits(data, 31, 12) | mbits(va, 11, 0);
342 /** If the section is shareable. See texcb() comment. */
343 bool shareable() const
345 return bits(data, 10);
348 /** Set access flag that this entry has been touched. Mark
349 * the entry as requiring a writeback, in the future.
357 /** This entry needs to be written back to memory */
365 /** Long-descriptor format (LPAE) */
366 class LongDescriptor : public DescriptorBase {
368 /** Descriptor type */
376 /** The raw bits of the entry */
379 /** This entry has been modified (access flag set) and needs to be
380 * written back to memory */
383 virtual uint64_t getRawData() const
388 virtual std::string dbgHeader() const
390 if (type() == LongDescriptor::Page) {
391 assert(lookupLevel == L3);
392 return "Inserting Page descriptor into TLB\n";
394 assert(lookupLevel < L3);
395 return "Inserting Block descriptor into TLB\n";
400 * Returns true if this entry targets the secure physical address
403 bool secure(bool have_security, WalkerState *currState) const
405 assert(type() == Block || type() == Page);
406 return have_security && (currState->secureLookup && !bits(data, 5));
409 /** True if the current lookup is performed in AArch64 state */
412 /** True if the granule size is 64 KB (AArch64 only) */
415 /** Width of the granule size in bits */
418 /** Return the descriptor type */
419 EntryType type() const
421 switch (bits(data, 1, 0)) {
423 // In AArch64 blocks are not allowed at L0 for the 4 KB granule
424 // and at L1 for the 64 KB granule
426 return lookupLevel == L2 ? Block : Invalid;
427 return lookupLevel == L0 || lookupLevel == L3 ? Invalid : Block;
429 return lookupLevel == L3 ? Page : Table;
435 /** Return the bit width of the page/block offset */
436 uint8_t offsetBits() const
438 assert(type() == Block || type() == Page);
441 return 29 /* 512 MB */;
442 return 16 /* 64 KB */; // type() == Page
445 return lookupLevel == L1 ? 30 /* 1 GB */ : 21 /* 2 MB */;
446 return 12 /* 4 KB */; // type() == Page
450 /** Return the physical frame, bits shifted right */
454 return bits(data, 47, offsetBits());
455 return bits(data, 39, offsetBits());
458 /** Return the complete physical address given a VA */
459 Addr paddr(Addr va) const
461 int n = offsetBits();
463 return mbits(data, 47, n) | mbits(va, n - 1, 0);
464 return mbits(data, 39, n) | mbits(va, n - 1, 0);
467 /** Return the physical address of the entry */
471 return mbits(data, 47, offsetBits());
472 return mbits(data, 39, offsetBits());
475 /** Return the address of the next page table */
476 Addr nextTableAddr() const
478 assert(type() == Table);
480 return mbits(data, 47, grainSize);
482 return mbits(data, 39, 12);
485 /** Return the address of the next descriptor */
486 Addr nextDescAddr(Addr va) const
488 assert(type() == Table);
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);
496 if (lookupLevel == L1)
497 pa = nextTableAddr() | (bits(va, 29, 21) << 3);
498 else // lookupLevel == L2
499 pa = nextTableAddr() | (bits(va, 20, 12) << 3);
504 /** Is execution allowed on this mapping? */
507 assert(type() == Block || type() == Page);
508 return bits(data, 54);
511 /** Is privileged execution allowed on this mapping? (LPAE only) */
514 assert(type() == Block || type() == Page);
515 return bits(data, 53);
518 /** Contiguous hint bit. */
519 bool contiguousHint() const
521 assert(type() == Block || type() == Page);
522 return bits(data, 52);
525 /** Is the translation global (no asid used)? */
526 bool global(WalkerState *currState) const
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) {
540 return !bits(data, 11);
543 /** Returns true if the access flag (AF) is set. */
546 assert(type() == Block || type() == Page);
547 return bits(data, 10);
550 /** 2-bit shareability field */
553 assert(type() == Block || type() == Page);
554 return bits(data, 9, 8);
557 /** 2-bit access protection flags */
560 assert(type() == Block || type() == Page);
561 // Long descriptors only support the AP[2:1] scheme
562 return bits(data, 7, 6);
565 /** Read/write access protection flag */
568 assert(type() == Block || type() == Page);
569 return !bits(data, 7);
572 /** User/privileged level access protection flag */
575 assert(type() == Block || type() == Page);
576 return bits(data, 6);
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)
584 return ((!rw) << 2) | (user << 1);
587 TlbEntry::DomainType domain() const
589 // Long-desc. format only supports Client domain
590 assert(type() == Block || type() == Page);
591 return TlbEntry::DomainType::Client;
594 /** Attribute index */
595 uint8_t attrIndx() const
597 assert(type() == Block || type() == Page);
598 return bits(data, 4, 2);
601 /** Memory attributes, only used by stage 2 translations */
602 uint8_t memAttr() const
604 assert(type() == Block || type() == Page);
605 return bits(data, 5, 2);
608 /** Set access flag that this entry has been touched. Mark the entry as
609 * requiring a writeback, in the future. */
616 /** This entry needs to be written back to memory */
622 /** Whether the subsequent levels of lookup are secure */
623 bool secureTable() const
625 assert(type() == Table);
626 return !bits(data, 63);
629 /** Two bit access protection flags for subsequent levels of lookup */
630 uint8_t apTable() const
632 assert(type() == Table);
633 return bits(data, 62, 61);
636 /** R/W protection flag for subsequent levels of lookup */
637 uint8_t rwTable() const
639 assert(type() == Table);
640 return !bits(data, 62);
643 /** User/privileged mode protection flag for subsequent levels of
645 uint8_t userTable() const
647 assert(type() == Table);
648 return !bits(data, 61);
651 /** Is execution allowed on subsequent lookup levels? */
654 assert(type() == Table);
655 return bits(data, 60);
658 /** Is privileged execution allowed on subsequent lookup levels? */
659 bool pxnTable() const
661 assert(type() == Table);
662 return bits(data, 59);
669 /** Thread context that we're doing the walk for */
672 /** If the access is performed in AArch64 state */
675 /** Current exception level */
678 /** Current physical address range in bits */
681 /** Request that is currently being serviced */
684 /** ASID that we're servicing the request under */
689 /** Translation state for delayed requests */
690 TLB::Translation *transState;
692 /** The fault that we are going to return */
695 /** The virtual address that is being translated with tagging removed.*/
698 /** The virtual address that is being translated */
701 /** Cached copy of the sctlr as it existed when translation began */
704 /** Cached copy of the scr as it existed when translation began */
707 /** Cached copy of the cpsr as it existed when translation began */
710 /** Cached copy of the ttbcr as it existed when translation began. */
713 /** Cached copy of the htcr as it existed when translation began. */
716 /** Cached copy of the htcr as it existed when translation began. */
719 /** Cached copy of the vtcr as it existed when translation began. */
722 /** If the access is a write */
725 /** If the access is a fetch (for execution, and no-exec) must be checked?*/
728 /** If the access comes from the secure state. */
731 /** Helper variables used to implement hierarchical access permissions
732 * when the long-desc. format is used (LPAE only) */
739 /** Flag indicating if a second stage of lookup is required */
742 /** Indicates whether the translation has been passed onto the second
743 * stage mmu, and no more work is required from the first stage.
747 /** A pointer to the stage 2 translation that's in progress */
748 TLB::Translation *stage2Tran;
750 /** If the mode is timing or atomic */
753 /** If the atomic mode should be functional */
756 /** Save mode for use in delayed response */
759 /** The translation type that has been requested */
760 TLB::ArmTranslationType tranType;
762 /** Short-format descriptors */
766 /** Long-format descriptor (LPAE and AArch64) */
767 LongDescriptor longDesc;
769 /** Whether the response is delayed in timing mode due to additional
773 TableWalker *tableWalker;
775 void doL1Descriptor();
776 void doL2Descriptor();
778 void doLongDescriptor();
782 std::string name() const { return tableWalker->name(); }
788 * A snooping DMA port that currently does nothing besides
789 * extending the DMA port to accept snoops without complaining.
791 class SnoopingDmaPort : public DmaPort
796 virtual void recvTimingSnoopReq(PacketPtr pkt)
799 virtual Tick recvAtomicSnoop(PacketPtr pkt)
802 virtual void recvFunctionalSnoop(PacketPtr pkt)
805 virtual bool isSnooping() const { return true; }
810 * A snooping DMA port merely calls the construtor of the DMA
813 SnoopingDmaPort(MemObject *dev, System *s) :
818 /** Queues of requests for all the different lookup levels */
819 std::list<WalkerState *> stateQueues[MAX_LOOKUP_LEVELS];
821 /** Queue of requests that have passed are waiting because the walker is
823 std::list<WalkerState *> pendingQueue;
826 /** Port to issue translation requests from */
827 SnoopingDmaPort port;
829 /** If we're draining keep the drain event around until we're drained */
830 DrainManager *drainManager;
832 /** The MMU to forward second stage look upts to */
833 Stage2MMU *stage2Mmu;
835 /** Indicates whether this table walker is part of the stage 2 mmu */
838 /** TLB that is initiating these table walks */
841 /** Cached copy of the sctlr as it existed when translation began */
844 WalkerState *currState;
846 /** If a timing translation is currently in progress */
849 /** Request id for requests generated by this walker */
852 /** The number of walks belonging to squashed instructions that can be
853 * removed from the pendingQueue per cycle. */
854 unsigned numSquashable;
856 /** Cached copies of system-level properties */
859 bool _haveVirtualization;
860 uint8_t physAddrRange;
861 bool _haveLargeAsid64;
865 typedef ArmTableWalkerParams Params;
866 TableWalker(const Params *p);
867 virtual ~TableWalker();
872 return dynamic_cast<const Params *>(_params);
875 bool haveLPAE() const { return _haveLPAE; }
876 bool haveVirtualization() const { return _haveVirtualization; }
877 bool haveLargeAsid64() const { return _haveLargeAsid64; }
878 /** Checks if all state is cleared and if so, completes drain */
879 void completeDrain();
880 unsigned int drain(DrainManager *dm);
881 virtual void drainResume();
882 virtual BaseMasterPort& getMasterPort(const std::string &if_name,
883 PortID idx = InvalidPortID);
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.
890 * @return Our DMA port
892 DmaPort& getWalkerPort() { return port; }
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);
899 void setTlb(TLB *_tlb) { tlb = _tlb; }
900 TLB* getTlb() { return tlb; }
901 void setMMU(Stage2MMU *m) { stage2Mmu = m; }
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,
909 static LookupLevel toLookupLevel(uint8_t lookup_level_as_int);
913 void doL1Descriptor();
914 void doL1DescriptorWrapper();
915 EventWrapper<TableWalker,
916 &TableWalker::doL1DescriptorWrapper> doL1DescEvent;
918 void doL2Descriptor();
919 void doL2DescriptorWrapper();
920 EventWrapper<TableWalker,
921 &TableWalker::doL2DescriptorWrapper> doL2DescEvent;
923 void doLongDescriptor();
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;
938 void doLongDescriptorWrapper(LookupLevel curr_lookup_level);
940 bool fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
941 Request::Flags flags, int queueIndex, Event *event,
942 void (TableWalker::*doDescriptor)());
944 void insertTableEntry(DescriptorBase &descriptor, bool longDescriptor);
947 Fault processWalkLPAE();
948 static unsigned adjustTableSizeAArch64(unsigned tsz);
949 /// Returns true if the address exceeds the range permitted by the
950 /// system-wide setting or by the TCR_ELx IPS/PS setting
951 static bool checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange);
952 Fault processWalkAArch64();
953 void processWalkWrapper();
954 EventWrapper<TableWalker, &TableWalker::processWalkWrapper> doProcessEvent;
956 void nextWalk(ThreadContext *tc);
959 } // namespace ArmISA
961 #endif //__ARCH_ARM_TABLE_WALKER_HH__