summaryrefslogtreecommitdiff
path: root/src/arch/arm/pagetable.hh
diff options
context:
space:
mode:
authorARM gem5 Developers <none@none>2014-01-24 15:29:34 -0600
committerARM gem5 Developers <none@none>2014-01-24 15:29:34 -0600
commit612f8f074fa1099cf70faf495d46cc647762a031 (patch)
treebd1e99c43bf15292395eadd4b7ae3f5c823545c3 /src/arch/arm/pagetable.hh
parentf3585c841e964c98911784a187fc4f081a02a0a6 (diff)
downloadgem5-612f8f074fa1099cf70faf495d46cc647762a031.tar.xz
arm: Add support for ARMv8 (AArch64 & AArch32)
Note: AArch64 and AArch32 interworking is not supported. If you use an AArch64 kernel you are restricted to AArch64 user-mode binaries. This will be addressed in a later patch. Note: Virtualization is only supported in AArch32 mode. This will also be fixed in a later patch. Contributors: Giacomo Gabrielli (TrustZone, LPAE, system-level AArch64, AArch64 NEON, validation) Thomas Grocutt (AArch32 Virtualization, AArch64 FP, validation) Mbou Eyole (AArch64 NEON, validation) Ali Saidi (AArch64 Linux support, code integration, validation) Edmund Grimley-Evans (AArch64 FP) William Wang (AArch64 Linux support) Rene De Jong (AArch64 Linux support, performance opt.) Matt Horsnell (AArch64 MP, validation) Matt Evans (device models, code integration, validation) Chris Adeniyi-Jones (AArch64 syscall-emulation) Prakash Ramrakhyani (validation) Dam Sunwoo (validation) Chander Sudanthi (validation) Stephan Diestelhorst (validation) Andreas Hansson (code integration, performance opt.) Eric Van Hensbergen (performance opt.) Gabe Black
Diffstat (limited to 'src/arch/arm/pagetable.hh')
-rw-r--r--src/arch/arm/pagetable.hh218
1 files changed, 178 insertions, 40 deletions
diff --git a/src/arch/arm/pagetable.hh b/src/arch/arm/pagetable.hh
index 898ab3191..591ec9807 100644
--- a/src/arch/arm/pagetable.hh
+++ b/src/arch/arm/pagetable.hh
@@ -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
@@ -43,6 +43,8 @@
#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"
@@ -71,69 +73,107 @@ struct PTE
};
+// Lookup level
+enum LookupLevel {
+ L0 = 0, // AArch64 only
+ L1,
+ L2,
+ L3,
+ MAX_LOOKUP_LEVELS
+};
+
// ITB/DTB table entry
struct TlbEntry
{
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
+ uint8_t 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; // Access permissions bits
- uint8_t domain; // Access Domain
+ 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) :
+ pfn(_paddr >> PageShift), size(PageBytes - 1), vpn(_vaddr >> PageShift),
+ attributes(0), lookupLevel(L1), asid(_asn), 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)
{
- 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
+ }
- 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(true),
+ ns(true), nstid(true), el(0), 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)
{
@@ -141,67 +181,165 @@ 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,
+ 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 && (global || cid == asid))
- return true;
- return false;
+
+ 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)
+ 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(std::ostream &os)
{
+ 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_SCALAR(sNp);
+ 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(domain);
+ SERIALIZE_SCALAR(hap);
+ uint8_t domain_ = static_cast<uint8_t>(domain);
+ paramOut(os, "domain", domain_);
}
void
unserialize(Checkpoint *cp, const std::string &section)
{
+ 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_SCALAR(sNp);
+ 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(domain);
+ UNSERIALIZE_SCALAR(hap);
+ uint8_t domain_;
+ paramIn(cp, section, "domain", domain_);
+ domain = static_cast<DomainType>(domain_);
}
};