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