diff options
author | ARM gem5 Developers <none@none> | 2014-01-24 15:29:34 -0600 |
---|---|---|
committer | ARM gem5 Developers <none@none> | 2014-01-24 15:29:34 -0600 |
commit | 612f8f074fa1099cf70faf495d46cc647762a031 (patch) | |
tree | bd1e99c43bf15292395eadd4b7ae3f5c823545c3 /src/arch/arm/pagetable.hh | |
parent | f3585c841e964c98911784a187fc4f081a02a0a6 (diff) | |
download | gem5-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.hh | 218 |
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 §ion) { + 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_); } }; |