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