arch,sim: Convert clone to GuestABI and define a cloneBackwardsFunc.
[gem5.git] / src / arch / arm / pagetable.hh
index 76b0e3bb838f25b62b5e55fc334058338d1eb60d..933742bc10a0358bfe7bff739206a8eda4fbd3d7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010, 2012-2013 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Ali Saidi
  */
 
 #ifndef __ARCH_ARM_PAGETABLE_H__
 #define __ARCH_ARM_PAGETABLE_H__
 
+#include <cstdint>
+
 #include "arch/arm/isa_traits.hh"
 #include "arch/arm/utility.hh"
 #include "arch/arm/vtophys.hh"
-#include "config/full_system.hh"
+#include "sim/serialize.hh"
 
 namespace ArmISA {
 
@@ -59,116 +59,122 @@ struct VAddr
 // ITB/DTB page table entry
 struct PTE
 {
-    void serialize(std::ostream &os)
+    void serialize(CheckpointOut &cp) const
     {
         panic("Need to implement PTE serialization\n");
     }
 
-    void unserialize(Checkpoint *cp, const std::string &section)
+    void unserialize(CheckpointIn &cp)
     {
         panic("Need to implement PTE serialization\n");
     }
 
 };
 
-struct TlbRange
-{
-    Addr va;
-    Addr size;
-    int contextId;
-    bool global;
-
-    inline bool
-    operator<(const TlbRange &r2) const
-    {
-        if (!(global || r2.global)) {
-            if (contextId < r2.contextId)
-                return true;
-            else if (contextId > r2.contextId)
-                return false;
-        }
-
-        if (va < r2.va)
-            return true;
-        return false;
-    }
-
-    inline bool
-    operator==(const TlbRange &r2) const
-    {
-        return va == r2.va &&
-               size == r2.size &&
-               contextId == r2.contextId &&
-               global == r2.global;
-    }
+// Lookup level
+enum LookupLevel {
+    L0 = 0,  // AArch64 only
+    L1,
+    L2,
+    L3,
+    MAX_LOOKUP_LEVELS
 };
 
-
 // ITB/DTB table entry
-struct TlbEntry
+struct TlbEntry : public Serializable
 {
   public:
-    enum MemoryType {
+    enum class MemoryType : std::uint8_t {
         StronglyOrdered,
         Device,
         Normal
     };
-    enum DomainType {
-        DomainNoAccess = 0,
-        DomainClient,
-        DomainReserved,
-        DomainManager
+
+    enum class DomainType : std::uint8_t {
+        NoAccess = 0,
+        Client,
+        Reserved,
+        Manager
     };
 
     // Matching variables
     Addr pfn;
     Addr size;              // Size of this entry, == Type of TLB Rec
     Addr vpn;               // Virtual Page Number
-    uint32_t asid;          // Address Space Identifier
+    uint64_t attributes;    // Memory attributes formatted for PAR
+
+    LookupLevel lookupLevel;    // Lookup level where the descriptor was fetched
+                                // from.  Used to set the FSR for faults
+                                // occurring while the long desc. format is in
+                                // use (AArch32 w/ LPAE and AArch64)
+
+    uint16_t asid;          // Address Space Identifier
+    uint8_t vmid;           // Virtual machine Identifier
     uint8_t N;              // Number of bits in pagesize
+    uint8_t innerAttrs;
+    uint8_t outerAttrs;
+    uint8_t ap;             // Access permissions bits
+    uint8_t hap;            // Hyp access permissions bits
+    DomainType domain;         // Access Domain
+
+    MemoryType mtype;
+
+    // True if the long descriptor format is used for this entry (LPAE only)
+    bool longDescFormat; // @todo use this in the update attribute bethod
+
+    bool isHyp;
     bool global;
     bool valid;
 
+    // True if the entry targets the non-secure physical address space
+    bool ns;
+    // True if the entry was brought in from a non-secure page table
+    bool nstid;
+    // Exception level on insert, AARCH64 EL0&1, AARCH32 -> el=1
+    ExceptionLevel el;
+
     // Type of memory
     bool nonCacheable;     // Can we wrap this in mtype?
-    bool sNp;      // Section descriptor
 
     // Memory Attributes
-    MemoryType mtype;
-    uint8_t innerAttrs;
-    uint8_t outerAttrs;
     bool shareable;
-    uint32_t attributes;    // Memory attributes formatted for PAR
-
+    bool outerShareable;
 
     // Access permissions
     bool xn;                // Execute Never
-    uint8_t ap:3;           // Access permissions bits
-    uint8_t domain:4;       // Access Domain
-
-    TlbRange range;         // For fast TLB searching
+    bool pxn;               // Privileged Execute Never (LPAE only)
 
     //Construct an entry that maps to physical address addr for SE mode
-    TlbEntry(Addr _asn, Addr _vaddr, Addr _paddr)
+    TlbEntry(Addr _asn, Addr _vaddr, Addr _paddr,
+             bool uncacheable, bool read_only) :
+         pfn(_paddr >> PageShift), size(PageBytes - 1), vpn(_vaddr >> PageShift),
+         attributes(0), lookupLevel(L1), asid(_asn), vmid(0), N(0),
+         innerAttrs(0), outerAttrs(0), ap(read_only ? 0x3 : 0), hap(0x3),
+         domain(DomainType::Client),  mtype(MemoryType::StronglyOrdered),
+         longDescFormat(false), isHyp(false), global(false), valid(true),
+         ns(true), nstid(true), el(EL0), nonCacheable(uncacheable),
+         shareable(false), outerShareable(false), xn(0), pxn(0)
     {
-        pfn = _paddr >> PageShift;
-        size = PageBytes - 1;
-        asid = _asn;
-        global = false;
-        valid = true;
+        // no restrictions by default, hap = 0x3
 
-        vpn = _vaddr >> PageShift;
+        // @todo Check the memory type
+        if (read_only)
+            warn("ARM TlbEntry does not support read-only mappings\n");
+    }
 
-        nonCacheable = sNp = false;
+    TlbEntry() :
+         pfn(0), size(0), vpn(0), attributes(0), lookupLevel(L1), asid(0),
+         vmid(0), N(0), innerAttrs(0), outerAttrs(0), ap(0), hap(0x3),
+         domain(DomainType::Client), mtype(MemoryType::StronglyOrdered),
+         longDescFormat(false), isHyp(false), global(false), valid(false),
+         ns(true), nstid(true), el(EL0), nonCacheable(false),
+         shareable(false), outerShareable(false), xn(0), pxn(0)
+    {
+        // no restrictions by default, hap = 0x3
 
-        xn = 0;
-        ap = 0; // ???
-        domain = DomainClient; //???
+        // @todo Check the memory type
     }
 
-    TlbEntry()
-    {}
-
     void
     updateVaddr(Addr new_vaddr)
     {
@@ -176,33 +182,179 @@ struct TlbEntry
     }
 
     Addr
-    pageStart()
+    pageStart() const
     {
         return pfn << PageShift;
     }
 
     bool
-    match(Addr va, uint8_t cid)
+    match(Addr va, uint8_t _vmid, bool hypLookUp, bool secure_lookup,
+          ExceptionLevel target_el) const
     {
+        return match(va, 0, _vmid, hypLookUp, secure_lookup, true, target_el);
+    }
+
+    bool
+    match(Addr va, uint16_t asn, uint8_t _vmid, bool hypLookUp,
+          bool secure_lookup, bool ignore_asn, ExceptionLevel target_el) const
+    {
+        bool match = false;
         Addr v = vpn << N;
-        if (valid && va >= v && va <= v + size && (global || cid == asid))
-            return true;
-        return false;
+
+        if (valid && va >= v && va <= v + size && (secure_lookup == !nstid) &&
+            (hypLookUp == isHyp))
+        {
+            match = checkELMatch(target_el);
+
+            if (match && !ignore_asn) {
+                match = global || (asn == asid);
+            }
+            if (match && nstid) {
+                match = isHyp || (_vmid == vmid);
+            }
+        }
+        return match;
+    }
+
+    bool
+    checkELMatch(ExceptionLevel target_el) const
+    {
+        if (target_el == EL2 || target_el == EL3) {
+            return (el  == target_el);
+        } else {
+            return (el == EL0) || (el == EL1);
+        }
     }
 
     Addr
-    pAddr(Addr va)
+    pAddr(Addr va) const
     {
         return (pfn << N) | (va & size);
     }
 
-    void serialize(std::ostream &os) { panic("Need to Implement\n"); }
-    void unserialize(Checkpoint *cp, const std::string &section)
-                   { panic("Need to Implement\n");}
-};
+    void
+    updateAttributes()
+    {
+        uint64_t mask;
+        uint64_t newBits;
+
+        // chec bit 11 to determine if its currently LPAE or VMSA format.
+        if ( attributes & (1 << 11) ) {
+            newBits = ((outerShareable ? 0x2 :
+                      shareable         ? 0x3 : 0) << 7);
+            mask = 0x180;
+        } else {
+            /** Formatting for Physical Address Register (PAR)
+             *  Only including lower bits (TLB info here)
+             *  PAR (32-bit format):
+             *  PA   [31:12]
+             *  LPAE [11] (Large Physical Address Extension)
+             *  TLB info [10:1]
+             *      NOS  [10] (Not Outer Sharable)
+             *      NS   [9]  (Non-Secure)
+             *      --   [8]  (Implementation Defined)
+             *      SH   [7]  (Sharable)
+             *      Inner[6:4](Inner memory attributes)
+             *      Outer[3:2](Outer memory attributes)
+             *      SS   [1]  (SuperSection)
+             *      F    [0]  (Fault, Fault Status in [6:1] if faulted)
+            */
+            newBits = ((outerShareable ? 0:1) << 10) |
+                      ((shareable ? 1:0) << 7) |
+                      (innerAttrs << 4) |
+                      (outerAttrs << 2);
+                      // TODO: Supersection bit
+            mask = 0x4FC;
+        }
+        // common bits
+        newBits |= ns << 9;  // NS bit
+        mask    |= 1  << 9;
+        // add in the new bits
+        attributes &= ~mask;
+        attributes |= newBits;
+    }
 
+    void
+    setAttributes(bool lpae)
+    {
+        attributes = lpae ? (1 << 11) : 0;
+        updateAttributes();
+    }
 
+    std::string
+    print() const
+    {
+        return csprintf("%#x, asn %d vmn %d hyp %d ppn %#x size: %#x ap:%d "
+                        "ns:%d nstid:%d g:%d el:%d", vpn << N, asid, vmid,
+                        isHyp, pfn << N, size, ap, ns, nstid, global, el);
+    }
+
+    void
+    serialize(CheckpointOut &cp) const override
+    {
+        SERIALIZE_SCALAR(longDescFormat);
+        SERIALIZE_SCALAR(pfn);
+        SERIALIZE_SCALAR(size);
+        SERIALIZE_SCALAR(vpn);
+        SERIALIZE_SCALAR(asid);
+        SERIALIZE_SCALAR(vmid);
+        SERIALIZE_SCALAR(isHyp);
+        SERIALIZE_SCALAR(N);
+        SERIALIZE_SCALAR(global);
+        SERIALIZE_SCALAR(valid);
+        SERIALIZE_SCALAR(ns);
+        SERIALIZE_SCALAR(nstid);
+        SERIALIZE_SCALAR(nonCacheable);
+        SERIALIZE_ENUM(lookupLevel);
+        SERIALIZE_ENUM(mtype);
+        SERIALIZE_SCALAR(innerAttrs);
+        SERIALIZE_SCALAR(outerAttrs);
+        SERIALIZE_SCALAR(shareable);
+        SERIALIZE_SCALAR(outerShareable);
+        SERIALIZE_SCALAR(attributes);
+        SERIALIZE_SCALAR(xn);
+        SERIALIZE_SCALAR(pxn);
+        SERIALIZE_SCALAR(ap);
+        SERIALIZE_SCALAR(hap);
+        uint8_t domain_ = static_cast<uint8_t>(domain);
+        paramOut(cp, "domain", domain_);
+    }
+    void
+    unserialize(CheckpointIn &cp) override
+    {
+        UNSERIALIZE_SCALAR(longDescFormat);
+        UNSERIALIZE_SCALAR(pfn);
+        UNSERIALIZE_SCALAR(size);
+        UNSERIALIZE_SCALAR(vpn);
+        UNSERIALIZE_SCALAR(asid);
+        UNSERIALIZE_SCALAR(vmid);
+        UNSERIALIZE_SCALAR(isHyp);
+        UNSERIALIZE_SCALAR(N);
+        UNSERIALIZE_SCALAR(global);
+        UNSERIALIZE_SCALAR(valid);
+        UNSERIALIZE_SCALAR(ns);
+        UNSERIALIZE_SCALAR(nstid);
+        UNSERIALIZE_SCALAR(nonCacheable);
+        UNSERIALIZE_ENUM(lookupLevel);
+        UNSERIALIZE_ENUM(mtype);
+        UNSERIALIZE_SCALAR(innerAttrs);
+        UNSERIALIZE_SCALAR(outerAttrs);
+        UNSERIALIZE_SCALAR(shareable);
+        UNSERIALIZE_SCALAR(outerShareable);
+        UNSERIALIZE_SCALAR(attributes);
+        UNSERIALIZE_SCALAR(xn);
+        UNSERIALIZE_SCALAR(pxn);
+        UNSERIALIZE_SCALAR(ap);
+        UNSERIALIZE_SCALAR(hap);
+        uint8_t domain_;
+        paramIn(cp, "domain", domain_);
+        domain = static_cast<DomainType>(domain_);
+    }
 
 };
+
+
+
+}
 #endif // __ARCH_ARM_PAGETABLE_H__