/*
+ * Copyright (c) 2010, 2012-2013 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2002-2005 The Regents of The University of Michigan
- * Copyright (c) 2007 MIPS Technologies, Inc.
- * Copyright (c) 2007-2008 The Florida State University
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* (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: Nathan Binkert
- * Steve Reinhardt
- * Jaidev Patwardhan
- * Stephen Hines
+ * 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 {
- struct VAddr
+struct VAddr
+{
+ VAddr(Addr a) { panic("not implemented yet."); }
+};
+
+
+// ITB/DTB page table entry
+struct PTE
+{
+ void serialize(CheckpointOut &cp) const
{
- static const int ImplBits = 43;
- static const Addr ImplMask = (ULL(1) << ImplBits) - 1;
- static const Addr UnImplMask = ~ImplMask;
-
- VAddr(Addr a) : addr(a) {}
- Addr addr;
- operator Addr() const { return addr; }
- const VAddr &operator=(Addr a) { addr = a; return *this; }
-
- Addr vpn() const { return (addr & ImplMask) >> PageShift; }
- Addr page() const { return addr & Page_Mask; }
- Addr offset() const { return addr & PageOffset; }
-
- Addr level3() const
- { return ArmISA::PteAddr(addr >> PageShift); }
- Addr level2() const
- { return ArmISA::PteAddr(addr >> (NPtePageShift + PageShift)); }
- Addr level1() const
- { return ArmISA::PteAddr(addr >> (2 * NPtePageShift + PageShift)); }
- };
+ panic("Need to implement PTE serialization\n");
+ }
- // ITB/DTB page table entry
- struct PTE
+ void unserialize(CheckpointIn &cp)
{
- Addr Mask; // What parts of the VAddr (from bits 28..11) should be used in translation (includes Mask and MaskX from PageMask)
- Addr VPN; // Virtual Page Number (/2) (Includes VPN2 + VPN2X .. bits 31..11 from EntryHi)
- uint8_t asid; // Address Space ID (8 bits) // Lower 8 bits of EntryHi
-
- bool G; // Global Bit - Obtained by an *AND* of EntryLo0 and EntryLo1 G bit
-
- /* Contents of Entry Lo0 */
- Addr PFN0; // Physical Frame Number - Even
- bool D0; // Even entry Dirty Bit
- bool V0; // Even entry Valid Bit
- uint8_t C0; // Cache Coherency Bits - Even
-
- /* Contents of Entry Lo1 */
- Addr PFN1; // Physical Frame Number - Odd
- bool D1; // Odd entry Dirty Bit
- bool V1; // Odd entry Valid Bit
- uint8_t C1; // Cache Coherency Bits (3 bits)
-
- /* The next few variables are put in as optimizations to reduce TLB lookup overheads */
- /* For a given Mask, what is the address shift amount, and what is the OffsetMask */
- int AddrShiftAmount;
- int OffsetMask;
-
- bool Valid() { return (V0 | V1);};
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string §ion);
+ panic("Need to implement PTE serialization\n");
+ }
+
+};
+
+// Lookup level
+enum LookupLevel {
+ L0 = 0, // AArch64 only
+ L1,
+ L2,
+ L3,
+ MAX_LOOKUP_LEVELS
+};
+
+// ITB/DTB table entry
+struct TlbEntry : public Serializable
+{
+ public:
+ enum class MemoryType : std::uint8_t {
+ StronglyOrdered,
+ Device,
+ Normal
+ };
+
+ 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
+ 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
+ uint8_t el;
+
+ // Type of memory
+ bool nonCacheable; // Can we wrap this in mtype?
+
+ // Memory Attributes
+ bool shareable;
+ bool outerShareable;
+
+ // Access permissions
+ bool xn; // Execute Never
+ 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,
+ 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(0), nonCacheable(uncacheable),
+ shareable(false), outerShareable(false), xn(0), pxn(0)
+ {
+ // no restrictions by default, hap = 0x3
+
+ // @todo Check the memory type
+ if (read_only)
+ warn("ARM TlbEntry does not support read-only mappings\n");
+ }
+
+ 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(true),
+ ns(true), nstid(true), el(0), nonCacheable(false),
+ shareable(false), outerShareable(false), xn(0), pxn(0)
+ {
+ // no restrictions by default, hap = 0x3
+
+ // @todo Check the memory type
+ }
+
+ void
+ updateVaddr(Addr new_vaddr)
+ {
+ vpn = new_vaddr >> PageShift;
+ }
+
+ Addr
+ pageStart() const
+ {
+ return pfn << PageShift;
+ }
+
+ bool
+ match(Addr va, uint8_t _vmid, bool hypLookUp, bool secure_lookup,
+ uint8_t 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, uint8_t target_el) const
+ {
+ bool match = false;
+ Addr v = vpn << N;
+
+ if (valid && va >= v && va <= v + size && (secure_lookup == !nstid) &&
+ (hypLookUp == isHyp))
+ {
+ if (target_el == 2 || target_el == 3)
+ match = (el == target_el);
+ else
+ match = (el == 0) || (el == 1);
+ if (match && !ignore_asn) {
+ match = global || (asn == asid);
+ }
+ if (match && nstid) {
+ match = isHyp || (_vmid == vmid);
+ }
+ }
+ return match;
+ }
+
+ Addr
+ pAddr(Addr va) const
+ {
+ return (pfn << N) | (va & size);
+ }
+
+ 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__