17404SAli.Saidi@ARM.com/* 214095Sgiacomo.travaglini@arm.com * Copyright (c) 2010-2016, 2019 ARM Limited 37404SAli.Saidi@ARM.com * All rights reserved 47404SAli.Saidi@ARM.com * 57404SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 67404SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual 77404SAli.Saidi@ARM.com * property including but not limited to intellectual property relating 87404SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software 97404SAli.Saidi@ARM.com * licensed hereunder. You may use the software subject to the license 107404SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 117404SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software, 127404SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form. 137404SAli.Saidi@ARM.com * 147404SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 157404SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 167404SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 177404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 187404SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 197404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 207404SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 217404SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 227404SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 237404SAli.Saidi@ARM.com * this software without specific prior written permission. 247404SAli.Saidi@ARM.com * 257404SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 267404SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 277404SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 287404SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 297404SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 307404SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 317404SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 327404SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 337404SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 347404SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 357404SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 367404SAli.Saidi@ARM.com * 377404SAli.Saidi@ARM.com * Authors: Ali Saidi 3810037SARM gem5 Developers * Giacomo Gabrielli 397404SAli.Saidi@ARM.com */ 407404SAli.Saidi@ARM.com 417404SAli.Saidi@ARM.com#ifndef __ARCH_ARM_TABLE_WALKER_HH__ 427404SAli.Saidi@ARM.com#define __ARCH_ARM_TABLE_WALKER_HH__ 437404SAli.Saidi@ARM.com 447578Sdam.sunwoo@arm.com#include <list> 457578Sdam.sunwoo@arm.com 4614093Sgiacomo.travaglini@arm.com#include "arch/arm/faults.hh" 477404SAli.Saidi@ARM.com#include "arch/arm/miscregs.hh" 4810037SARM gem5 Developers#include "arch/arm/system.hh" 497404SAli.Saidi@ARM.com#include "arch/arm/tlb.hh" 507404SAli.Saidi@ARM.com#include "mem/request.hh" 517404SAli.Saidi@ARM.com#include "params/ArmTableWalker.hh" 5213892Sgabeblack@google.com#include "sim/clocked_object.hh" 537404SAli.Saidi@ARM.com#include "sim/eventq.hh" 547404SAli.Saidi@ARM.com 557404SAli.Saidi@ARM.comclass ThreadContext; 567404SAli.Saidi@ARM.com 5710873Sandreas.sandberg@arm.comclass DmaPort; 5810873Sandreas.sandberg@arm.com 597404SAli.Saidi@ARM.comnamespace ArmISA { 607404SAli.Saidi@ARM.comclass Translation; 617404SAli.Saidi@ARM.comclass TLB; 6210037SARM gem5 Developersclass Stage2MMU; 637404SAli.Saidi@ARM.com 6413892Sgabeblack@google.comclass TableWalker : public ClockedObject 657404SAli.Saidi@ARM.com{ 667694SAli.Saidi@ARM.com public: 6710037SARM gem5 Developers class WalkerState; 6810037SARM gem5 Developers 6910037SARM gem5 Developers class DescriptorBase { 7010037SARM gem5 Developers public: 7114040Sgiacomo.travaglini@arm.com DescriptorBase() : lookupLevel(L0) {} 7214040Sgiacomo.travaglini@arm.com 7310037SARM gem5 Developers /** Current lookup level for this descriptor */ 7410037SARM gem5 Developers LookupLevel lookupLevel; 7510037SARM gem5 Developers 7610037SARM gem5 Developers virtual Addr pfn() const = 0; 7710037SARM gem5 Developers virtual TlbEntry::DomainType domain() const = 0; 7810037SARM gem5 Developers virtual bool xn() const = 0; 7910037SARM gem5 Developers virtual uint8_t ap() const = 0; 8010037SARM gem5 Developers virtual bool global(WalkerState *currState) const = 0; 8110037SARM gem5 Developers virtual uint8_t offsetBits() const = 0; 8210037SARM gem5 Developers virtual bool secure(bool have_security, WalkerState *currState) const = 0; 8310037SARM gem5 Developers virtual std::string dbgHeader() const = 0; 8410037SARM gem5 Developers virtual uint64_t getRawData() const = 0; 8510037SARM gem5 Developers virtual uint8_t texcb() const 8610037SARM gem5 Developers { 8710037SARM gem5 Developers panic("texcb() not implemented for this class\n"); 8810037SARM gem5 Developers } 8910037SARM gem5 Developers virtual bool shareable() const 9010037SARM gem5 Developers { 9110037SARM gem5 Developers panic("shareable() not implemented for this class\n"); 9210037SARM gem5 Developers } 9310037SARM gem5 Developers }; 9410037SARM gem5 Developers 9510037SARM gem5 Developers class L1Descriptor : public DescriptorBase { 9610037SARM gem5 Developers public: 977404SAli.Saidi@ARM.com /** Type of page table entry ARM DDI 0406B: B3-8*/ 987404SAli.Saidi@ARM.com enum EntryType { 997404SAli.Saidi@ARM.com Ignore, 1007404SAli.Saidi@ARM.com PageTable, 1017404SAli.Saidi@ARM.com Section, 1027404SAli.Saidi@ARM.com Reserved 1037404SAli.Saidi@ARM.com }; 1047404SAli.Saidi@ARM.com 1057436Sdam.sunwoo@arm.com /** The raw bits of the entry */ 1067404SAli.Saidi@ARM.com uint32_t data; 1077404SAli.Saidi@ARM.com 1087436Sdam.sunwoo@arm.com /** This entry has been modified (access flag set) and needs to be 1097436Sdam.sunwoo@arm.com * written back to memory */ 1107436Sdam.sunwoo@arm.com bool _dirty; 1117436Sdam.sunwoo@arm.com 11210037SARM gem5 Developers /** Default ctor */ 11310537Sandreas.hansson@arm.com L1Descriptor() : data(0), _dirty(false) 11410037SARM gem5 Developers { 11510037SARM gem5 Developers lookupLevel = L1; 11610037SARM gem5 Developers } 11710037SARM gem5 Developers 11810037SARM gem5 Developers virtual uint64_t getRawData() const 11910037SARM gem5 Developers { 12010037SARM gem5 Developers return (data); 12110037SARM gem5 Developers } 12210037SARM gem5 Developers 12310037SARM gem5 Developers virtual std::string dbgHeader() const 12410037SARM gem5 Developers { 12510037SARM gem5 Developers return "Inserting Section Descriptor into TLB\n"; 12610037SARM gem5 Developers } 12710037SARM gem5 Developers 12810037SARM gem5 Developers virtual uint8_t offsetBits() const 12910037SARM gem5 Developers { 13010037SARM gem5 Developers return 20; 13110037SARM gem5 Developers } 13210037SARM gem5 Developers 1337404SAli.Saidi@ARM.com EntryType type() const 1347404SAli.Saidi@ARM.com { 1357404SAli.Saidi@ARM.com return (EntryType)(data & 0x3); 1367404SAli.Saidi@ARM.com } 1377404SAli.Saidi@ARM.com 1387404SAli.Saidi@ARM.com /** Is the page a Supersection (16MB)?*/ 1397404SAli.Saidi@ARM.com bool supersection() const 1407404SAli.Saidi@ARM.com { 1417404SAli.Saidi@ARM.com return bits(data, 18); 1427404SAli.Saidi@ARM.com } 1437404SAli.Saidi@ARM.com 1447404SAli.Saidi@ARM.com /** Return the physcal address of the entry, bits in position*/ 1457404SAli.Saidi@ARM.com Addr paddr() const 1467404SAli.Saidi@ARM.com { 1477404SAli.Saidi@ARM.com if (supersection()) 1487404SAli.Saidi@ARM.com panic("Super sections not implemented\n"); 1497946SGiacomo.Gabrielli@arm.com return mbits(data, 31, 20); 1507404SAli.Saidi@ARM.com } 1517694SAli.Saidi@ARM.com /** Return the physcal address of the entry, bits in position*/ 1527694SAli.Saidi@ARM.com Addr paddr(Addr va) const 1537694SAli.Saidi@ARM.com { 1547694SAli.Saidi@ARM.com if (supersection()) 1557694SAli.Saidi@ARM.com panic("Super sections not implemented\n"); 1567946SGiacomo.Gabrielli@arm.com return mbits(data, 31, 20) | mbits(va, 19, 0); 1577694SAli.Saidi@ARM.com } 1587694SAli.Saidi@ARM.com 1597404SAli.Saidi@ARM.com 1607404SAli.Saidi@ARM.com /** Return the physical frame, bits shifted right */ 1617404SAli.Saidi@ARM.com Addr pfn() const 1627404SAli.Saidi@ARM.com { 1637404SAli.Saidi@ARM.com if (supersection()) 1647404SAli.Saidi@ARM.com panic("Super sections not implemented\n"); 1657946SGiacomo.Gabrielli@arm.com return bits(data, 31, 20); 1667404SAli.Saidi@ARM.com } 1677404SAli.Saidi@ARM.com 1687404SAli.Saidi@ARM.com /** Is the translation global (no asid used)? */ 16910037SARM gem5 Developers bool global(WalkerState *currState) const 1707404SAli.Saidi@ARM.com { 17110037SARM gem5 Developers return !bits(data, 17); 1727404SAli.Saidi@ARM.com } 1737404SAli.Saidi@ARM.com 1747404SAli.Saidi@ARM.com /** Is the translation not allow execution? */ 1757404SAli.Saidi@ARM.com bool xn() const 1767404SAli.Saidi@ARM.com { 1777608SGene.Wu@arm.com return bits(data, 4); 1787404SAli.Saidi@ARM.com } 1797404SAli.Saidi@ARM.com 1807404SAli.Saidi@ARM.com /** Three bit access protection flags */ 1817404SAli.Saidi@ARM.com uint8_t ap() const 1827404SAli.Saidi@ARM.com { 1837946SGiacomo.Gabrielli@arm.com return (bits(data, 15) << 2) | bits(data, 11, 10); 1847404SAli.Saidi@ARM.com } 1857404SAli.Saidi@ARM.com 1867404SAli.Saidi@ARM.com /** Domain Client/Manager: ARM DDI 0406B: B3-31 */ 18710037SARM gem5 Developers TlbEntry::DomainType domain() const 1887404SAli.Saidi@ARM.com { 18910037SARM gem5 Developers return static_cast<TlbEntry::DomainType>(bits(data, 8, 5)); 1907404SAli.Saidi@ARM.com } 1917404SAli.Saidi@ARM.com 1927404SAli.Saidi@ARM.com /** Address of L2 descriptor if it exists */ 1937404SAli.Saidi@ARM.com Addr l2Addr() const 1947404SAli.Saidi@ARM.com { 1957946SGiacomo.Gabrielli@arm.com return mbits(data, 31, 10); 1967404SAli.Saidi@ARM.com } 1977404SAli.Saidi@ARM.com 1987436Sdam.sunwoo@arm.com /** Memory region attributes: ARM DDI 0406B: B3-32. 1997436Sdam.sunwoo@arm.com * These bits are largly ignored by M5 and only used to 2007436Sdam.sunwoo@arm.com * provide the illusion that the memory system cares about 2017436Sdam.sunwoo@arm.com * anything but cachable vs. uncachable. 2027436Sdam.sunwoo@arm.com */ 2037404SAli.Saidi@ARM.com uint8_t texcb() const 2047404SAli.Saidi@ARM.com { 2057946SGiacomo.Gabrielli@arm.com return bits(data, 2) | bits(data, 3) << 1 | bits(data, 14, 12) << 2; 2067404SAli.Saidi@ARM.com } 2077404SAli.Saidi@ARM.com 2087436Sdam.sunwoo@arm.com /** If the section is shareable. See texcb() comment. */ 2097436Sdam.sunwoo@arm.com bool shareable() const 2107436Sdam.sunwoo@arm.com { 2117436Sdam.sunwoo@arm.com return bits(data, 16); 2127436Sdam.sunwoo@arm.com } 2137436Sdam.sunwoo@arm.com 2147436Sdam.sunwoo@arm.com /** Set access flag that this entry has been touched. Mark 2157436Sdam.sunwoo@arm.com * the entry as requiring a writeback, in the future. 2167436Sdam.sunwoo@arm.com */ 2177436Sdam.sunwoo@arm.com void setAp0() 2187436Sdam.sunwoo@arm.com { 2197436Sdam.sunwoo@arm.com data |= 1 << 10; 2207436Sdam.sunwoo@arm.com _dirty = true; 2217436Sdam.sunwoo@arm.com } 2227436Sdam.sunwoo@arm.com 2237436Sdam.sunwoo@arm.com /** This entry needs to be written back to memory */ 2247436Sdam.sunwoo@arm.com bool dirty() const 2257436Sdam.sunwoo@arm.com { 2267436Sdam.sunwoo@arm.com return _dirty; 2277436Sdam.sunwoo@arm.com } 22810037SARM gem5 Developers 22910037SARM gem5 Developers /** 23010037SARM gem5 Developers * Returns true if this entry targets the secure physical address 23110037SARM gem5 Developers * map. 23210037SARM gem5 Developers */ 23310037SARM gem5 Developers bool secure(bool have_security, WalkerState *currState) const 23410037SARM gem5 Developers { 23510037SARM gem5 Developers if (have_security) { 23610037SARM gem5 Developers if (type() == PageTable) 23710037SARM gem5 Developers return !bits(data, 3); 23810037SARM gem5 Developers else 23910037SARM gem5 Developers return !bits(data, 19); 24010037SARM gem5 Developers } 24110037SARM gem5 Developers return false; 24210037SARM gem5 Developers } 2437404SAli.Saidi@ARM.com }; 2447404SAli.Saidi@ARM.com 2457404SAli.Saidi@ARM.com /** Level 2 page table descriptor */ 24610037SARM gem5 Developers class L2Descriptor : public DescriptorBase { 24710037SARM gem5 Developers public: 2487436Sdam.sunwoo@arm.com /** The raw bits of the entry. */ 24910037SARM gem5 Developers uint32_t data; 25010037SARM gem5 Developers L1Descriptor *l1Parent; 2517404SAli.Saidi@ARM.com 2527436Sdam.sunwoo@arm.com /** This entry has been modified (access flag set) and needs to be 2537436Sdam.sunwoo@arm.com * written back to memory */ 2547436Sdam.sunwoo@arm.com bool _dirty; 2557436Sdam.sunwoo@arm.com 25610037SARM gem5 Developers /** Default ctor */ 25710537Sandreas.hansson@arm.com L2Descriptor() : data(0), l1Parent(nullptr), _dirty(false) 25810037SARM gem5 Developers { 25910037SARM gem5 Developers lookupLevel = L2; 26010037SARM gem5 Developers } 26110037SARM gem5 Developers 26210537Sandreas.hansson@arm.com L2Descriptor(L1Descriptor &parent) : data(0), l1Parent(&parent), 26310537Sandreas.hansson@arm.com _dirty(false) 26410037SARM gem5 Developers { 26510037SARM gem5 Developers lookupLevel = L2; 26610037SARM gem5 Developers } 26710037SARM gem5 Developers 26810037SARM gem5 Developers virtual uint64_t getRawData() const 26910037SARM gem5 Developers { 27010037SARM gem5 Developers return (data); 27110037SARM gem5 Developers } 27210037SARM gem5 Developers 27310037SARM gem5 Developers virtual std::string dbgHeader() const 27410037SARM gem5 Developers { 27510037SARM gem5 Developers return "Inserting L2 Descriptor into TLB\n"; 27610037SARM gem5 Developers } 27710037SARM gem5 Developers 27810037SARM gem5 Developers virtual TlbEntry::DomainType domain() const 27910037SARM gem5 Developers { 28010037SARM gem5 Developers return l1Parent->domain(); 28110037SARM gem5 Developers } 28210037SARM gem5 Developers 28310037SARM gem5 Developers bool secure(bool have_security, WalkerState *currState) const 28410037SARM gem5 Developers { 28510037SARM gem5 Developers return l1Parent->secure(have_security, currState); 28610037SARM gem5 Developers } 28710037SARM gem5 Developers 28810037SARM gem5 Developers virtual uint8_t offsetBits() const 28910037SARM gem5 Developers { 29010037SARM gem5 Developers return large() ? 16 : 12; 29110037SARM gem5 Developers } 29210037SARM gem5 Developers 2937404SAli.Saidi@ARM.com /** Is the entry invalid */ 2947404SAli.Saidi@ARM.com bool invalid() const 2957404SAli.Saidi@ARM.com { 2967946SGiacomo.Gabrielli@arm.com return bits(data, 1, 0) == 0; 2977404SAli.Saidi@ARM.com } 2987404SAli.Saidi@ARM.com 2997404SAli.Saidi@ARM.com /** What is the size of the mapping? */ 3007404SAli.Saidi@ARM.com bool large() const 3017404SAli.Saidi@ARM.com { 3027404SAli.Saidi@ARM.com return bits(data, 1) == 0; 3037404SAli.Saidi@ARM.com } 3047404SAli.Saidi@ARM.com 3057404SAli.Saidi@ARM.com /** Is execution allowed on this mapping? */ 3067404SAli.Saidi@ARM.com bool xn() const 3077404SAli.Saidi@ARM.com { 3087404SAli.Saidi@ARM.com return large() ? bits(data, 15) : bits(data, 0); 3097404SAli.Saidi@ARM.com } 3107404SAli.Saidi@ARM.com 3117404SAli.Saidi@ARM.com /** Is the translation global (no asid used)? */ 31210037SARM gem5 Developers bool global(WalkerState *currState) const 3137404SAli.Saidi@ARM.com { 3147404SAli.Saidi@ARM.com return !bits(data, 11); 3157404SAli.Saidi@ARM.com } 3167404SAli.Saidi@ARM.com 3177404SAli.Saidi@ARM.com /** Three bit access protection flags */ 3187404SAli.Saidi@ARM.com uint8_t ap() const 3197404SAli.Saidi@ARM.com { 3207404SAli.Saidi@ARM.com return bits(data, 5, 4) | (bits(data, 9) << 2); 3217404SAli.Saidi@ARM.com } 3227404SAli.Saidi@ARM.com 3237404SAli.Saidi@ARM.com /** Memory region attributes: ARM DDI 0406B: B3-32 */ 3247404SAli.Saidi@ARM.com uint8_t texcb() const 3257404SAli.Saidi@ARM.com { 3267404SAli.Saidi@ARM.com return large() ? 3277946SGiacomo.Gabrielli@arm.com (bits(data, 2) | (bits(data, 3) << 1) | (bits(data, 14, 12) << 2)) : 3287946SGiacomo.Gabrielli@arm.com (bits(data, 2) | (bits(data, 3) << 1) | (bits(data, 8, 6) << 2)); 3297404SAli.Saidi@ARM.com } 3307404SAli.Saidi@ARM.com 3317404SAli.Saidi@ARM.com /** Return the physical frame, bits shifted right */ 3327404SAli.Saidi@ARM.com Addr pfn() const 3337404SAli.Saidi@ARM.com { 3347404SAli.Saidi@ARM.com return large() ? bits(data, 31, 16) : bits(data, 31, 12); 3357404SAli.Saidi@ARM.com } 3367404SAli.Saidi@ARM.com 3377694SAli.Saidi@ARM.com /** Return complete physical address given a VA */ 3387694SAli.Saidi@ARM.com Addr paddr(Addr va) const 3397694SAli.Saidi@ARM.com { 3407694SAli.Saidi@ARM.com if (large()) 3417694SAli.Saidi@ARM.com return mbits(data, 31, 16) | mbits(va, 15, 0); 3427694SAli.Saidi@ARM.com else 3437694SAli.Saidi@ARM.com return mbits(data, 31, 12) | mbits(va, 11, 0); 3447694SAli.Saidi@ARM.com } 3457694SAli.Saidi@ARM.com 3467436Sdam.sunwoo@arm.com /** If the section is shareable. See texcb() comment. */ 3477436Sdam.sunwoo@arm.com bool shareable() const 3487436Sdam.sunwoo@arm.com { 3497436Sdam.sunwoo@arm.com return bits(data, 10); 3507436Sdam.sunwoo@arm.com } 3517436Sdam.sunwoo@arm.com 3527436Sdam.sunwoo@arm.com /** Set access flag that this entry has been touched. Mark 3537436Sdam.sunwoo@arm.com * the entry as requiring a writeback, in the future. 3547436Sdam.sunwoo@arm.com */ 3557436Sdam.sunwoo@arm.com void setAp0() 3567436Sdam.sunwoo@arm.com { 3577436Sdam.sunwoo@arm.com data |= 1 << 4; 3587436Sdam.sunwoo@arm.com _dirty = true; 3597436Sdam.sunwoo@arm.com } 3607436Sdam.sunwoo@arm.com 3617436Sdam.sunwoo@arm.com /** This entry needs to be written back to memory */ 3627436Sdam.sunwoo@arm.com bool dirty() const 3637436Sdam.sunwoo@arm.com { 3647436Sdam.sunwoo@arm.com return _dirty; 3657436Sdam.sunwoo@arm.com } 3667436Sdam.sunwoo@arm.com 3677404SAli.Saidi@ARM.com }; 3687404SAli.Saidi@ARM.com 36910324SCurtis.Dunham@arm.com // Granule sizes for AArch64 long descriptors 37010324SCurtis.Dunham@arm.com enum GrainSize { 37110324SCurtis.Dunham@arm.com Grain4KB = 12, 37210324SCurtis.Dunham@arm.com Grain16KB = 14, 37310324SCurtis.Dunham@arm.com Grain64KB = 16, 37410324SCurtis.Dunham@arm.com ReservedGrain = 0 37510324SCurtis.Dunham@arm.com }; 37610324SCurtis.Dunham@arm.com 37710037SARM gem5 Developers /** Long-descriptor format (LPAE) */ 37810037SARM gem5 Developers class LongDescriptor : public DescriptorBase { 37910037SARM gem5 Developers public: 38010037SARM gem5 Developers /** Descriptor type */ 38110037SARM gem5 Developers enum EntryType { 38210037SARM gem5 Developers Invalid, 38310037SARM gem5 Developers Table, 38410037SARM gem5 Developers Block, 38510037SARM gem5 Developers Page 38610037SARM gem5 Developers }; 38710037SARM gem5 Developers 38814040Sgiacomo.travaglini@arm.com LongDescriptor() : data(0), _dirty(false) {} 38914040Sgiacomo.travaglini@arm.com 39010037SARM gem5 Developers /** The raw bits of the entry */ 39110037SARM gem5 Developers uint64_t data; 39210037SARM gem5 Developers 39310037SARM gem5 Developers /** This entry has been modified (access flag set) and needs to be 39410037SARM gem5 Developers * written back to memory */ 39510037SARM gem5 Developers bool _dirty; 39610037SARM gem5 Developers 39710037SARM gem5 Developers virtual uint64_t getRawData() const 39810037SARM gem5 Developers { 39910037SARM gem5 Developers return (data); 40010037SARM gem5 Developers } 40110037SARM gem5 Developers 40210037SARM gem5 Developers virtual std::string dbgHeader() const 40310037SARM gem5 Developers { 40410037SARM gem5 Developers if (type() == LongDescriptor::Page) { 40510037SARM gem5 Developers assert(lookupLevel == L3); 40610037SARM gem5 Developers return "Inserting Page descriptor into TLB\n"; 40710037SARM gem5 Developers } else { 40810037SARM gem5 Developers assert(lookupLevel < L3); 40910037SARM gem5 Developers return "Inserting Block descriptor into TLB\n"; 41010037SARM gem5 Developers } 41110037SARM gem5 Developers } 41210037SARM gem5 Developers 41310037SARM gem5 Developers /** 41410037SARM gem5 Developers * Returns true if this entry targets the secure physical address 41510037SARM gem5 Developers * map. 41610037SARM gem5 Developers */ 41710037SARM gem5 Developers bool secure(bool have_security, WalkerState *currState) const 41810037SARM gem5 Developers { 41910037SARM gem5 Developers assert(type() == Block || type() == Page); 42010037SARM gem5 Developers return have_security && (currState->secureLookup && !bits(data, 5)); 42110037SARM gem5 Developers } 42210037SARM gem5 Developers 42310037SARM gem5 Developers /** True if the current lookup is performed in AArch64 state */ 42410037SARM gem5 Developers bool aarch64; 42510037SARM gem5 Developers 42610037SARM gem5 Developers /** Width of the granule size in bits */ 42710324SCurtis.Dunham@arm.com GrainSize grainSize; 42810037SARM gem5 Developers 42910037SARM gem5 Developers /** Return the descriptor type */ 43010037SARM gem5 Developers EntryType type() const 43110037SARM gem5 Developers { 43210037SARM gem5 Developers switch (bits(data, 1, 0)) { 43310037SARM gem5 Developers case 0x1: 43410037SARM gem5 Developers // In AArch64 blocks are not allowed at L0 for the 4 KB granule 43510324SCurtis.Dunham@arm.com // and at L1 for 16/64 KB granules 43610324SCurtis.Dunham@arm.com if (grainSize > Grain4KB) 43710037SARM gem5 Developers return lookupLevel == L2 ? Block : Invalid; 43810037SARM gem5 Developers return lookupLevel == L0 || lookupLevel == L3 ? Invalid : Block; 43910037SARM gem5 Developers case 0x3: 44010037SARM gem5 Developers return lookupLevel == L3 ? Page : Table; 44110037SARM gem5 Developers default: 44210037SARM gem5 Developers return Invalid; 44310037SARM gem5 Developers } 44410037SARM gem5 Developers } 44510037SARM gem5 Developers 44610037SARM gem5 Developers /** Return the bit width of the page/block offset */ 44710037SARM gem5 Developers uint8_t offsetBits() const 44810037SARM gem5 Developers { 44910324SCurtis.Dunham@arm.com if (type() == Block) { 45010324SCurtis.Dunham@arm.com switch (grainSize) { 45110324SCurtis.Dunham@arm.com case Grain4KB: 45210324SCurtis.Dunham@arm.com return lookupLevel == L1 ? 30 /* 1 GB */ 45310324SCurtis.Dunham@arm.com : 21 /* 2 MB */; 45410324SCurtis.Dunham@arm.com case Grain16KB: 45510324SCurtis.Dunham@arm.com return 25 /* 32 MB */; 45610324SCurtis.Dunham@arm.com case Grain64KB: 45710324SCurtis.Dunham@arm.com return 29 /* 512 MB */; 45810324SCurtis.Dunham@arm.com default: 45910324SCurtis.Dunham@arm.com panic("Invalid AArch64 VM granule size\n"); 46010324SCurtis.Dunham@arm.com } 46110324SCurtis.Dunham@arm.com } else if (type() == Page) { 46210324SCurtis.Dunham@arm.com switch (grainSize) { 46310324SCurtis.Dunham@arm.com case Grain4KB: 46410324SCurtis.Dunham@arm.com case Grain16KB: 46510324SCurtis.Dunham@arm.com case Grain64KB: 46610324SCurtis.Dunham@arm.com return grainSize; /* enum -> uint okay */ 46710324SCurtis.Dunham@arm.com default: 46810324SCurtis.Dunham@arm.com panic("Invalid AArch64 VM granule size\n"); 46910324SCurtis.Dunham@arm.com } 47010037SARM gem5 Developers } else { 47110324SCurtis.Dunham@arm.com panic("AArch64 page table entry must be block or page\n"); 47210037SARM gem5 Developers } 47310037SARM gem5 Developers } 47410037SARM gem5 Developers 47510037SARM gem5 Developers /** Return the physical frame, bits shifted right */ 47610037SARM gem5 Developers Addr pfn() const 47710037SARM gem5 Developers { 47810037SARM gem5 Developers if (aarch64) 47910037SARM gem5 Developers return bits(data, 47, offsetBits()); 48010037SARM gem5 Developers return bits(data, 39, offsetBits()); 48110037SARM gem5 Developers } 48210037SARM gem5 Developers 48310037SARM gem5 Developers /** Return the complete physical address given a VA */ 48410037SARM gem5 Developers Addr paddr(Addr va) const 48510037SARM gem5 Developers { 48610037SARM gem5 Developers int n = offsetBits(); 48710037SARM gem5 Developers if (aarch64) 48810037SARM gem5 Developers return mbits(data, 47, n) | mbits(va, n - 1, 0); 48910037SARM gem5 Developers return mbits(data, 39, n) | mbits(va, n - 1, 0); 49010037SARM gem5 Developers } 49110037SARM gem5 Developers 49210037SARM gem5 Developers /** Return the physical address of the entry */ 49310037SARM gem5 Developers Addr paddr() const 49410037SARM gem5 Developers { 49510037SARM gem5 Developers if (aarch64) 49610037SARM gem5 Developers return mbits(data, 47, offsetBits()); 49710037SARM gem5 Developers return mbits(data, 39, offsetBits()); 49810037SARM gem5 Developers } 49910037SARM gem5 Developers 50010037SARM gem5 Developers /** Return the address of the next page table */ 50110037SARM gem5 Developers Addr nextTableAddr() const 50210037SARM gem5 Developers { 50310037SARM gem5 Developers assert(type() == Table); 50410037SARM gem5 Developers if (aarch64) 50510037SARM gem5 Developers return mbits(data, 47, grainSize); 50610037SARM gem5 Developers else 50710037SARM gem5 Developers return mbits(data, 39, 12); 50810037SARM gem5 Developers } 50910037SARM gem5 Developers 51010037SARM gem5 Developers /** Return the address of the next descriptor */ 51110037SARM gem5 Developers Addr nextDescAddr(Addr va) const 51210037SARM gem5 Developers { 51310037SARM gem5 Developers assert(type() == Table); 51410037SARM gem5 Developers Addr pa = 0; 51510037SARM gem5 Developers if (aarch64) { 51610037SARM gem5 Developers int stride = grainSize - 3; 51710037SARM gem5 Developers int va_lo = stride * (3 - (lookupLevel + 1)) + grainSize; 51810037SARM gem5 Developers int va_hi = va_lo + stride - 1; 51910037SARM gem5 Developers pa = nextTableAddr() | (bits(va, va_hi, va_lo) << 3); 52010037SARM gem5 Developers } else { 52110037SARM gem5 Developers if (lookupLevel == L1) 52210037SARM gem5 Developers pa = nextTableAddr() | (bits(va, 29, 21) << 3); 52310037SARM gem5 Developers else // lookupLevel == L2 52410037SARM gem5 Developers pa = nextTableAddr() | (bits(va, 20, 12) << 3); 52510037SARM gem5 Developers } 52610037SARM gem5 Developers return pa; 52710037SARM gem5 Developers } 52810037SARM gem5 Developers 52910037SARM gem5 Developers /** Is execution allowed on this mapping? */ 53010037SARM gem5 Developers bool xn() const 53110037SARM gem5 Developers { 53210037SARM gem5 Developers assert(type() == Block || type() == Page); 53310037SARM gem5 Developers return bits(data, 54); 53410037SARM gem5 Developers } 53510037SARM gem5 Developers 53610037SARM gem5 Developers /** Is privileged execution allowed on this mapping? (LPAE only) */ 53710037SARM gem5 Developers bool pxn() const 53810037SARM gem5 Developers { 53910037SARM gem5 Developers assert(type() == Block || type() == Page); 54010037SARM gem5 Developers return bits(data, 53); 54110037SARM gem5 Developers } 54210037SARM gem5 Developers 54310037SARM gem5 Developers /** Contiguous hint bit. */ 54410037SARM gem5 Developers bool contiguousHint() const 54510037SARM gem5 Developers { 54610037SARM gem5 Developers assert(type() == Block || type() == Page); 54710037SARM gem5 Developers return bits(data, 52); 54810037SARM gem5 Developers } 54910037SARM gem5 Developers 55010037SARM gem5 Developers /** Is the translation global (no asid used)? */ 55110037SARM gem5 Developers bool global(WalkerState *currState) const 55210037SARM gem5 Developers { 55310037SARM gem5 Developers assert(currState && (type() == Block || type() == Page)); 55410037SARM gem5 Developers if (!currState->aarch64 && (currState->isSecure && 55510037SARM gem5 Developers !currState->secureLookup)) { 55610037SARM gem5 Developers return false; // ARM ARM issue C B3.6.3 55710037SARM gem5 Developers } else if (currState->aarch64) { 55810037SARM gem5 Developers if (currState->el == EL2 || currState->el == EL3) { 55910037SARM gem5 Developers return true; // By default translations are treated as global 56010037SARM gem5 Developers // in AArch64 EL2 and EL3 56110037SARM gem5 Developers } else if (currState->isSecure && !currState->secureLookup) { 56210037SARM gem5 Developers return false; 56310037SARM gem5 Developers } 56410037SARM gem5 Developers } 56510037SARM gem5 Developers return !bits(data, 11); 56610037SARM gem5 Developers } 56710037SARM gem5 Developers 56810037SARM gem5 Developers /** Returns true if the access flag (AF) is set. */ 56910037SARM gem5 Developers bool af() const 57010037SARM gem5 Developers { 57110037SARM gem5 Developers assert(type() == Block || type() == Page); 57210037SARM gem5 Developers return bits(data, 10); 57310037SARM gem5 Developers } 57410037SARM gem5 Developers 57510037SARM gem5 Developers /** 2-bit shareability field */ 57610037SARM gem5 Developers uint8_t sh() const 57710037SARM gem5 Developers { 57810037SARM gem5 Developers assert(type() == Block || type() == Page); 57910037SARM gem5 Developers return bits(data, 9, 8); 58010037SARM gem5 Developers } 58110037SARM gem5 Developers 58210037SARM gem5 Developers /** 2-bit access protection flags */ 58310037SARM gem5 Developers uint8_t ap() const 58410037SARM gem5 Developers { 58510037SARM gem5 Developers assert(type() == Block || type() == Page); 58610037SARM gem5 Developers // Long descriptors only support the AP[2:1] scheme 58710037SARM gem5 Developers return bits(data, 7, 6); 58810037SARM gem5 Developers } 58910037SARM gem5 Developers 59010037SARM gem5 Developers /** Read/write access protection flag */ 59110037SARM gem5 Developers bool rw() const 59210037SARM gem5 Developers { 59310037SARM gem5 Developers assert(type() == Block || type() == Page); 59410037SARM gem5 Developers return !bits(data, 7); 59510037SARM gem5 Developers } 59610037SARM gem5 Developers 59710037SARM gem5 Developers /** User/privileged level access protection flag */ 59810037SARM gem5 Developers bool user() const 59910037SARM gem5 Developers { 60010037SARM gem5 Developers assert(type() == Block || type() == Page); 60110037SARM gem5 Developers return bits(data, 6); 60210037SARM gem5 Developers } 60310037SARM gem5 Developers 60410037SARM gem5 Developers /** Return the AP bits as compatible with the AP[2:0] format. Utility 60510037SARM gem5 Developers * function used to simplify the code in the TLB for performing 60610037SARM gem5 Developers * permission checks. */ 60710037SARM gem5 Developers static uint8_t ap(bool rw, bool user) 60810037SARM gem5 Developers { 60910037SARM gem5 Developers return ((!rw) << 2) | (user << 1); 61010037SARM gem5 Developers } 61110037SARM gem5 Developers 61210037SARM gem5 Developers TlbEntry::DomainType domain() const 61310037SARM gem5 Developers { 61410037SARM gem5 Developers // Long-desc. format only supports Client domain 61510037SARM gem5 Developers assert(type() == Block || type() == Page); 61610037SARM gem5 Developers return TlbEntry::DomainType::Client; 61710037SARM gem5 Developers } 61810037SARM gem5 Developers 61910037SARM gem5 Developers /** Attribute index */ 62010037SARM gem5 Developers uint8_t attrIndx() const 62110037SARM gem5 Developers { 62210037SARM gem5 Developers assert(type() == Block || type() == Page); 62310037SARM gem5 Developers return bits(data, 4, 2); 62410037SARM gem5 Developers } 62510037SARM gem5 Developers 62610037SARM gem5 Developers /** Memory attributes, only used by stage 2 translations */ 62710037SARM gem5 Developers uint8_t memAttr() const 62810037SARM gem5 Developers { 62910037SARM gem5 Developers assert(type() == Block || type() == Page); 63010037SARM gem5 Developers return bits(data, 5, 2); 63110037SARM gem5 Developers } 63210037SARM gem5 Developers 63310037SARM gem5 Developers /** Set access flag that this entry has been touched. Mark the entry as 63410037SARM gem5 Developers * requiring a writeback, in the future. */ 63510037SARM gem5 Developers void setAf() 63610037SARM gem5 Developers { 63710037SARM gem5 Developers data |= 1 << 10; 63810037SARM gem5 Developers _dirty = true; 63910037SARM gem5 Developers } 64010037SARM gem5 Developers 64110037SARM gem5 Developers /** This entry needs to be written back to memory */ 64210037SARM gem5 Developers bool dirty() const 64310037SARM gem5 Developers { 64410037SARM gem5 Developers return _dirty; 64510037SARM gem5 Developers } 64610037SARM gem5 Developers 64710037SARM gem5 Developers /** Whether the subsequent levels of lookup are secure */ 64810037SARM gem5 Developers bool secureTable() const 64910037SARM gem5 Developers { 65010037SARM gem5 Developers assert(type() == Table); 65110037SARM gem5 Developers return !bits(data, 63); 65210037SARM gem5 Developers } 65310037SARM gem5 Developers 65410037SARM gem5 Developers /** Two bit access protection flags for subsequent levels of lookup */ 65510037SARM gem5 Developers uint8_t apTable() const 65610037SARM gem5 Developers { 65710037SARM gem5 Developers assert(type() == Table); 65810037SARM gem5 Developers return bits(data, 62, 61); 65910037SARM gem5 Developers } 66010037SARM gem5 Developers 66110037SARM gem5 Developers /** R/W protection flag for subsequent levels of lookup */ 66210037SARM gem5 Developers uint8_t rwTable() const 66310037SARM gem5 Developers { 66410037SARM gem5 Developers assert(type() == Table); 66510037SARM gem5 Developers return !bits(data, 62); 66610037SARM gem5 Developers } 66710037SARM gem5 Developers 66810037SARM gem5 Developers /** User/privileged mode protection flag for subsequent levels of 66910037SARM gem5 Developers * lookup */ 67010037SARM gem5 Developers uint8_t userTable() const 67110037SARM gem5 Developers { 67210037SARM gem5 Developers assert(type() == Table); 67310037SARM gem5 Developers return !bits(data, 61); 67410037SARM gem5 Developers } 67510037SARM gem5 Developers 67610037SARM gem5 Developers /** Is execution allowed on subsequent lookup levels? */ 67710037SARM gem5 Developers bool xnTable() const 67810037SARM gem5 Developers { 67910037SARM gem5 Developers assert(type() == Table); 68010037SARM gem5 Developers return bits(data, 60); 68110037SARM gem5 Developers } 68210037SARM gem5 Developers 68310037SARM gem5 Developers /** Is privileged execution allowed on subsequent lookup levels? */ 68410037SARM gem5 Developers bool pxnTable() const 68510037SARM gem5 Developers { 68610037SARM gem5 Developers assert(type() == Table); 68710037SARM gem5 Developers return bits(data, 59); 68810037SARM gem5 Developers } 68910037SARM gem5 Developers }; 69010037SARM gem5 Developers 69110037SARM gem5 Developers class WalkerState 69210037SARM gem5 Developers { 69310037SARM gem5 Developers public: 69410037SARM gem5 Developers /** Thread context that we're doing the walk for */ 69510037SARM gem5 Developers ThreadContext *tc; 69610037SARM gem5 Developers 69710037SARM gem5 Developers /** If the access is performed in AArch64 state */ 69810037SARM gem5 Developers bool aarch64; 69910037SARM gem5 Developers 70010037SARM gem5 Developers /** Current exception level */ 70110037SARM gem5 Developers ExceptionLevel el; 70210037SARM gem5 Developers 70310037SARM gem5 Developers /** Current physical address range in bits */ 70410037SARM gem5 Developers int physAddrRange; 70510037SARM gem5 Developers 70610037SARM gem5 Developers /** Request that is currently being serviced */ 70710037SARM gem5 Developers RequestPtr req; 70810037SARM gem5 Developers 70910037SARM gem5 Developers /** ASID that we're servicing the request under */ 71010037SARM gem5 Developers uint16_t asid; 71110037SARM gem5 Developers uint8_t vmid; 71210037SARM gem5 Developers bool isHyp; 71310037SARM gem5 Developers 71410037SARM gem5 Developers /** Translation state for delayed requests */ 71510037SARM gem5 Developers TLB::Translation *transState; 71610037SARM gem5 Developers 71710037SARM gem5 Developers /** The fault that we are going to return */ 71810037SARM gem5 Developers Fault fault; 71910037SARM gem5 Developers 72010037SARM gem5 Developers /** The virtual address that is being translated with tagging removed.*/ 72110037SARM gem5 Developers Addr vaddr; 72210037SARM gem5 Developers 72310037SARM gem5 Developers /** The virtual address that is being translated */ 72410037SARM gem5 Developers Addr vaddr_tainted; 72510037SARM gem5 Developers 72610037SARM gem5 Developers /** Cached copy of the sctlr as it existed when translation began */ 72710037SARM gem5 Developers SCTLR sctlr; 72810037SARM gem5 Developers 72910037SARM gem5 Developers /** Cached copy of the scr as it existed when translation began */ 73010037SARM gem5 Developers SCR scr; 73110037SARM gem5 Developers 73210037SARM gem5 Developers /** Cached copy of the cpsr as it existed when translation began */ 73310037SARM gem5 Developers CPSR cpsr; 73410037SARM gem5 Developers 73510324SCurtis.Dunham@arm.com /** Cached copy of ttbcr/tcr as it existed when translation began */ 73610324SCurtis.Dunham@arm.com union { 73710324SCurtis.Dunham@arm.com TTBCR ttbcr; // AArch32 translations 73810324SCurtis.Dunham@arm.com TCR tcr; // AArch64 translations 73910324SCurtis.Dunham@arm.com }; 74010037SARM gem5 Developers 74110037SARM gem5 Developers /** Cached copy of the htcr as it existed when translation began. */ 74210037SARM gem5 Developers HTCR htcr; 74310037SARM gem5 Developers 74410037SARM gem5 Developers /** Cached copy of the htcr as it existed when translation began. */ 74510037SARM gem5 Developers HCR hcr; 74610037SARM gem5 Developers 74710037SARM gem5 Developers /** Cached copy of the vtcr as it existed when translation began. */ 74810037SARM gem5 Developers VTCR_t vtcr; 74910037SARM gem5 Developers 75010037SARM gem5 Developers /** If the access is a write */ 75110037SARM gem5 Developers bool isWrite; 75210037SARM gem5 Developers 75310037SARM gem5 Developers /** If the access is a fetch (for execution, and no-exec) must be checked?*/ 75410037SARM gem5 Developers bool isFetch; 75510037SARM gem5 Developers 75610037SARM gem5 Developers /** If the access comes from the secure state. */ 75710037SARM gem5 Developers bool isSecure; 75810037SARM gem5 Developers 75910037SARM gem5 Developers /** Helper variables used to implement hierarchical access permissions 76010037SARM gem5 Developers * when the long-desc. format is used (LPAE only) */ 76110037SARM gem5 Developers bool secureLookup; 76210037SARM gem5 Developers bool rwTable; 76310037SARM gem5 Developers bool userTable; 76410037SARM gem5 Developers bool xnTable; 76510037SARM gem5 Developers bool pxnTable; 76610037SARM gem5 Developers 76714095Sgiacomo.travaglini@arm.com /** Hierarchical access permission disable */ 76814095Sgiacomo.travaglini@arm.com bool hpd; 76914095Sgiacomo.travaglini@arm.com 77010037SARM gem5 Developers /** Flag indicating if a second stage of lookup is required */ 77110037SARM gem5 Developers bool stage2Req; 77210037SARM gem5 Developers 77310037SARM gem5 Developers /** A pointer to the stage 2 translation that's in progress */ 77410037SARM gem5 Developers TLB::Translation *stage2Tran; 77510037SARM gem5 Developers 77610037SARM gem5 Developers /** If the mode is timing or atomic */ 77710037SARM gem5 Developers bool timing; 77810037SARM gem5 Developers 77910037SARM gem5 Developers /** If the atomic mode should be functional */ 78010037SARM gem5 Developers bool functional; 78110037SARM gem5 Developers 78210037SARM gem5 Developers /** Save mode for use in delayed response */ 78310037SARM gem5 Developers BaseTLB::Mode mode; 78410037SARM gem5 Developers 78510037SARM gem5 Developers /** The translation type that has been requested */ 78610037SARM gem5 Developers TLB::ArmTranslationType tranType; 78710037SARM gem5 Developers 78810037SARM gem5 Developers /** Short-format descriptors */ 78910037SARM gem5 Developers L1Descriptor l1Desc; 79010037SARM gem5 Developers L2Descriptor l2Desc; 79110037SARM gem5 Developers 79210037SARM gem5 Developers /** Long-format descriptor (LPAE and AArch64) */ 79310037SARM gem5 Developers LongDescriptor longDesc; 79410037SARM gem5 Developers 79510037SARM gem5 Developers /** Whether the response is delayed in timing mode due to additional 79610037SARM gem5 Developers * lookups */ 79710037SARM gem5 Developers bool delayed; 79810037SARM gem5 Developers 79910037SARM gem5 Developers TableWalker *tableWalker; 80010037SARM gem5 Developers 80110621SCurtis.Dunham@arm.com /** Timestamp for calculating elapsed time in service (for stats) */ 80210621SCurtis.Dunham@arm.com Tick startTime; 80310621SCurtis.Dunham@arm.com 80410621SCurtis.Dunham@arm.com /** Page entries walked during service (for stats) */ 80510621SCurtis.Dunham@arm.com unsigned levels; 80610621SCurtis.Dunham@arm.com 80710037SARM gem5 Developers void doL1Descriptor(); 80810037SARM gem5 Developers void doL2Descriptor(); 80910037SARM gem5 Developers 81010037SARM gem5 Developers void doLongDescriptor(); 81110037SARM gem5 Developers 81210037SARM gem5 Developers WalkerState(); 81310037SARM gem5 Developers 81410037SARM gem5 Developers std::string name() const { return tableWalker->name(); } 81510037SARM gem5 Developers }; 81610037SARM gem5 Developers 8179015Sandreas.hansson@arm.com protected: 8189015Sandreas.hansson@arm.com 81910037SARM gem5 Developers /** Queues of requests for all the different lookup levels */ 82010037SARM gem5 Developers std::list<WalkerState *> stateQueues[MAX_LOOKUP_LEVELS]; 8217439Sdam.sunwoo@arm.com 8227728SAli.Saidi@ARM.com /** Queue of requests that have passed are waiting because the walker is 8237728SAli.Saidi@ARM.com * currently busy. */ 8248902Sandreas.hansson@arm.com std::list<WalkerState *> pendingQueue; 8257728SAli.Saidi@ARM.com 82610037SARM gem5 Developers /** The MMU to forward second stage look upts to */ 82710037SARM gem5 Developers Stage2MMU *stage2Mmu; 82810037SARM gem5 Developers 82910717Sandreas.hansson@arm.com /** Port shared by the two table walkers. */ 83010717Sandreas.hansson@arm.com DmaPort* port; 83110717Sandreas.hansson@arm.com 83210717Sandreas.hansson@arm.com /** Master id assigned by the MMU. */ 83310717Sandreas.hansson@arm.com MasterID masterId; 83410717Sandreas.hansson@arm.com 83510037SARM gem5 Developers /** Indicates whether this table walker is part of the stage 2 mmu */ 83610037SARM gem5 Developers const bool isStage2; 83710037SARM gem5 Developers 8387404SAli.Saidi@ARM.com /** TLB that is initiating these table walks */ 8397404SAli.Saidi@ARM.com TLB *tlb; 8407404SAli.Saidi@ARM.com 8417404SAli.Saidi@ARM.com /** Cached copy of the sctlr as it existed when translation began */ 8427404SAli.Saidi@ARM.com SCTLR sctlr; 8437404SAli.Saidi@ARM.com 8447439Sdam.sunwoo@arm.com WalkerState *currState; 8457437Sdam.sunwoo@arm.com 8467728SAli.Saidi@ARM.com /** If a timing translation is currently in progress */ 8477728SAli.Saidi@ARM.com bool pending; 8487728SAli.Saidi@ARM.com 8499258SAli.Saidi@ARM.com /** The number of walks belonging to squashed instructions that can be 8509258SAli.Saidi@ARM.com * removed from the pendingQueue per cycle. */ 8519258SAli.Saidi@ARM.com unsigned numSquashable; 8529258SAli.Saidi@ARM.com 85310037SARM gem5 Developers /** Cached copies of system-level properties */ 85410037SARM gem5 Developers bool haveSecurity; 85510037SARM gem5 Developers bool _haveLPAE; 85610037SARM gem5 Developers bool _haveVirtualization; 85710037SARM gem5 Developers uint8_t physAddrRange; 85810037SARM gem5 Developers bool _haveLargeAsid64; 85910037SARM gem5 Developers 86010621SCurtis.Dunham@arm.com /** Statistics */ 86110621SCurtis.Dunham@arm.com Stats::Scalar statWalks; 86210621SCurtis.Dunham@arm.com Stats::Scalar statWalksShortDescriptor; 86310621SCurtis.Dunham@arm.com Stats::Scalar statWalksLongDescriptor; 86410621SCurtis.Dunham@arm.com Stats::Vector statWalksShortTerminatedAtLevel; 86510621SCurtis.Dunham@arm.com Stats::Vector statWalksLongTerminatedAtLevel; 86610621SCurtis.Dunham@arm.com Stats::Scalar statSquashedBefore; 86710621SCurtis.Dunham@arm.com Stats::Scalar statSquashedAfter; 86810621SCurtis.Dunham@arm.com Stats::Histogram statWalkWaitTime; 86910621SCurtis.Dunham@arm.com Stats::Histogram statWalkServiceTime; 87010621SCurtis.Dunham@arm.com Stats::Histogram statPendingWalks; // essentially "L" of queueing theory 87110621SCurtis.Dunham@arm.com Stats::Vector statPageSizes; 87210621SCurtis.Dunham@arm.com Stats::Vector2d statRequestOrigin; 87310621SCurtis.Dunham@arm.com 87410621SCurtis.Dunham@arm.com mutable unsigned pendingReqs; 87510621SCurtis.Dunham@arm.com mutable Tick pendingChangeTick; 87610621SCurtis.Dunham@arm.com 87710621SCurtis.Dunham@arm.com static const unsigned REQUESTED = 0; 87810621SCurtis.Dunham@arm.com static const unsigned COMPLETED = 1; 87910621SCurtis.Dunham@arm.com 8807404SAli.Saidi@ARM.com public: 88110037SARM gem5 Developers typedef ArmTableWalkerParams Params; 8827404SAli.Saidi@ARM.com TableWalker(const Params *p); 8837404SAli.Saidi@ARM.com virtual ~TableWalker(); 8847404SAli.Saidi@ARM.com 8857404SAli.Saidi@ARM.com const Params * 8867404SAli.Saidi@ARM.com params() const 8877404SAli.Saidi@ARM.com { 8887404SAli.Saidi@ARM.com return dynamic_cast<const Params *>(_params); 8897404SAli.Saidi@ARM.com } 8907404SAli.Saidi@ARM.com 89111169Sandreas.hansson@arm.com void init() override; 89210717Sandreas.hansson@arm.com 89310037SARM gem5 Developers bool haveLPAE() const { return _haveLPAE; } 89410037SARM gem5 Developers bool haveVirtualization() const { return _haveVirtualization; } 89510037SARM gem5 Developers bool haveLargeAsid64() const { return _haveLargeAsid64; } 8969152Satgutier@umich.edu /** Checks if all state is cleared and if so, completes drain */ 8979152Satgutier@umich.edu void completeDrain(); 89811168Sandreas.hansson@arm.com DrainState drain() override; 89911169Sandreas.hansson@arm.com void drainResume() override; 90010717Sandreas.hansson@arm.com 90113784Sgabeblack@google.com Port &getPort(const std::string &if_name, 90213784Sgabeblack@google.com PortID idx=InvalidPortID) override; 90310717Sandreas.hansson@arm.com 90411169Sandreas.hansson@arm.com void regStats() override; 9057404SAli.Saidi@ARM.com 90612749Sgiacomo.travaglini@arm.com Fault walk(const RequestPtr &req, ThreadContext *tc, 90712749Sgiacomo.travaglini@arm.com uint16_t asid, uint8_t _vmid, 90810037SARM gem5 Developers bool _isHyp, TLB::Mode mode, TLB::Translation *_trans, 90910037SARM gem5 Developers bool timing, bool functional, bool secure, 91011580SDylan.Johnson@ARM.com TLB::ArmTranslationType tranType, bool _stage2Req); 9117404SAli.Saidi@ARM.com 9127404SAli.Saidi@ARM.com void setTlb(TLB *_tlb) { tlb = _tlb; } 91310037SARM gem5 Developers TLB* getTlb() { return tlb; } 91410717Sandreas.hansson@arm.com void setMMU(Stage2MMU *m, MasterID master_id); 9157439Sdam.sunwoo@arm.com void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, 9167439Sdam.sunwoo@arm.com uint8_t texcb, bool s); 91710037SARM gem5 Developers void memAttrsLPAE(ThreadContext *tc, TlbEntry &te, 91810037SARM gem5 Developers LongDescriptor &lDescriptor); 91911583SDylan.Johnson@ARM.com void memAttrsAArch64(ThreadContext *tc, TlbEntry &te, 92011583SDylan.Johnson@ARM.com LongDescriptor &lDescriptor); 92110037SARM gem5 Developers 92210037SARM gem5 Developers static LookupLevel toLookupLevel(uint8_t lookup_level_as_int); 9237404SAli.Saidi@ARM.com 9247404SAli.Saidi@ARM.com private: 9257404SAli.Saidi@ARM.com 9267404SAli.Saidi@ARM.com void doL1Descriptor(); 9277437Sdam.sunwoo@arm.com void doL1DescriptorWrapper(); 92812086Sspwilson2@wisc.edu EventFunctionWrapper doL1DescEvent; 9297404SAli.Saidi@ARM.com 9307404SAli.Saidi@ARM.com void doL2Descriptor(); 9317437Sdam.sunwoo@arm.com void doL2DescriptorWrapper(); 93212086Sspwilson2@wisc.edu EventFunctionWrapper doL2DescEvent; 93310037SARM gem5 Developers 93410037SARM gem5 Developers void doLongDescriptor(); 93510037SARM gem5 Developers 93610037SARM gem5 Developers void doL0LongDescriptorWrapper(); 93712086Sspwilson2@wisc.edu EventFunctionWrapper doL0LongDescEvent; 93810037SARM gem5 Developers void doL1LongDescriptorWrapper(); 93912086Sspwilson2@wisc.edu EventFunctionWrapper doL1LongDescEvent; 94010037SARM gem5 Developers void doL2LongDescriptorWrapper(); 94112086Sspwilson2@wisc.edu EventFunctionWrapper doL2LongDescEvent; 94210037SARM gem5 Developers void doL3LongDescriptorWrapper(); 94312086Sspwilson2@wisc.edu EventFunctionWrapper doL3LongDescEvent; 94410037SARM gem5 Developers 94510037SARM gem5 Developers void doLongDescriptorWrapper(LookupLevel curr_lookup_level); 94611588SCurtis.Dunham@arm.com Event* LongDescEventByLevel[4]; 94710037SARM gem5 Developers 94810037SARM gem5 Developers bool fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes, 94910037SARM gem5 Developers Request::Flags flags, int queueIndex, Event *event, 95010037SARM gem5 Developers void (TableWalker::*doDescriptor)()); 95110037SARM gem5 Developers 95214093Sgiacomo.travaglini@arm.com Fault generateLongDescFault(ArmFault::FaultSource src); 95314093Sgiacomo.travaglini@arm.com 95410037SARM gem5 Developers void insertTableEntry(DescriptorBase &descriptor, bool longDescriptor); 9557404SAli.Saidi@ARM.com 9567728SAli.Saidi@ARM.com Fault processWalk(); 95710037SARM gem5 Developers Fault processWalkLPAE(); 95810037SARM gem5 Developers static unsigned adjustTableSizeAArch64(unsigned tsz); 95910037SARM gem5 Developers /// Returns true if the address exceeds the range permitted by the 96010037SARM gem5 Developers /// system-wide setting or by the TCR_ELx IPS/PS setting 96110037SARM gem5 Developers static bool checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange); 96210037SARM gem5 Developers Fault processWalkAArch64(); 9637728SAli.Saidi@ARM.com void processWalkWrapper(); 96412086Sspwilson2@wisc.edu EventFunctionWrapper doProcessEvent; 9657404SAli.Saidi@ARM.com 9667728SAli.Saidi@ARM.com void nextWalk(ThreadContext *tc); 96710621SCurtis.Dunham@arm.com 96810621SCurtis.Dunham@arm.com void pendingChange(); 96910621SCurtis.Dunham@arm.com 97010621SCurtis.Dunham@arm.com static uint8_t pageSizeNtoStatBin(uint8_t N); 97111395Sandreas.sandberg@arm.com 97211395Sandreas.sandberg@arm.com Fault testWalk(Addr pa, Addr size, TlbEntry::DomainType domain, 97311395Sandreas.sandberg@arm.com LookupLevel lookup_level); 9747404SAli.Saidi@ARM.com}; 9757404SAli.Saidi@ARM.com 9767404SAli.Saidi@ARM.com} // namespace ArmISA 9777404SAli.Saidi@ARM.com 9787404SAli.Saidi@ARM.com#endif //__ARCH_ARM_TABLE_WALKER_HH__ 9797404SAli.Saidi@ARM.com 980