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