table_walker.hh revision 13784
13691SN/A/*
23691SN/A * Copyright (c) 2010-2016 ARM Limited
39449SAli.Saidi@ARM.com * All rights reserved
49729Sandreas.hansson@arm.com *
59729Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
68721SN/A * not be construed as granting a license to any other intellectual
79729Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
89729Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
99729Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
109729Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
119729Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
129729Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
139729Sandreas.hansson@arm.com *
149729Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
159729Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
169729Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
179729Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
189729Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
199729Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
209729Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
219055Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its
229729Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
239729Sandreas.hansson@arm.com * this software without specific prior written permission.
249729Sandreas.hansson@arm.com *
259729Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
269729Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
279729Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
289055Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
299729Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
309729Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
319729Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
329729Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
339729Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
349729Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
359729Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
369729Sandreas.hansson@arm.com *
379247Sandreas.hansson@arm.com * Authors: Ali Saidi
389729Sandreas.hansson@arm.com *          Giacomo Gabrielli
399729Sandreas.hansson@arm.com */
409729Sandreas.hansson@arm.com
419729Sandreas.hansson@arm.com#ifndef __ARCH_ARM_TABLE_WALKER_HH__
429729Sandreas.hansson@arm.com#define __ARCH_ARM_TABLE_WALKER_HH__
439729Sandreas.hansson@arm.com
449729Sandreas.hansson@arm.com#include <list>
459729Sandreas.hansson@arm.com
468721SN/A#include "arch/arm/miscregs.hh"
478721SN/A#include "arch/arm/system.hh"
488721SN/A#include "arch/arm/tlb.hh"
498721SN/A#include "mem/request.hh"
508721SN/A#include "params/ArmTableWalker.hh"
518721SN/A#include "sim/eventq.hh"
528721SN/A
538721SN/Aclass ThreadContext;
548721SN/A
558721SN/Aclass DmaPort;
568721SN/A
578721SN/Anamespace ArmISA {
588721SN/Aclass Translation;
598721SN/Aclass TLB;
608721SN/Aclass Stage2MMU;
618721SN/A
629729Sandreas.hansson@arm.comclass TableWalker : public MemObject
638721SN/A{
648721SN/A  public:
658721SN/A    class WalkerState;
669729Sandreas.hansson@arm.com
678721SN/A    class DescriptorBase {
688721SN/A      public:
698721SN/A        /** Current lookup level for this descriptor */
709729Sandreas.hansson@arm.com        LookupLevel lookupLevel;
716024SN/A
728721SN/A        virtual Addr pfn() const = 0;
738721SN/A        virtual TlbEntry::DomainType domain() const = 0;
749729Sandreas.hansson@arm.com        virtual bool xn() const = 0;
758721SN/A        virtual uint8_t ap() const = 0;
768721SN/A        virtual bool global(WalkerState *currState) const = 0;
779729Sandreas.hansson@arm.com        virtual uint8_t offsetBits() const = 0;
788721SN/A        virtual bool secure(bool have_security, WalkerState *currState) const = 0;
798721SN/A        virtual std::string dbgHeader() const = 0;
808721SN/A        virtual uint64_t getRawData() const = 0;
818721SN/A        virtual uint8_t texcb() const
828721SN/A        {
838721SN/A            panic("texcb() not implemented for this class\n");
848721SN/A        }
858721SN/A        virtual bool shareable() const
866024SN/A        {
876024SN/A            panic("shareable() not implemented for this class\n");
888721SN/A        }
898721SN/A    };
909729Sandreas.hansson@arm.com
918721SN/A    class L1Descriptor : public DescriptorBase {
928721SN/A      public:
939729Sandreas.hansson@arm.com        /** Type of page table entry ARM DDI 0406B: B3-8*/
949729Sandreas.hansson@arm.com        enum EntryType {
959729Sandreas.hansson@arm.com            Ignore,
969729Sandreas.hansson@arm.com            PageTable,
979729Sandreas.hansson@arm.com            Section,
989729Sandreas.hansson@arm.com            Reserved
999729Sandreas.hansson@arm.com        };
1009729Sandreas.hansson@arm.com
1019729Sandreas.hansson@arm.com        /** The raw bits of the entry */
1029729Sandreas.hansson@arm.com        uint32_t data;
1039729Sandreas.hansson@arm.com
1049729Sandreas.hansson@arm.com        /** This entry has been modified (access flag set) and needs to be
1059729Sandreas.hansson@arm.com         * written back to memory */
1069729Sandreas.hansson@arm.com        bool _dirty;
1079729Sandreas.hansson@arm.com
1089729Sandreas.hansson@arm.com        /** Default ctor */
1099729Sandreas.hansson@arm.com        L1Descriptor() : data(0), _dirty(false)
1109729Sandreas.hansson@arm.com        {
1119729Sandreas.hansson@arm.com            lookupLevel = L1;
1123691SN/A        }
1139729Sandreas.hansson@arm.com
1149729Sandreas.hansson@arm.com        virtual uint64_t getRawData() const
1159729Sandreas.hansson@arm.com        {
1169729Sandreas.hansson@arm.com            return (data);
1179449SAli.Saidi@ARM.com        }
1189729Sandreas.hansson@arm.com
1199729Sandreas.hansson@arm.com        virtual std::string dbgHeader() const
1209729Sandreas.hansson@arm.com        {
1219729Sandreas.hansson@arm.com            return "Inserting Section Descriptor into TLB\n";
1229729Sandreas.hansson@arm.com        }
1239729Sandreas.hansson@arm.com
1249729Sandreas.hansson@arm.com        virtual uint8_t offsetBits() const
1259729Sandreas.hansson@arm.com        {
1269729Sandreas.hansson@arm.com            return 20;
1279449SAli.Saidi@ARM.com        }
1289729Sandreas.hansson@arm.com
1299729Sandreas.hansson@arm.com        EntryType type() const
1309449SAli.Saidi@ARM.com        {
1316127SN/A            return (EntryType)(data & 0x3);
1326127SN/A        }
1339729Sandreas.hansson@arm.com
1349729Sandreas.hansson@arm.com        /** Is the page a Supersection (16MB)?*/
1356291SN/A        bool supersection() const
1366291SN/A        {
1376291SN/A            return bits(data, 18);
1386291SN/A        }
1396291SN/A
1406291SN/A        /** Return the physcal address of the entry, bits in position*/
1416291SN/A        Addr paddr() const
1426291SN/A        {
1436291SN/A            if (supersection())
1446291SN/A                panic("Super sections not implemented\n");
1456291SN/A            return mbits(data, 31, 20);
1466291SN/A        }
1476291SN/A        /** Return the physcal address of the entry, bits in position*/
1486291SN/A        Addr paddr(Addr va) const
1496291SN/A        {
1506291SN/A            if (supersection())
1516291SN/A                panic("Super sections not implemented\n");
1526291SN/A            return mbits(data, 31, 20) | mbits(va, 19, 0);
1536291SN/A        }
1546291SN/A
1556291SN/A
1566127SN/A        /** Return the physical frame, bits shifted right */
1579729Sandreas.hansson@arm.com        Addr pfn() const
1589449SAli.Saidi@ARM.com        {
1599729Sandreas.hansson@arm.com            if (supersection())
1609449SAli.Saidi@ARM.com                panic("Super sections not implemented\n");
1619449SAli.Saidi@ARM.com            return bits(data, 31, 20);
1629490Sandreas.hansson@arm.com        }
1639490Sandreas.hansson@arm.com
1649449SAli.Saidi@ARM.com        /** Is the translation global (no asid used)? */
1659449SAli.Saidi@ARM.com        bool global(WalkerState *currState) const
1669729Sandreas.hansson@arm.com        {
1679729Sandreas.hansson@arm.com            return !bits(data, 17);
1689729Sandreas.hansson@arm.com        }
1699729Sandreas.hansson@arm.com
1709449SAli.Saidi@ARM.com        /** Is the translation not allow execution? */
1719729Sandreas.hansson@arm.com        bool xn() const
1729729Sandreas.hansson@arm.com        {
1739729Sandreas.hansson@arm.com            return bits(data, 4);
1748721SN/A        }
1759729Sandreas.hansson@arm.com
1769490Sandreas.hansson@arm.com        /** Three bit access protection flags */
1779729Sandreas.hansson@arm.com        uint8_t ap() const
1789729Sandreas.hansson@arm.com        {
1799729Sandreas.hansson@arm.com            return (bits(data, 15) << 2) | bits(data, 11, 10);
1809729Sandreas.hansson@arm.com        }
1818721SN/A
1828721SN/A        /** Domain Client/Manager: ARM DDI 0406B: B3-31 */
1838721SN/A        TlbEntry::DomainType domain() const
1848721SN/A        {
1858721SN/A            return static_cast<TlbEntry::DomainType>(bits(data, 8, 5));
1868721SN/A        }
1878721SN/A
1888721SN/A        /** Address of L2 descriptor if it exists */
1898721SN/A        Addr l2Addr() const
1908721SN/A        {
1919729Sandreas.hansson@arm.com            return mbits(data, 31, 10);
1923691SN/A        }
1939729Sandreas.hansson@arm.com
1943691SN/A        /** Memory region attributes: ARM DDI 0406B: B3-32.
1959449SAli.Saidi@ARM.com         * These bits are largly ignored by M5 and only used to
1968721SN/A         * provide the illusion that the memory system cares about
1973691SN/A         * anything but cachable vs. uncachable.
1987461SN/A         */
1999449SAli.Saidi@ARM.com        uint8_t texcb() const
2009449SAli.Saidi@ARM.com        {
2018721SN/A            return bits(data, 2) | bits(data, 3) << 1 | bits(data, 14, 12) << 2;
2028721SN/A        }
2038721SN/A
2048721SN/A        /** If the section is shareable. See texcb() comment. */
2058721SN/A        bool shareable() const
2068721SN/A        {
2078721SN/A            return bits(data, 16);
2088721SN/A        }
2098721SN/A
2108721SN/A        /** Set access flag that this entry has been touched. Mark
2118721SN/A         * the entry as requiring a writeback, in the future.
2129247Sandreas.hansson@arm.com         */
2138721SN/A        void setAp0()
2143691SN/A        {
2158721SN/A            data |= 1 << 10;
2168721SN/A            _dirty = true;
2178721SN/A        }
2189490Sandreas.hansson@arm.com
2199247Sandreas.hansson@arm.com        /** This entry needs to be written back to memory */
2209729Sandreas.hansson@arm.com        bool dirty() const
2218721SN/A        {
2228721SN/A            return _dirty;
2238721SN/A        }
2248721SN/A
2258721SN/A        /**
2263691SN/A         * Returns true if this entry targets the secure physical address
2278721SN/A         * map.
2289729Sandreas.hansson@arm.com         */
2298721SN/A        bool secure(bool have_security, WalkerState *currState) const
2309729Sandreas.hansson@arm.com        {
2319729Sandreas.hansson@arm.com            if (have_security) {
2329729Sandreas.hansson@arm.com                if (type() == PageTable)
2339729Sandreas.hansson@arm.com                    return !bits(data, 3);
2349729Sandreas.hansson@arm.com                else
2359729Sandreas.hansson@arm.com                    return !bits(data, 19);
2369729Sandreas.hansson@arm.com            }
2379729Sandreas.hansson@arm.com            return false;
2389729Sandreas.hansson@arm.com        }
2399055Ssaidi@eecs.umich.edu    };
2409729Sandreas.hansson@arm.com
2419729Sandreas.hansson@arm.com    /** Level 2 page table descriptor */
2429729Sandreas.hansson@arm.com    class L2Descriptor : public DescriptorBase {
2439729Sandreas.hansson@arm.com      public:
2449729Sandreas.hansson@arm.com        /** The raw bits of the entry. */
2459729Sandreas.hansson@arm.com        uint32_t     data;
2469055Ssaidi@eecs.umich.edu        L1Descriptor *l1Parent;
2479729Sandreas.hansson@arm.com
2489729Sandreas.hansson@arm.com        /** This entry has been modified (access flag set) and needs to be
2499729Sandreas.hansson@arm.com         * written back to memory */
2509729Sandreas.hansson@arm.com        bool _dirty;
2519729Sandreas.hansson@arm.com
2529729Sandreas.hansson@arm.com        /** Default ctor */
2539729Sandreas.hansson@arm.com        L2Descriptor() : data(0), l1Parent(nullptr), _dirty(false)
2549729Sandreas.hansson@arm.com        {
2559449SAli.Saidi@ARM.com            lookupLevel = L2;
2569729Sandreas.hansson@arm.com        }
2579729Sandreas.hansson@arm.com
2589729Sandreas.hansson@arm.com        L2Descriptor(L1Descriptor &parent) : data(0), l1Parent(&parent),
2599729Sandreas.hansson@arm.com                                             _dirty(false)
2609729Sandreas.hansson@arm.com        {
2619729Sandreas.hansson@arm.com            lookupLevel = L2;
2629729Sandreas.hansson@arm.com        }
2639729Sandreas.hansson@arm.com
2648721SN/A        virtual uint64_t getRawData() const
2658721SN/A        {
2668721SN/A            return (data);
2678721SN/A        }
2688721SN/A
2698721SN/A        virtual std::string dbgHeader() const
2708721SN/A        {
2718721SN/A            return "Inserting L2 Descriptor into TLB\n";
2728721SN/A        }
2738721SN/A
2748721SN/A        virtual TlbEntry::DomainType domain() const
2758721SN/A        {
2768721SN/A            return l1Parent->domain();
2778721SN/A        }
2788721SN/A
2798721SN/A        bool secure(bool have_security, WalkerState *currState) const
2809729Sandreas.hansson@arm.com        {
2818721SN/A            return l1Parent->secure(have_security, currState);
2828721SN/A        }
2839247Sandreas.hansson@arm.com
2849729Sandreas.hansson@arm.com        virtual uint8_t offsetBits() const
2858721SN/A        {
2868721SN/A            return large() ? 16 : 12;
2879247Sandreas.hansson@arm.com        }
2889729Sandreas.hansson@arm.com
2898721SN/A        /** Is the entry invalid */
2908721SN/A        bool invalid() const
2919247Sandreas.hansson@arm.com        {
2929729Sandreas.hansson@arm.com            return bits(data, 1, 0) == 0;
2938721SN/A        }
2948721SN/A
2959729Sandreas.hansson@arm.com        /** What is the size of the mapping? */
2968721SN/A        bool large() const
2978721SN/A        {
2988721SN/A            return bits(data, 1) == 0;
2998721SN/A        }
3008721SN/A
3018721SN/A        /** Is execution allowed on this mapping? */
3028721SN/A        bool xn() const
3038721SN/A        {
3048721SN/A            return large() ? bits(data, 15) : bits(data, 0);
3058721SN/A        }
3068721SN/A
3078721SN/A        /** Is the translation global (no asid used)? */
3089729Sandreas.hansson@arm.com        bool global(WalkerState *currState) const
3098721SN/A        {
3108721SN/A            return !bits(data, 11);
3119729Sandreas.hansson@arm.com        }
3129729Sandreas.hansson@arm.com
3139729Sandreas.hansson@arm.com        /** Three bit access protection flags */
3149247Sandreas.hansson@arm.com        uint8_t ap() const
3159729Sandreas.hansson@arm.com        {
3169729Sandreas.hansson@arm.com           return bits(data, 5, 4) | (bits(data, 9) << 2);
3179729Sandreas.hansson@arm.com        }
3189247Sandreas.hansson@arm.com
3199729Sandreas.hansson@arm.com        /** Memory region attributes: ARM DDI 0406B: B3-32 */
3209729Sandreas.hansson@arm.com        uint8_t texcb() const
3219247Sandreas.hansson@arm.com        {
3229247Sandreas.hansson@arm.com            return large() ?
3239729Sandreas.hansson@arm.com                (bits(data, 2) | (bits(data, 3) << 1) | (bits(data, 14, 12) << 2)) :
3249729Sandreas.hansson@arm.com                (bits(data, 2) | (bits(data, 3) << 1) | (bits(data, 8, 6) << 2));
3259729Sandreas.hansson@arm.com        }
3269729Sandreas.hansson@arm.com
3279729Sandreas.hansson@arm.com        /** Return the physical frame, bits shifted right */
3289729Sandreas.hansson@arm.com        Addr pfn() const
3299729Sandreas.hansson@arm.com        {
3308721SN/A            return large() ? bits(data, 31, 16) : bits(data, 31, 12);
3319729Sandreas.hansson@arm.com        }
3329729Sandreas.hansson@arm.com
3339729Sandreas.hansson@arm.com        /** Return complete physical address given a VA */
3349729Sandreas.hansson@arm.com        Addr paddr(Addr va) const
3359449SAli.Saidi@ARM.com        {
3369729Sandreas.hansson@arm.com            if (large())
3379729Sandreas.hansson@arm.com                return mbits(data, 31, 16) | mbits(va, 15, 0);
3389729Sandreas.hansson@arm.com            else
3399729Sandreas.hansson@arm.com                return mbits(data, 31, 12) | mbits(va, 11, 0);
3409449SAli.Saidi@ARM.com        }
3419729Sandreas.hansson@arm.com
3429729Sandreas.hansson@arm.com        /** If the section is shareable. See texcb() comment. */
3439729Sandreas.hansson@arm.com        bool shareable() const
3449729Sandreas.hansson@arm.com        {
3459449SAli.Saidi@ARM.com            return bits(data, 10);
3469729Sandreas.hansson@arm.com        }
3479729Sandreas.hansson@arm.com
3488721SN/A        /** Set access flag that this entry has been touched. Mark
3498721SN/A         * the entry as requiring a writeback, in the future.
3508721SN/A         */
3519729Sandreas.hansson@arm.com        void setAp0()
3529729Sandreas.hansson@arm.com        {
3538721SN/A            data |= 1 << 4;
3548721SN/A            _dirty = true;
3558721SN/A        }
3568721SN/A
3578721SN/A        /** This entry needs to be written back to memory */
3588721SN/A        bool dirty() const
3598721SN/A        {
3608721SN/A            return _dirty;
3618721SN/A        }
3628721SN/A
3638721SN/A    };
3648721SN/A
3658721SN/A    // Granule sizes for AArch64 long descriptors
3669449SAli.Saidi@ARM.com    enum GrainSize {
3679449SAli.Saidi@ARM.com        Grain4KB  = 12,
3689729Sandreas.hansson@arm.com        Grain16KB = 14,
3699449SAli.Saidi@ARM.com        Grain64KB = 16,
3709449SAli.Saidi@ARM.com        ReservedGrain = 0
3719729Sandreas.hansson@arm.com    };
3729449SAli.Saidi@ARM.com
3739449SAli.Saidi@ARM.com    /** Long-descriptor format (LPAE) */
3749729Sandreas.hansson@arm.com    class LongDescriptor : public DescriptorBase {
3759449SAli.Saidi@ARM.com      public:
3769729Sandreas.hansson@arm.com        /** Descriptor type */
3779729Sandreas.hansson@arm.com        enum EntryType {
3789729Sandreas.hansson@arm.com            Invalid,
3799729Sandreas.hansson@arm.com            Table,
3809247Sandreas.hansson@arm.com            Block,
3819729Sandreas.hansson@arm.com            Page
3828721SN/A        };
3839449SAli.Saidi@ARM.com
3849729Sandreas.hansson@arm.com        /** The raw bits of the entry */
3859729Sandreas.hansson@arm.com        uint64_t data;
3869729Sandreas.hansson@arm.com
3879729Sandreas.hansson@arm.com        /** This entry has been modified (access flag set) and needs to be
3889247Sandreas.hansson@arm.com         * written back to memory */
3898721SN/A        bool _dirty;
3908721SN/A
3918721SN/A        virtual uint64_t getRawData() const
3928721SN/A        {
3938721SN/A            return (data);
3948721SN/A        }
3958721SN/A
3968721SN/A        virtual std::string dbgHeader() const
3978721SN/A        {
3988721SN/A            if (type() == LongDescriptor::Page) {
3999729Sandreas.hansson@arm.com                assert(lookupLevel == L3);
4008721SN/A                return "Inserting Page descriptor into TLB\n";
4019729Sandreas.hansson@arm.com            } else {
4028721SN/A                assert(lookupLevel < L3);
4039449SAli.Saidi@ARM.com                return "Inserting Block descriptor into TLB\n";
4048721SN/A            }
4058721SN/A        }
4068721SN/A
4079449SAli.Saidi@ARM.com        /**
4089449SAli.Saidi@ARM.com         * Returns true if this entry targets the secure physical address
4098721SN/A         * map.
4108721SN/A         */
4118721SN/A        bool secure(bool have_security, WalkerState *currState) const
4128721SN/A        {
4138721SN/A            assert(type() == Block || type() == Page);
4148721SN/A            return have_security && (currState->secureLookup && !bits(data, 5));
4158721SN/A        }
4168721SN/A
4178721SN/A        /** True if the current lookup is performed in AArch64 state */
4188721SN/A        bool aarch64;
4198721SN/A
4209449SAli.Saidi@ARM.com        /** Width of the granule size in bits */
4219449SAli.Saidi@ARM.com        GrainSize grainSize;
4228721SN/A
4238721SN/A        /** Return the descriptor type */
4248721SN/A        EntryType type() const
4258721SN/A        {
4269729Sandreas.hansson@arm.com            switch (bits(data, 1, 0)) {
4279449SAli.Saidi@ARM.com              case 0x1:
4289729Sandreas.hansson@arm.com                // In AArch64 blocks are not allowed at L0 for the 4 KB granule
4298721SN/A                // and at L1 for 16/64 KB granules
4308721SN/A                if (grainSize > Grain4KB)
4318721SN/A                    return lookupLevel == L2 ? Block : Invalid;
4328721SN/A                return lookupLevel == L0 || lookupLevel == L3 ? Invalid : Block;
4338721SN/A              case 0x3:
4348721SN/A                return lookupLevel == L3 ? Page : Table;
4358721SN/A              default:
4369729Sandreas.hansson@arm.com                return Invalid;
4378721SN/A            }
4389729Sandreas.hansson@arm.com        }
4399729Sandreas.hansson@arm.com
4403691SN/A        /** Return the bit width of the page/block offset */
4413691SN/A        uint8_t offsetBits() const
4423691SN/A        {
4433691SN/A            if (type() == Block) {
4449449SAli.Saidi@ARM.com                switch (grainSize) {
4459729Sandreas.hansson@arm.com                    case Grain4KB:
4469729Sandreas.hansson@arm.com                        return lookupLevel == L1 ? 30 /* 1 GB */
4478721SN/A                                                 : 21 /* 2 MB */;
4489729Sandreas.hansson@arm.com                    case Grain16KB:
4499729Sandreas.hansson@arm.com                        return 25  /* 32 MB */;
4509729Sandreas.hansson@arm.com                    case Grain64KB:
4519729Sandreas.hansson@arm.com                        return 29 /* 512 MB */;
4529729Sandreas.hansson@arm.com                    default:
4539729Sandreas.hansson@arm.com                        panic("Invalid AArch64 VM granule size\n");
4549729Sandreas.hansson@arm.com                }
4559729Sandreas.hansson@arm.com            } else if (type() == Page) {
4569729Sandreas.hansson@arm.com                switch (grainSize) {
4579729Sandreas.hansson@arm.com                    case Grain4KB:
4589729Sandreas.hansson@arm.com                    case Grain16KB:
4599729Sandreas.hansson@arm.com                    case Grain64KB:
4609729Sandreas.hansson@arm.com                        return grainSize; /* enum -> uint okay */
4619729Sandreas.hansson@arm.com                    default:
4629729Sandreas.hansson@arm.com                        panic("Invalid AArch64 VM granule size\n");
4639729Sandreas.hansson@arm.com                }
4649729Sandreas.hansson@arm.com            } else {
4659729Sandreas.hansson@arm.com                panic("AArch64 page table entry must be block or page\n");
4669729Sandreas.hansson@arm.com            }
4679729Sandreas.hansson@arm.com        }
4689729Sandreas.hansson@arm.com
4699729Sandreas.hansson@arm.com        /** Return the physical frame, bits shifted right */
4709729Sandreas.hansson@arm.com        Addr pfn() const
4719729Sandreas.hansson@arm.com        {
4729729Sandreas.hansson@arm.com            if (aarch64)
4739729Sandreas.hansson@arm.com                return bits(data, 47, offsetBits());
4749729Sandreas.hansson@arm.com            return bits(data, 39, offsetBits());
4759729Sandreas.hansson@arm.com        }
4769729Sandreas.hansson@arm.com
4779729Sandreas.hansson@arm.com        /** Return the complete physical address given a VA */
4789729Sandreas.hansson@arm.com        Addr paddr(Addr va) const
4799729Sandreas.hansson@arm.com        {
4809729Sandreas.hansson@arm.com            int n = offsetBits();
4819729Sandreas.hansson@arm.com            if (aarch64)
4829729Sandreas.hansson@arm.com                return mbits(data, 47, n) | mbits(va, n - 1, 0);
4839729Sandreas.hansson@arm.com            return mbits(data, 39, n) | mbits(va, n - 1, 0);
4848721SN/A        }
4858721SN/A
4868721SN/A        /** Return the physical address of the entry */
4878721SN/A        Addr paddr() const
4888721SN/A        {
4898721SN/A            if (aarch64)
4908721SN/A                return mbits(data, 47, offsetBits());
4918721SN/A            return mbits(data, 39, offsetBits());
4928721SN/A        }
4938721SN/A
4948721SN/A        /** Return the address of the next page table */
4958721SN/A        Addr nextTableAddr() const
4968721SN/A        {
4978721SN/A            assert(type() == Table);
4988721SN/A            if (aarch64)
4998721SN/A                return mbits(data, 47, grainSize);
5009729Sandreas.hansson@arm.com            else
5018721SN/A                return mbits(data, 39, 12);
5028721SN/A        }
5038721SN/A
5049729Sandreas.hansson@arm.com        /** Return the address of the next descriptor */
5058721SN/A        Addr nextDescAddr(Addr va) const
5068721SN/A        {
5078721SN/A            assert(type() == Table);
5089729Sandreas.hansson@arm.com            Addr pa = 0;
5098721SN/A            if (aarch64) {
5108721SN/A                int stride = grainSize - 3;
5118721SN/A                int va_lo = stride * (3 - (lookupLevel + 1)) + grainSize;
5129729Sandreas.hansson@arm.com                int va_hi = va_lo + stride - 1;
5138721SN/A                pa = nextTableAddr() | (bits(va, va_hi, va_lo) << 3);
5148721SN/A            } else {
5159729Sandreas.hansson@arm.com                if (lookupLevel == L1)
5168721SN/A                    pa = nextTableAddr() | (bits(va, 29, 21) << 3);
5178721SN/A                else  // lookupLevel == L2
5188721SN/A                    pa = nextTableAddr() | (bits(va, 20, 12) << 3);
5198721SN/A            }
5208721SN/A            return pa;
5218721SN/A        }
5228721SN/A
5238721SN/A        /** Is execution allowed on this mapping? */
5248721SN/A        bool xn() const
5258721SN/A        {
5268721SN/A            assert(type() == Block || type() == Page);
5278721SN/A            return bits(data, 54);
5289729Sandreas.hansson@arm.com        }
5298721SN/A
5308721SN/A        /** Is privileged execution allowed on this mapping? (LPAE only) */
5319729Sandreas.hansson@arm.com        bool pxn() const
5329729Sandreas.hansson@arm.com        {
5339729Sandreas.hansson@arm.com            assert(type() == Block || type() == Page);
5348721SN/A            return bits(data, 53);
5359729Sandreas.hansson@arm.com        }
5369729Sandreas.hansson@arm.com
5379729Sandreas.hansson@arm.com        /** Contiguous hint bit. */
5388721SN/A        bool contiguousHint() const
5399729Sandreas.hansson@arm.com        {
5409729Sandreas.hansson@arm.com            assert(type() == Block || type() == Page);
5418721SN/A            return bits(data, 52);
5428721SN/A        }
5439729Sandreas.hansson@arm.com
5449729Sandreas.hansson@arm.com        /** Is the translation global (no asid used)? */
5459729Sandreas.hansson@arm.com        bool global(WalkerState *currState) const
5469729Sandreas.hansson@arm.com        {
5479729Sandreas.hansson@arm.com            assert(currState && (type() == Block || type() == Page));
5489729Sandreas.hansson@arm.com            if (!currState->aarch64 && (currState->isSecure &&
5499729Sandreas.hansson@arm.com                                        !currState->secureLookup)) {
5508721SN/A                return false;  // ARM ARM issue C B3.6.3
5519490Sandreas.hansson@arm.com            } else if (currState->aarch64) {
5529729Sandreas.hansson@arm.com                if (currState->el == EL2 || currState->el == EL3) {
5539729Sandreas.hansson@arm.com                    return true;  // By default translations are treated as global
5549729Sandreas.hansson@arm.com                                  // in AArch64 EL2 and EL3
5559729Sandreas.hansson@arm.com                } else if (currState->isSecure && !currState->secureLookup) {
5569729Sandreas.hansson@arm.com                    return false;
5579729Sandreas.hansson@arm.com                }
5589729Sandreas.hansson@arm.com            }
5599729Sandreas.hansson@arm.com            return !bits(data, 11);
5609729Sandreas.hansson@arm.com        }
5619729Sandreas.hansson@arm.com
5629729Sandreas.hansson@arm.com        /** Returns true if the access flag (AF) is set. */
5639729Sandreas.hansson@arm.com        bool af() const
5649729Sandreas.hansson@arm.com        {
5659490Sandreas.hansson@arm.com            assert(type() == Block || type() == Page);
5669729Sandreas.hansson@arm.com            return bits(data, 10);
5679729Sandreas.hansson@arm.com        }
5689247Sandreas.hansson@arm.com
5699449SAli.Saidi@ARM.com        /** 2-bit shareability field */
5709247Sandreas.hansson@arm.com        uint8_t sh() const
5719729Sandreas.hansson@arm.com        {
5729729Sandreas.hansson@arm.com            assert(type() == Block || type() == Page);
5739729Sandreas.hansson@arm.com            return bits(data, 9, 8);
5749729Sandreas.hansson@arm.com        }
5759729Sandreas.hansson@arm.com
5769729Sandreas.hansson@arm.com        /** 2-bit access protection flags */
5778721SN/A        uint8_t ap() const
5788721SN/A        {
5799729Sandreas.hansson@arm.com            assert(type() == Block || type() == Page);
5808721SN/A            // Long descriptors only support the AP[2:1] scheme
5818721SN/A            return bits(data, 7, 6);
5828721SN/A        }
5838983Snate@binkert.org
5848983Snate@binkert.org        /** Read/write access protection flag */
5859247Sandreas.hansson@arm.com        bool rw() const
5869247Sandreas.hansson@arm.com        {
5878721SN/A            assert(type() == Block || type() == Page);
5888721SN/A            return !bits(data, 7);
5898721SN/A        }
5908721SN/A
5919729Sandreas.hansson@arm.com        /** User/privileged level access protection flag */
5928721SN/A        bool user() const
5939729Sandreas.hansson@arm.com        {
5948721SN/A            assert(type() == Block || type() == Page);
5958721SN/A            return bits(data, 6);
5969449SAli.Saidi@ARM.com        }
5978721SN/A
5988721SN/A        /** Return the AP bits as compatible with the AP[2:0] format.  Utility
5999449SAli.Saidi@ARM.com         * function used to simplify the code in the TLB for performing
6008721SN/A         * permission checks. */
6018721SN/A        static uint8_t ap(bool rw, bool user)
6029449SAli.Saidi@ARM.com        {
6038721SN/A            return ((!rw) << 2) | (user << 1);
6048721SN/A        }
6059449SAli.Saidi@ARM.com
6068721SN/A        TlbEntry::DomainType domain() const
6078721SN/A        {
6089449SAli.Saidi@ARM.com            // Long-desc. format only supports Client domain
6098721SN/A            assert(type() == Block || type() == Page);
6109729Sandreas.hansson@arm.com            return TlbEntry::DomainType::Client;
6119449SAli.Saidi@ARM.com        }
6129729Sandreas.hansson@arm.com
6138721SN/A        /** Attribute index */
6149449SAli.Saidi@ARM.com        uint8_t attrIndx() const
6158721SN/A        {
6168721SN/A            assert(type() == Block || type() == Page);
6179449SAli.Saidi@ARM.com            return bits(data, 4, 2);
6188721SN/A        }
6199449SAli.Saidi@ARM.com
6209729Sandreas.hansson@arm.com        /** Memory attributes, only used by stage 2 translations */
6218721SN/A        uint8_t memAttr() const
6229729Sandreas.hansson@arm.com        {
6239729Sandreas.hansson@arm.com            assert(type() == Block || type() == Page);
6249449SAli.Saidi@ARM.com            return bits(data, 5, 2);
6259449SAli.Saidi@ARM.com        }
6269729Sandreas.hansson@arm.com
6279729Sandreas.hansson@arm.com        /** Set access flag that this entry has been touched.  Mark the entry as
6289449SAli.Saidi@ARM.com         * requiring a writeback, in the future. */
6299449SAli.Saidi@ARM.com        void setAf()
6309449SAli.Saidi@ARM.com        {
6319449SAli.Saidi@ARM.com            data |= 1 << 10;
6329449SAli.Saidi@ARM.com            _dirty = true;
6339449SAli.Saidi@ARM.com        }
6349729Sandreas.hansson@arm.com
6359729Sandreas.hansson@arm.com        /** This entry needs to be written back to memory */
6369449SAli.Saidi@ARM.com        bool dirty() const
6379449SAli.Saidi@ARM.com        {
6389729Sandreas.hansson@arm.com            return _dirty;
6399729Sandreas.hansson@arm.com        }
6409729Sandreas.hansson@arm.com
6419729Sandreas.hansson@arm.com        /** Whether the subsequent levels of lookup are secure */
6429729Sandreas.hansson@arm.com        bool secureTable() const
6439729Sandreas.hansson@arm.com        {
6449729Sandreas.hansson@arm.com            assert(type() == Table);
6459729Sandreas.hansson@arm.com            return !bits(data, 63);
6469729Sandreas.hansson@arm.com        }
6479729Sandreas.hansson@arm.com
6489729Sandreas.hansson@arm.com        /** Two bit access protection flags for subsequent levels of lookup */
6499729Sandreas.hansson@arm.com        uint8_t apTable() const
6509729Sandreas.hansson@arm.com        {
6519729Sandreas.hansson@arm.com            assert(type() == Table);
6529729Sandreas.hansson@arm.com            return bits(data, 62, 61);
6538721SN/A        }
6548721SN/A
6558721SN/A        /** R/W protection flag for subsequent levels of lookup */
6568721SN/A        uint8_t rwTable() const
6578721SN/A        {
6588721SN/A            assert(type() == Table);
6598721SN/A            return !bits(data, 62);
6608721SN/A        }
6618721SN/A
6628721SN/A        /** User/privileged mode protection flag for subsequent levels of
6638721SN/A         * lookup */
6648721SN/A        uint8_t userTable() const
6658721SN/A        {
6668721SN/A            assert(type() == Table);
6678721SN/A            return !bits(data, 61);
6688721SN/A        }
6699449SAli.Saidi@ARM.com
6708721SN/A        /** Is execution allowed on subsequent lookup levels? */
6718721SN/A        bool xnTable() const
6728721SN/A        {
6739449SAli.Saidi@ARM.com            assert(type() == Table);
6748721SN/A            return bits(data, 60);
6758721SN/A        }
6768721SN/A
6779449SAli.Saidi@ARM.com        /** Is privileged execution allowed on subsequent lookup levels? */
6786024SN/A        bool pxnTable() const
6798721SN/A        {
6808721SN/A            assert(type() == Table);
6819449SAli.Saidi@ARM.com            return bits(data, 59);
6828721SN/A        }
6838721SN/A    };
6849449SAli.Saidi@ARM.com
6858721SN/A    class WalkerState
6868721SN/A    {
6878721SN/A      public:
6888721SN/A        /** Thread context that we're doing the walk for */
6898721SN/A        ThreadContext *tc;
6908721SN/A
6918721SN/A        /** If the access is performed in AArch64 state */
6928721SN/A        bool aarch64;
6936024SN/A
6946024SN/A        /** Current exception level */
6958721SN/A        ExceptionLevel el;
6968721SN/A
6979729Sandreas.hansson@arm.com        /** Current physical address range in bits */
6988721SN/A        int physAddrRange;
6998721SN/A
7009449SAli.Saidi@ARM.com        /** Request that is currently being serviced */
7019449SAli.Saidi@ARM.com        RequestPtr req;
7029449SAli.Saidi@ARM.com
7038721SN/A        /** ASID that we're servicing the request under */
7049449SAli.Saidi@ARM.com        uint16_t asid;
7059449SAli.Saidi@ARM.com        uint8_t vmid;
7069449SAli.Saidi@ARM.com        bool    isHyp;
7078721SN/A
7089449SAli.Saidi@ARM.com        /** Translation state for delayed requests */
7099449SAli.Saidi@ARM.com        TLB::Translation *transState;
7108721SN/A
7118721SN/A        /** The fault that we are going to return */
7129449SAli.Saidi@ARM.com        Fault fault;
7139449SAli.Saidi@ARM.com
7149449SAli.Saidi@ARM.com        /** The virtual address that is being translated with tagging removed.*/
7159729Sandreas.hansson@arm.com        Addr vaddr;
7169729Sandreas.hansson@arm.com
7179729Sandreas.hansson@arm.com        /** The virtual address that is being translated */
7189729Sandreas.hansson@arm.com        Addr vaddr_tainted;
7193691SN/A
7209449SAli.Saidi@ARM.com        /** Cached copy of the sctlr as it existed when translation began */
7219449SAli.Saidi@ARM.com        SCTLR sctlr;
7229449SAli.Saidi@ARM.com
7239449SAli.Saidi@ARM.com        /** Cached copy of the scr as it existed when translation began */
7249449SAli.Saidi@ARM.com        SCR scr;
7259449SAli.Saidi@ARM.com
7269449SAli.Saidi@ARM.com        /** Cached copy of the cpsr as it existed when translation began */
7279449SAli.Saidi@ARM.com        CPSR cpsr;
7289449SAli.Saidi@ARM.com
7299449SAli.Saidi@ARM.com        /** Cached copy of ttbcr/tcr as it existed when translation began */
7309449SAli.Saidi@ARM.com        union {
7319449SAli.Saidi@ARM.com            TTBCR ttbcr; // AArch32 translations
7329729Sandreas.hansson@arm.com            TCR tcr;     // AArch64 translations
7339729Sandreas.hansson@arm.com        };
7349449SAli.Saidi@ARM.com
7359449SAli.Saidi@ARM.com        /** Cached copy of the htcr as it existed when translation began. */
7369729Sandreas.hansson@arm.com        HTCR htcr;
7379247Sandreas.hansson@arm.com
7389449SAli.Saidi@ARM.com        /** Cached copy of the htcr as it existed when translation began. */
7399247Sandreas.hansson@arm.com        HCR  hcr;
7409449SAli.Saidi@ARM.com
7419449SAli.Saidi@ARM.com        /** Cached copy of the vtcr as it existed when translation began. */
7429449SAli.Saidi@ARM.com        VTCR_t vtcr;
7439449SAli.Saidi@ARM.com
7449449SAli.Saidi@ARM.com        /** If the access is a write */
7459449SAli.Saidi@ARM.com        bool isWrite;
7468721SN/A
7478721SN/A        /** If the access is a fetch (for execution, and no-exec) must be checked?*/
7489449SAli.Saidi@ARM.com        bool isFetch;
7496127SN/A
7506127SN/A        /** If the access comes from the secure state. */
7516127SN/A        bool isSecure;
7528983Snate@binkert.org
7538983Snate@binkert.org        /** Helper variables used to implement hierarchical access permissions
7549247Sandreas.hansson@arm.com         * when the long-desc. format is used (LPAE only) */
7559247Sandreas.hansson@arm.com        bool secureLookup;
7566127SN/A        bool rwTable;
7576127SN/A        bool userTable;
7586127SN/A        bool xnTable;
7593691SN/A        bool pxnTable;
7609729Sandreas.hansson@arm.com
7613691SN/A        /** Flag indicating if a second stage of lookup is required */
7629729Sandreas.hansson@arm.com        bool stage2Req;
7633691SN/A
7648721SN/A        /** A pointer to the stage 2 translation that's in progress */
7659449SAli.Saidi@ARM.com        TLB::Translation *stage2Tran;
7668721SN/A
7678721SN/A        /** If the mode is timing or atomic */
7689449SAli.Saidi@ARM.com        bool timing;
7698721SN/A
7708721SN/A        /** If the atomic mode should be functional */
7719449SAli.Saidi@ARM.com        bool functional;
7728721SN/A
7738721SN/A        /** Save mode for use in delayed response */
7749449SAli.Saidi@ARM.com        BaseTLB::Mode mode;
7758721SN/A
7768721SN/A        /** The translation type that has been requested */
7779449SAli.Saidi@ARM.com        TLB::ArmTranslationType tranType;
7788721SN/A
7799449SAli.Saidi@ARM.com        /** Short-format descriptors */
7809449SAli.Saidi@ARM.com        L1Descriptor l1Desc;
7819729Sandreas.hansson@arm.com        L2Descriptor l2Desc;
7828721SN/A
7839449SAli.Saidi@ARM.com        /** Long-format descriptor (LPAE and AArch64) */
7848721SN/A        LongDescriptor longDesc;
7858721SN/A
7869449SAli.Saidi@ARM.com        /** Whether the response is delayed in timing mode due to additional
7878721SN/A         * lookups */
7889449SAli.Saidi@ARM.com        bool delayed;
7899729Sandreas.hansson@arm.com
7903691SN/A        TableWalker *tableWalker;
7919729Sandreas.hansson@arm.com
7929729Sandreas.hansson@arm.com        /** Timestamp for calculating elapsed time in service (for stats) */
7933691SN/A        Tick startTime;
7943691SN/A
795        /** Page entries walked during service (for stats) */
796        unsigned levels;
797
798        void doL1Descriptor();
799        void doL2Descriptor();
800
801        void doLongDescriptor();
802
803        WalkerState();
804
805        std::string name() const { return tableWalker->name(); }
806    };
807
808  protected:
809
810    /** Queues of requests for all the different lookup levels */
811    std::list<WalkerState *> stateQueues[MAX_LOOKUP_LEVELS];
812
813    /** Queue of requests that have passed are waiting because the walker is
814     * currently busy. */
815    std::list<WalkerState *> pendingQueue;
816
817    /** The MMU to forward second stage look upts to */
818    Stage2MMU *stage2Mmu;
819
820    /** Port shared by the two table walkers. */
821    DmaPort* port;
822
823    /** Master id assigned by the MMU. */
824    MasterID masterId;
825
826    /** Indicates whether this table walker is part of the stage 2 mmu */
827    const bool isStage2;
828
829    /** TLB that is initiating these table walks */
830    TLB *tlb;
831
832    /** Cached copy of the sctlr as it existed when translation began */
833    SCTLR sctlr;
834
835    WalkerState *currState;
836
837    /** If a timing translation is currently in progress */
838    bool pending;
839
840    /** The number of walks belonging to squashed instructions that can be
841     * removed from the pendingQueue per cycle. */
842    unsigned numSquashable;
843
844    /** Cached copies of system-level properties */
845    bool haveSecurity;
846    bool _haveLPAE;
847    bool _haveVirtualization;
848    uint8_t physAddrRange;
849    bool _haveLargeAsid64;
850
851    /** Statistics */
852    Stats::Scalar statWalks;
853    Stats::Scalar statWalksShortDescriptor;
854    Stats::Scalar statWalksLongDescriptor;
855    Stats::Vector statWalksShortTerminatedAtLevel;
856    Stats::Vector statWalksLongTerminatedAtLevel;
857    Stats::Scalar statSquashedBefore;
858    Stats::Scalar statSquashedAfter;
859    Stats::Histogram statWalkWaitTime;
860    Stats::Histogram statWalkServiceTime;
861    Stats::Histogram statPendingWalks; // essentially "L" of queueing theory
862    Stats::Vector statPageSizes;
863    Stats::Vector2d statRequestOrigin;
864
865    mutable unsigned pendingReqs;
866    mutable Tick pendingChangeTick;
867
868    static const unsigned REQUESTED = 0;
869    static const unsigned COMPLETED = 1;
870
871  public:
872   typedef ArmTableWalkerParams Params;
873    TableWalker(const Params *p);
874    virtual ~TableWalker();
875
876    const Params *
877    params() const
878    {
879        return dynamic_cast<const Params *>(_params);
880    }
881
882    void init() override;
883
884    bool haveLPAE() const { return _haveLPAE; }
885    bool haveVirtualization() const { return _haveVirtualization; }
886    bool haveLargeAsid64() const { return _haveLargeAsid64; }
887    /** Checks if all state is cleared and if so, completes drain */
888    void completeDrain();
889    DrainState drain() override;
890    void drainResume() override;
891
892    Port &getPort(const std::string &if_name,
893                  PortID idx=InvalidPortID) override;
894
895    void regStats() override;
896
897    Fault walk(const RequestPtr &req, ThreadContext *tc,
898               uint16_t asid, uint8_t _vmid,
899               bool _isHyp, TLB::Mode mode, TLB::Translation *_trans,
900               bool timing, bool functional, bool secure,
901               TLB::ArmTranslationType tranType, bool _stage2Req);
902
903    void setTlb(TLB *_tlb) { tlb = _tlb; }
904    TLB* getTlb() { return tlb; }
905    void setMMU(Stage2MMU *m, MasterID master_id);
906    void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
907                  uint8_t texcb, bool s);
908    void memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
909                      LongDescriptor &lDescriptor);
910    void memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
911                         LongDescriptor &lDescriptor);
912
913    static LookupLevel toLookupLevel(uint8_t lookup_level_as_int);
914
915  private:
916
917    void doL1Descriptor();
918    void doL1DescriptorWrapper();
919    EventFunctionWrapper doL1DescEvent;
920
921    void doL2Descriptor();
922    void doL2DescriptorWrapper();
923    EventFunctionWrapper doL2DescEvent;
924
925    void doLongDescriptor();
926
927    void doL0LongDescriptorWrapper();
928    EventFunctionWrapper doL0LongDescEvent;
929    void doL1LongDescriptorWrapper();
930    EventFunctionWrapper doL1LongDescEvent;
931    void doL2LongDescriptorWrapper();
932    EventFunctionWrapper doL2LongDescEvent;
933    void doL3LongDescriptorWrapper();
934    EventFunctionWrapper doL3LongDescEvent;
935
936    void doLongDescriptorWrapper(LookupLevel curr_lookup_level);
937    Event* LongDescEventByLevel[4];
938
939    bool fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
940        Request::Flags flags, int queueIndex, Event *event,
941        void (TableWalker::*doDescriptor)());
942
943    void insertTableEntry(DescriptorBase &descriptor, bool longDescriptor);
944
945    Fault processWalk();
946    Fault processWalkLPAE();
947    static unsigned adjustTableSizeAArch64(unsigned tsz);
948    /// Returns true if the address exceeds the range permitted by the
949    /// system-wide setting or by the TCR_ELx IPS/PS setting
950    static bool checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange);
951    Fault processWalkAArch64();
952    void processWalkWrapper();
953    EventFunctionWrapper doProcessEvent;
954
955    void nextWalk(ThreadContext *tc);
956
957    void pendingChange();
958
959    static uint8_t pageSizeNtoStatBin(uint8_t N);
960
961    Fault testWalk(Addr pa, Addr size, TlbEntry::DomainType domain,
962                   LookupLevel lookup_level);
963};
964
965} // namespace ArmISA
966
967#endif //__ARCH_ARM_TABLE_WALKER_HH__
968
969