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