1/*
2 * Copyright (c) 2010-2016, 2019 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Ali Saidi
38 *          Giacomo Gabrielli
39 */
40
41#ifndef __ARCH_ARM_TABLE_WALKER_HH__
42#define __ARCH_ARM_TABLE_WALKER_HH__
43
44#include <list>
45
46#include "arch/arm/faults.hh"
47#include "arch/arm/miscregs.hh"
48#include "arch/arm/system.hh"
49#include "arch/arm/tlb.hh"
50#include "mem/request.hh"
51#include "params/ArmTableWalker.hh"
52#include "sim/clocked_object.hh"
53#include "sim/eventq.hh"
54
55class ThreadContext;
56
57class DmaPort;
58
59namespace ArmISA {
60class Translation;
61class TLB;
62class Stage2MMU;
63
64class TableWalker : public ClockedObject
65{
66  public:
67    class WalkerState;
68
69    class DescriptorBase {
70      public:
71        DescriptorBase() : lookupLevel(L0) {}
72
73        /** Current lookup level for this descriptor */
74        LookupLevel lookupLevel;
75
76        virtual Addr pfn() const = 0;
77        virtual TlbEntry::DomainType domain() const = 0;
78        virtual bool xn() const = 0;
79        virtual uint8_t ap() const = 0;
80        virtual bool global(WalkerState *currState) const = 0;
81        virtual uint8_t offsetBits() const = 0;
82        virtual bool secure(bool have_security, WalkerState *currState) const = 0;
83        virtual std::string dbgHeader() const = 0;
84        virtual uint64_t getRawData() const = 0;
85        virtual uint8_t texcb() const
86        {
87            panic("texcb() not implemented for this class\n");
88        }
89        virtual bool shareable() const
90        {
91            panic("shareable() not implemented for this class\n");
92        }
93    };
94
95    class L1Descriptor : public DescriptorBase {
96      public:
97        /** Type of page table entry ARM DDI 0406B: B3-8*/
98        enum EntryType {
99            Ignore,
100            PageTable,
101            Section,
102            Reserved
103        };
104
105        /** The raw bits of the entry */
106        uint32_t data;
107
108        /** This entry has been modified (access flag set) and needs to be
109         * written back to memory */
110        bool _dirty;
111
112        /** Default ctor */
113        L1Descriptor() : data(0), _dirty(false)
114        {
115            lookupLevel = L1;
116        }
117
118        virtual uint64_t getRawData() const
119        {
120            return (data);
121        }
122
123        virtual std::string dbgHeader() const
124        {
125            return "Inserting Section Descriptor into TLB\n";
126        }
127
128        virtual uint8_t offsetBits() const
129        {
130            return 20;
131        }
132
133        EntryType type() const
134        {
135            return (EntryType)(data & 0x3);
136        }
137
138        /** Is the page a Supersection (16MB)?*/
139        bool supersection() const
140        {
141            return bits(data, 18);
142        }
143
144        /** Return the physcal address of the entry, bits in position*/
145        Addr paddr() const
146        {
147            if (supersection())
148                panic("Super sections not implemented\n");
149            return mbits(data, 31, 20);
150        }
151        /** Return the physcal address of the entry, bits in position*/
152        Addr paddr(Addr va) const
153        {
154            if (supersection())
155                panic("Super sections not implemented\n");
156            return mbits(data, 31, 20) | mbits(va, 19, 0);
157        }
158
159
160        /** Return the physical frame, bits shifted right */
161        Addr pfn() const
162        {
163            if (supersection())
164                panic("Super sections not implemented\n");
165            return bits(data, 31, 20);
166        }
167
168        /** Is the translation global (no asid used)? */
169        bool global(WalkerState *currState) const
170        {
171            return !bits(data, 17);
172        }
173
174        /** Is the translation not allow execution? */
175        bool xn() const
176        {
177            return bits(data, 4);
178        }
179
180        /** Three bit access protection flags */
181        uint8_t ap() const
182        {
183            return (bits(data, 15) << 2) | bits(data, 11, 10);
184        }
185
186        /** Domain Client/Manager: ARM DDI 0406B: B3-31 */
187        TlbEntry::DomainType domain() const
188        {
189            return static_cast<TlbEntry::DomainType>(bits(data, 8, 5));
190        }
191
192        /** Address of L2 descriptor if it exists */
193        Addr l2Addr() const
194        {
195            return mbits(data, 31, 10);
196        }
197
198        /** Memory region attributes: ARM DDI 0406B: B3-32.
199         * These bits are largly ignored by M5 and only used to
200         * provide the illusion that the memory system cares about
201         * anything but cachable vs. uncachable.
202         */
203        uint8_t texcb() const
204        {
205            return bits(data, 2) | bits(data, 3) << 1 | bits(data, 14, 12) << 2;
206        }
207
208        /** If the section is shareable. See texcb() comment. */
209        bool shareable() const
210        {
211            return bits(data, 16);
212        }
213
214        /** Set access flag that this entry has been touched. Mark
215         * the entry as requiring a writeback, in the future.
216         */
217        void setAp0()
218        {
219            data |= 1 << 10;
220            _dirty = true;
221        }
222
223        /** This entry needs to be written back to memory */
224        bool dirty() const
225        {
226            return _dirty;
227        }
228
229        /**
230         * Returns true if this entry targets the secure physical address
231         * map.
232         */
233        bool secure(bool have_security, WalkerState *currState) const
234        {
235            if (have_security) {
236                if (type() == PageTable)
237                    return !bits(data, 3);
238                else
239                    return !bits(data, 19);
240            }
241            return false;
242        }
243    };
244
245    /** Level 2 page table descriptor */
246    class L2Descriptor : public DescriptorBase {
247      public:
248        /** The raw bits of the entry. */
249        uint32_t     data;
250        L1Descriptor *l1Parent;
251
252        /** This entry has been modified (access flag set) and needs to be
253         * written back to memory */
254        bool _dirty;
255
256        /** Default ctor */
257        L2Descriptor() : data(0), l1Parent(nullptr), _dirty(false)
258        {
259            lookupLevel = L2;
260        }
261
262        L2Descriptor(L1Descriptor &parent) : data(0), l1Parent(&parent),
263                                             _dirty(false)
264        {
265            lookupLevel = L2;
266        }
267
268        virtual uint64_t getRawData() const
269        {
270            return (data);
271        }
272
273        virtual std::string dbgHeader() const
274        {
275            return "Inserting L2 Descriptor into TLB\n";
276        }
277
278        virtual TlbEntry::DomainType domain() const
279        {
280            return l1Parent->domain();
281        }
282
283        bool secure(bool have_security, WalkerState *currState) const
284        {
285            return l1Parent->secure(have_security, currState);
286        }
287
288        virtual uint8_t offsetBits() const
289        {
290            return large() ? 16 : 12;
291        }
292
293        /** Is the entry invalid */
294        bool invalid() const
295        {
296            return bits(data, 1, 0) == 0;
297        }
298
299        /** What is the size of the mapping? */
300        bool large() const
301        {
302            return bits(data, 1) == 0;
303        }
304
305        /** Is execution allowed on this mapping? */
306        bool xn() const
307        {
308            return large() ? bits(data, 15) : bits(data, 0);
309        }
310
311        /** Is the translation global (no asid used)? */
312        bool global(WalkerState *currState) const
313        {
314            return !bits(data, 11);
315        }
316
317        /** Three bit access protection flags */
318        uint8_t ap() const
319        {
320           return bits(data, 5, 4) | (bits(data, 9) << 2);
321        }
322
323        /** Memory region attributes: ARM DDI 0406B: B3-32 */
324        uint8_t texcb() const
325        {
326            return large() ?
327                (bits(data, 2) | (bits(data, 3) << 1) | (bits(data, 14, 12) << 2)) :
328                (bits(data, 2) | (bits(data, 3) << 1) | (bits(data, 8, 6) << 2));
329        }
330
331        /** Return the physical frame, bits shifted right */
332        Addr pfn() const
333        {
334            return large() ? bits(data, 31, 16) : bits(data, 31, 12);
335        }
336
337        /** Return complete physical address given a VA */
338        Addr paddr(Addr va) const
339        {
340            if (large())
341                return mbits(data, 31, 16) | mbits(va, 15, 0);
342            else
343                return mbits(data, 31, 12) | mbits(va, 11, 0);
344        }
345
346        /** If the section is shareable. See texcb() comment. */
347        bool shareable() const
348        {
349            return bits(data, 10);
350        }
351
352        /** Set access flag that this entry has been touched. Mark
353         * the entry as requiring a writeback, in the future.
354         */
355        void setAp0()
356        {
357            data |= 1 << 4;
358            _dirty = true;
359        }
360
361        /** This entry needs to be written back to memory */
362        bool dirty() const
363        {
364            return _dirty;
365        }
366
367    };
368
369    // Granule sizes for AArch64 long descriptors
370    enum GrainSize {
371        Grain4KB  = 12,
372        Grain16KB = 14,
373        Grain64KB = 16,
374        ReservedGrain = 0
375    };
376
377    /** Long-descriptor format (LPAE) */
378    class LongDescriptor : public DescriptorBase {
379      public:
380        /** Descriptor type */
381        enum EntryType {
382            Invalid,
383            Table,
384            Block,
385            Page
386        };
387
388        LongDescriptor() : data(0), _dirty(false) {}
389
390        /** The raw bits of the entry */
391        uint64_t data;
392
393        /** This entry has been modified (access flag set) and needs to be
394         * written back to memory */
395        bool _dirty;
396
397        virtual uint64_t getRawData() const
398        {
399            return (data);
400        }
401
402        virtual std::string dbgHeader() const
403        {
404            if (type() == LongDescriptor::Page) {
405                assert(lookupLevel == L3);
406                return "Inserting Page descriptor into TLB\n";
407            } else {
408                assert(lookupLevel < L3);
409                return "Inserting Block descriptor into TLB\n";
410            }
411        }
412
413        /**
414         * Returns true if this entry targets the secure physical address
415         * map.
416         */
417        bool secure(bool have_security, WalkerState *currState) const
418        {
419            assert(type() == Block || type() == Page);
420            return have_security && (currState->secureLookup && !bits(data, 5));
421        }
422
423        /** True if the current lookup is performed in AArch64 state */
424        bool aarch64;
425
426        /** Width of the granule size in bits */
427        GrainSize grainSize;
428
429        /** Return the descriptor type */
430        EntryType type() const
431        {
432            switch (bits(data, 1, 0)) {
433              case 0x1:
434                // In AArch64 blocks are not allowed at L0 for the 4 KB granule
435                // and at L1 for 16/64 KB granules
436                if (grainSize > Grain4KB)
437                    return lookupLevel == L2 ? Block : Invalid;
438                return lookupLevel == L0 || lookupLevel == L3 ? Invalid : Block;
439              case 0x3:
440                return lookupLevel == L3 ? Page : Table;
441              default:
442                return Invalid;
443            }
444        }
445
446        /** Return the bit width of the page/block offset */
447        uint8_t offsetBits() const
448        {
449            if (type() == Block) {
450                switch (grainSize) {
451                    case Grain4KB:
452                        return lookupLevel == L1 ? 30 /* 1 GB */
453                                                 : 21 /* 2 MB */;
454                    case Grain16KB:
455                        return 25  /* 32 MB */;
456                    case Grain64KB:
457                        return 29 /* 512 MB */;
458                    default:
459                        panic("Invalid AArch64 VM granule size\n");
460                }
461            } else if (type() == Page) {
462                switch (grainSize) {
463                    case Grain4KB:
464                    case Grain16KB:
465                    case Grain64KB:
466                        return grainSize; /* enum -> uint okay */
467                    default:
468                        panic("Invalid AArch64 VM granule size\n");
469                }
470            } else {
471                panic("AArch64 page table entry must be block or page\n");
472            }
473        }
474
475        /** Return the physical frame, bits shifted right */
476        Addr pfn() const
477        {
478            if (aarch64)
479                return bits(data, 47, offsetBits());
480            return bits(data, 39, offsetBits());
481        }
482
483        /** Return the complete physical address given a VA */
484        Addr paddr(Addr va) const
485        {
486            int n = offsetBits();
487            if (aarch64)
488                return mbits(data, 47, n) | mbits(va, n - 1, 0);
489            return mbits(data, 39, n) | mbits(va, n - 1, 0);
490        }
491
492        /** Return the physical address of the entry */
493        Addr paddr() const
494        {
495            if (aarch64)
496                return mbits(data, 47, offsetBits());
497            return mbits(data, 39, offsetBits());
498        }
499
500        /** Return the address of the next page table */
501        Addr nextTableAddr() const
502        {
503            assert(type() == Table);
504            if (aarch64)
505                return mbits(data, 47, grainSize);
506            else
507                return mbits(data, 39, 12);
508        }
509
510        /** Return the address of the next descriptor */
511        Addr nextDescAddr(Addr va) const
512        {
513            assert(type() == Table);
514            Addr pa = 0;
515            if (aarch64) {
516                int stride = grainSize - 3;
517                int va_lo = stride * (3 - (lookupLevel + 1)) + grainSize;
518                int va_hi = va_lo + stride - 1;
519                pa = nextTableAddr() | (bits(va, va_hi, va_lo) << 3);
520            } else {
521                if (lookupLevel == L1)
522                    pa = nextTableAddr() | (bits(va, 29, 21) << 3);
523                else  // lookupLevel == L2
524                    pa = nextTableAddr() | (bits(va, 20, 12) << 3);
525            }
526            return pa;
527        }
528
529        /** Is execution allowed on this mapping? */
530        bool xn() const
531        {
532            assert(type() == Block || type() == Page);
533            return bits(data, 54);
534        }
535
536        /** Is privileged execution allowed on this mapping? (LPAE only) */
537        bool pxn() const
538        {
539            assert(type() == Block || type() == Page);
540            return bits(data, 53);
541        }
542
543        /** Contiguous hint bit. */
544        bool contiguousHint() const
545        {
546            assert(type() == Block || type() == Page);
547            return bits(data, 52);
548        }
549
550        /** Is the translation global (no asid used)? */
551        bool global(WalkerState *currState) const
552        {
553            assert(currState && (type() == Block || type() == Page));
554            if (!currState->aarch64 && (currState->isSecure &&
555                                        !currState->secureLookup)) {
556                return false;  // ARM ARM issue C B3.6.3
557            } else if (currState->aarch64) {
558                if (currState->el == EL2 || currState->el == EL3) {
559                    return true;  // By default translations are treated as global
560                                  // in AArch64 EL2 and EL3
561                } else if (currState->isSecure && !currState->secureLookup) {
562                    return false;
563                }
564            }
565            return !bits(data, 11);
566        }
567
568        /** Returns true if the access flag (AF) is set. */
569        bool af() const
570        {
571            assert(type() == Block || type() == Page);
572            return bits(data, 10);
573        }
574
575        /** 2-bit shareability field */
576        uint8_t sh() const
577        {
578            assert(type() == Block || type() == Page);
579            return bits(data, 9, 8);
580        }
581
582        /** 2-bit access protection flags */
583        uint8_t ap() const
584        {
585            assert(type() == Block || type() == Page);
586            // Long descriptors only support the AP[2:1] scheme
587            return bits(data, 7, 6);
588        }
589
590        /** Read/write access protection flag */
591        bool rw() const
592        {
593            assert(type() == Block || type() == Page);
594            return !bits(data, 7);
595        }
596
597        /** User/privileged level access protection flag */
598        bool user() const
599        {
600            assert(type() == Block || type() == Page);
601            return bits(data, 6);
602        }
603
604        /** Return the AP bits as compatible with the AP[2:0] format.  Utility
605         * function used to simplify the code in the TLB for performing
606         * permission checks. */
607        static uint8_t ap(bool rw, bool user)
608        {
609            return ((!rw) << 2) | (user << 1);
610        }
611
612        TlbEntry::DomainType domain() const
613        {
614            // Long-desc. format only supports Client domain
615            assert(type() == Block || type() == Page);
616            return TlbEntry::DomainType::Client;
617        }
618
619        /** Attribute index */
620        uint8_t attrIndx() const
621        {
622            assert(type() == Block || type() == Page);
623            return bits(data, 4, 2);
624        }
625
626        /** Memory attributes, only used by stage 2 translations */
627        uint8_t memAttr() const
628        {
629            assert(type() == Block || type() == Page);
630            return bits(data, 5, 2);
631        }
632
633        /** Set access flag that this entry has been touched.  Mark the entry as
634         * requiring a writeback, in the future. */
635        void setAf()
636        {
637            data |= 1 << 10;
638            _dirty = true;
639        }
640
641        /** This entry needs to be written back to memory */
642        bool dirty() const
643        {
644            return _dirty;
645        }
646
647        /** Whether the subsequent levels of lookup are secure */
648        bool secureTable() const
649        {
650            assert(type() == Table);
651            return !bits(data, 63);
652        }
653
654        /** Two bit access protection flags for subsequent levels of lookup */
655        uint8_t apTable() const
656        {
657            assert(type() == Table);
658            return bits(data, 62, 61);
659        }
660
661        /** R/W protection flag for subsequent levels of lookup */
662        uint8_t rwTable() const
663        {
664            assert(type() == Table);
665            return !bits(data, 62);
666        }
667
668        /** User/privileged mode protection flag for subsequent levels of
669         * lookup */
670        uint8_t userTable() const
671        {
672            assert(type() == Table);
673            return !bits(data, 61);
674        }
675
676        /** Is execution allowed on subsequent lookup levels? */
677        bool xnTable() const
678        {
679            assert(type() == Table);
680            return bits(data, 60);
681        }
682
683        /** Is privileged execution allowed on subsequent lookup levels? */
684        bool pxnTable() const
685        {
686            assert(type() == Table);
687            return bits(data, 59);
688        }
689    };
690
691    class WalkerState
692    {
693      public:
694        /** Thread context that we're doing the walk for */
695        ThreadContext *tc;
696
697        /** If the access is performed in AArch64 state */
698        bool aarch64;
699
700        /** Current exception level */
701        ExceptionLevel el;
702
703        /** Current physical address range in bits */
704        int physAddrRange;
705
706        /** Request that is currently being serviced */
707        RequestPtr req;
708
709        /** ASID that we're servicing the request under */
710        uint16_t asid;
711        uint8_t vmid;
712        bool    isHyp;
713
714        /** Translation state for delayed requests */
715        TLB::Translation *transState;
716
717        /** The fault that we are going to return */
718        Fault fault;
719
720        /** The virtual address that is being translated with tagging removed.*/
721        Addr vaddr;
722
723        /** The virtual address that is being translated */
724        Addr vaddr_tainted;
725
726        /** Cached copy of the sctlr as it existed when translation began */
727        SCTLR sctlr;
728
729        /** Cached copy of the scr as it existed when translation began */
730        SCR scr;
731
732        /** Cached copy of the cpsr as it existed when translation began */
733        CPSR cpsr;
734
735        /** Cached copy of ttbcr/tcr as it existed when translation began */
736        union {
737            TTBCR ttbcr; // AArch32 translations
738            TCR tcr;     // AArch64 translations
739        };
740
741        /** Cached copy of the htcr as it existed when translation began. */
742        HTCR htcr;
743
744        /** Cached copy of the htcr as it existed when translation began. */
745        HCR  hcr;
746
747        /** Cached copy of the vtcr as it existed when translation began. */
748        VTCR_t vtcr;
749
750        /** If the access is a write */
751        bool isWrite;
752
753        /** If the access is a fetch (for execution, and no-exec) must be checked?*/
754        bool isFetch;
755
756        /** If the access comes from the secure state. */
757        bool isSecure;
758
759        /** Helper variables used to implement hierarchical access permissions
760         * when the long-desc. format is used (LPAE only) */
761        bool secureLookup;
762        bool rwTable;
763        bool userTable;
764        bool xnTable;
765        bool pxnTable;
766
767        /** Hierarchical access permission disable */
768        bool hpd;
769
770        /** Flag indicating if a second stage of lookup is required */
771        bool stage2Req;
772
773        /** A pointer to the stage 2 translation that's in progress */
774        TLB::Translation *stage2Tran;
775
776        /** If the mode is timing or atomic */
777        bool timing;
778
779        /** If the atomic mode should be functional */
780        bool functional;
781
782        /** Save mode for use in delayed response */
783        BaseTLB::Mode mode;
784
785        /** The translation type that has been requested */
786        TLB::ArmTranslationType tranType;
787
788        /** Short-format descriptors */
789        L1Descriptor l1Desc;
790        L2Descriptor l2Desc;
791
792        /** Long-format descriptor (LPAE and AArch64) */
793        LongDescriptor longDesc;
794
795        /** Whether the response is delayed in timing mode due to additional
796         * lookups */
797        bool delayed;
798
799        TableWalker *tableWalker;
800
801        /** Timestamp for calculating elapsed time in service (for stats) */
802        Tick startTime;
803
804        /** Page entries walked during service (for stats) */
805        unsigned levels;
806
807        void doL1Descriptor();
808        void doL2Descriptor();
809
810        void doLongDescriptor();
811
812        WalkerState();
813
814        std::string name() const { return tableWalker->name(); }
815    };
816
817  protected:
818
819    /** Queues of requests for all the different lookup levels */
820    std::list<WalkerState *> stateQueues[MAX_LOOKUP_LEVELS];
821
822    /** Queue of requests that have passed are waiting because the walker is
823     * currently busy. */
824    std::list<WalkerState *> pendingQueue;
825
826    /** The MMU to forward second stage look upts to */
827    Stage2MMU *stage2Mmu;
828
829    /** Port shared by the two table walkers. */
830    DmaPort* port;
831
832    /** Master id assigned by the MMU. */
833    MasterID masterId;
834
835    /** Indicates whether this table walker is part of the stage 2 mmu */
836    const bool isStage2;
837
838    /** TLB that is initiating these table walks */
839    TLB *tlb;
840
841    /** Cached copy of the sctlr as it existed when translation began */
842    SCTLR sctlr;
843
844    WalkerState *currState;
845
846    /** If a timing translation is currently in progress */
847    bool pending;
848
849    /** The number of walks belonging to squashed instructions that can be
850     * removed from the pendingQueue per cycle. */
851    unsigned numSquashable;
852
853    /** Cached copies of system-level properties */
854    bool haveSecurity;
855    bool _haveLPAE;
856    bool _haveVirtualization;
857    uint8_t physAddrRange;
858    bool _haveLargeAsid64;
859
860    /** Statistics */
861    Stats::Scalar statWalks;
862    Stats::Scalar statWalksShortDescriptor;
863    Stats::Scalar statWalksLongDescriptor;
864    Stats::Vector statWalksShortTerminatedAtLevel;
865    Stats::Vector statWalksLongTerminatedAtLevel;
866    Stats::Scalar statSquashedBefore;
867    Stats::Scalar statSquashedAfter;
868    Stats::Histogram statWalkWaitTime;
869    Stats::Histogram statWalkServiceTime;
870    Stats::Histogram statPendingWalks; // essentially "L" of queueing theory
871    Stats::Vector statPageSizes;
872    Stats::Vector2d statRequestOrigin;
873
874    mutable unsigned pendingReqs;
875    mutable Tick pendingChangeTick;
876
877    static const unsigned REQUESTED = 0;
878    static const unsigned COMPLETED = 1;
879
880  public:
881   typedef ArmTableWalkerParams Params;
882    TableWalker(const Params *p);
883    virtual ~TableWalker();
884
885    const Params *
886    params() const
887    {
888        return dynamic_cast<const Params *>(_params);
889    }
890
891    void init() override;
892
893    bool haveLPAE() const { return _haveLPAE; }
894    bool haveVirtualization() const { return _haveVirtualization; }
895    bool haveLargeAsid64() const { return _haveLargeAsid64; }
896    /** Checks if all state is cleared and if so, completes drain */
897    void completeDrain();
898    DrainState drain() override;
899    void drainResume() override;
900
901    Port &getPort(const std::string &if_name,
902                  PortID idx=InvalidPortID) override;
903
904    void regStats() override;
905
906    Fault walk(const RequestPtr &req, ThreadContext *tc,
907               uint16_t asid, uint8_t _vmid,
908               bool _isHyp, TLB::Mode mode, TLB::Translation *_trans,
909               bool timing, bool functional, bool secure,
910               TLB::ArmTranslationType tranType, bool _stage2Req);
911
912    void setTlb(TLB *_tlb) { tlb = _tlb; }
913    TLB* getTlb() { return tlb; }
914    void setMMU(Stage2MMU *m, MasterID master_id);
915    void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
916                  uint8_t texcb, bool s);
917    void memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
918                      LongDescriptor &lDescriptor);
919    void memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
920                         LongDescriptor &lDescriptor);
921
922    static LookupLevel toLookupLevel(uint8_t lookup_level_as_int);
923
924  private:
925
926    void doL1Descriptor();
927    void doL1DescriptorWrapper();
928    EventFunctionWrapper doL1DescEvent;
929
930    void doL2Descriptor();
931    void doL2DescriptorWrapper();
932    EventFunctionWrapper doL2DescEvent;
933
934    void doLongDescriptor();
935
936    void doL0LongDescriptorWrapper();
937    EventFunctionWrapper doL0LongDescEvent;
938    void doL1LongDescriptorWrapper();
939    EventFunctionWrapper doL1LongDescEvent;
940    void doL2LongDescriptorWrapper();
941    EventFunctionWrapper doL2LongDescEvent;
942    void doL3LongDescriptorWrapper();
943    EventFunctionWrapper doL3LongDescEvent;
944
945    void doLongDescriptorWrapper(LookupLevel curr_lookup_level);
946    Event* LongDescEventByLevel[4];
947
948    bool fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
949        Request::Flags flags, int queueIndex, Event *event,
950        void (TableWalker::*doDescriptor)());
951
952    Fault generateLongDescFault(ArmFault::FaultSource src);
953
954    void insertTableEntry(DescriptorBase &descriptor, bool longDescriptor);
955
956    Fault processWalk();
957    Fault processWalkLPAE();
958    static unsigned adjustTableSizeAArch64(unsigned tsz);
959    /// Returns true if the address exceeds the range permitted by the
960    /// system-wide setting or by the TCR_ELx IPS/PS setting
961    static bool checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange);
962    Fault processWalkAArch64();
963    void processWalkWrapper();
964    EventFunctionWrapper doProcessEvent;
965
966    void nextWalk(ThreadContext *tc);
967
968    void pendingChange();
969
970    static uint8_t pageSizeNtoStatBin(uint8_t N);
971
972    Fault testWalk(Addr pa, Addr size, TlbEntry::DomainType domain,
973                   LookupLevel lookup_level);
974};
975
976} // namespace ArmISA
977
978#endif //__ARCH_ARM_TABLE_WALKER_HH__
979
980