table_walker.hh revision 10037:5cac77888310
1/*
2 * Copyright (c) 2010-2013 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/mem_object.hh"
51#include "mem/request.hh"
52#include "params/ArmTableWalker.hh"
53#include "sim/eventq.hh"
54#include "sim/fault_fwd.hh"
55
56class ThreadContext;
57
58namespace ArmISA {
59class Translation;
60class TLB;
61class Stage2MMU;
62
63class TableWalker : public MemObject
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()
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()
255        {
256            lookupLevel = L2;
257        }
258
259        L2Descriptor(L1Descriptor &parent) : l1Parent(&parent)
260        {
261            lookupLevel = L2;
262        }
263
264        virtual uint64_t getRawData() const
265        {
266            return (data);
267        }
268
269        virtual std::string dbgHeader() const
270        {
271            return "Inserting L2 Descriptor into TLB\n";
272        }
273
274        virtual TlbEntry::DomainType domain() const
275        {
276            return l1Parent->domain();
277        }
278
279        bool secure(bool have_security, WalkerState *currState) const
280        {
281            return l1Parent->secure(have_security, currState);
282        }
283
284        virtual uint8_t offsetBits() const
285        {
286            return large() ? 16 : 12;
287        }
288
289        /** Is the entry invalid */
290        bool invalid() const
291        {
292            return bits(data, 1, 0) == 0;
293        }
294
295        /** What is the size of the mapping? */
296        bool large() const
297        {
298            return bits(data, 1) == 0;
299        }
300
301        /** Is execution allowed on this mapping? */
302        bool xn() const
303        {
304            return large() ? bits(data, 15) : bits(data, 0);
305        }
306
307        /** Is the translation global (no asid used)? */
308        bool global(WalkerState *currState) const
309        {
310            return !bits(data, 11);
311        }
312
313        /** Three bit access protection flags */
314        uint8_t ap() const
315        {
316           return bits(data, 5, 4) | (bits(data, 9) << 2);
317        }
318
319        /** Memory region attributes: ARM DDI 0406B: B3-32 */
320        uint8_t texcb() const
321        {
322            return large() ?
323                (bits(data, 2) | (bits(data, 3) << 1) | (bits(data, 14, 12) << 2)) :
324                (bits(data, 2) | (bits(data, 3) << 1) | (bits(data, 8, 6) << 2));
325        }
326
327        /** Return the physical frame, bits shifted right */
328        Addr pfn() const
329        {
330            return large() ? bits(data, 31, 16) : bits(data, 31, 12);
331        }
332
333        /** Return complete physical address given a VA */
334        Addr paddr(Addr va) const
335        {
336            if (large())
337                return mbits(data, 31, 16) | mbits(va, 15, 0);
338            else
339                return mbits(data, 31, 12) | mbits(va, 11, 0);
340        }
341
342        /** If the section is shareable. See texcb() comment. */
343        bool shareable() const
344        {
345            return bits(data, 10);
346        }
347
348        /** Set access flag that this entry has been touched. Mark
349         * the entry as requiring a writeback, in the future.
350         */
351        void setAp0()
352        {
353            data |= 1 << 4;
354            _dirty = true;
355        }
356
357        /** This entry needs to be written back to memory */
358        bool dirty() const
359        {
360            return _dirty;
361        }
362
363    };
364
365    /** Long-descriptor format (LPAE) */
366    class LongDescriptor : public DescriptorBase {
367      public:
368        /** Descriptor type */
369        enum EntryType {
370            Invalid,
371            Table,
372            Block,
373            Page
374        };
375
376        /** The raw bits of the entry */
377        uint64_t data;
378
379        /** This entry has been modified (access flag set) and needs to be
380         * written back to memory */
381        bool _dirty;
382
383        virtual uint64_t getRawData() const
384        {
385            return (data);
386        }
387
388        virtual std::string dbgHeader() const
389        {
390            if (type() == LongDescriptor::Page) {
391                assert(lookupLevel == L3);
392                return "Inserting Page descriptor into TLB\n";
393            } else {
394                assert(lookupLevel < L3);
395                return "Inserting Block descriptor into TLB\n";
396            }
397        }
398
399        /**
400         * Returns true if this entry targets the secure physical address
401         * map.
402         */
403        bool secure(bool have_security, WalkerState *currState) const
404        {
405            assert(type() == Block || type() == Page);
406            return have_security && (currState->secureLookup && !bits(data, 5));
407        }
408
409        /** True if the current lookup is performed in AArch64 state */
410        bool aarch64;
411
412        /** True if the granule size is 64 KB (AArch64 only) */
413        bool largeGrain;
414
415        /** Width of the granule size in bits */
416        int grainSize;
417
418        /** Return the descriptor type */
419        EntryType type() const
420        {
421            switch (bits(data, 1, 0)) {
422              case 0x1:
423                // In AArch64 blocks are not allowed at L0 for the 4 KB granule
424                // and at L1 for the 64 KB granule
425                if (largeGrain)
426                    return lookupLevel == L2 ? Block : Invalid;
427                return lookupLevel == L0 || lookupLevel == L3 ? Invalid : Block;
428              case 0x3:
429                return lookupLevel == L3 ? Page : Table;
430              default:
431                return Invalid;
432            }
433        }
434
435        /** Return the bit width of the page/block offset */
436        uint8_t offsetBits() const
437        {
438            assert(type() == Block || type() == Page);
439            if (largeGrain) {
440                if (type() == Block)
441                    return 29 /* 512 MB */;
442                return 16 /* 64 KB */;  // type() == Page
443            } else {
444                if (type() == Block)
445                    return lookupLevel == L1 ? 30 /* 1 GB */ : 21 /* 2 MB */;
446                return 12 /* 4 KB */;  // type() == Page
447            }
448        }
449
450        /** Return the physical frame, bits shifted right */
451        Addr pfn() const
452        {
453            if (aarch64)
454                return bits(data, 47, offsetBits());
455            return bits(data, 39, offsetBits());
456        }
457
458        /** Return the complete physical address given a VA */
459        Addr paddr(Addr va) const
460        {
461            int n = offsetBits();
462            if (aarch64)
463                return mbits(data, 47, n) | mbits(va, n - 1, 0);
464            return mbits(data, 39, n) | mbits(va, n - 1, 0);
465        }
466
467        /** Return the physical address of the entry */
468        Addr paddr() const
469        {
470            if (aarch64)
471                return mbits(data, 47, offsetBits());
472            return mbits(data, 39, offsetBits());
473        }
474
475        /** Return the address of the next page table */
476        Addr nextTableAddr() const
477        {
478            assert(type() == Table);
479            if (aarch64)
480                return mbits(data, 47, grainSize);
481            else
482                return mbits(data, 39, 12);
483        }
484
485        /** Return the address of the next descriptor */
486        Addr nextDescAddr(Addr va) const
487        {
488            assert(type() == Table);
489            Addr pa = 0;
490            if (aarch64) {
491                int stride = grainSize - 3;
492                int va_lo = stride * (3 - (lookupLevel + 1)) + grainSize;
493                int va_hi = va_lo + stride - 1;
494                pa = nextTableAddr() | (bits(va, va_hi, va_lo) << 3);
495            } else {
496                if (lookupLevel == L1)
497                    pa = nextTableAddr() | (bits(va, 29, 21) << 3);
498                else  // lookupLevel == L2
499                    pa = nextTableAddr() | (bits(va, 20, 12) << 3);
500            }
501            return pa;
502        }
503
504        /** Is execution allowed on this mapping? */
505        bool xn() const
506        {
507            assert(type() == Block || type() == Page);
508            return bits(data, 54);
509        }
510
511        /** Is privileged execution allowed on this mapping? (LPAE only) */
512        bool pxn() const
513        {
514            assert(type() == Block || type() == Page);
515            return bits(data, 53);
516        }
517
518        /** Contiguous hint bit. */
519        bool contiguousHint() const
520        {
521            assert(type() == Block || type() == Page);
522            return bits(data, 52);
523        }
524
525        /** Is the translation global (no asid used)? */
526        bool global(WalkerState *currState) const
527        {
528            assert(currState && (type() == Block || type() == Page));
529            if (!currState->aarch64 && (currState->isSecure &&
530                                        !currState->secureLookup)) {
531                return false;  // ARM ARM issue C B3.6.3
532            } else if (currState->aarch64) {
533                if (currState->el == EL2 || currState->el == EL3) {
534                    return true;  // By default translations are treated as global
535                                  // in AArch64 EL2 and EL3
536                } else if (currState->isSecure && !currState->secureLookup) {
537                    return false;
538                }
539            }
540            return !bits(data, 11);
541        }
542
543        /** Returns true if the access flag (AF) is set. */
544        bool af() const
545        {
546            assert(type() == Block || type() == Page);
547            return bits(data, 10);
548        }
549
550        /** 2-bit shareability field */
551        uint8_t sh() const
552        {
553            assert(type() == Block || type() == Page);
554            return bits(data, 9, 8);
555        }
556
557        /** 2-bit access protection flags */
558        uint8_t ap() const
559        {
560            assert(type() == Block || type() == Page);
561            // Long descriptors only support the AP[2:1] scheme
562            return bits(data, 7, 6);
563        }
564
565        /** Read/write access protection flag */
566        bool rw() const
567        {
568            assert(type() == Block || type() == Page);
569            return !bits(data, 7);
570        }
571
572        /** User/privileged level access protection flag */
573        bool user() const
574        {
575            assert(type() == Block || type() == Page);
576            return bits(data, 6);
577        }
578
579        /** Return the AP bits as compatible with the AP[2:0] format.  Utility
580         * function used to simplify the code in the TLB for performing
581         * permission checks. */
582        static uint8_t ap(bool rw, bool user)
583        {
584            return ((!rw) << 2) | (user << 1);
585        }
586
587        TlbEntry::DomainType domain() const
588        {
589            // Long-desc. format only supports Client domain
590            assert(type() == Block || type() == Page);
591            return TlbEntry::DomainType::Client;
592        }
593
594        /** Attribute index */
595        uint8_t attrIndx() const
596        {
597            assert(type() == Block || type() == Page);
598            return bits(data, 4, 2);
599        }
600
601        /** Memory attributes, only used by stage 2 translations */
602        uint8_t memAttr() const
603        {
604            assert(type() == Block || type() == Page);
605            return bits(data, 5, 2);
606        }
607
608        /** Set access flag that this entry has been touched.  Mark the entry as
609         * requiring a writeback, in the future. */
610        void setAf()
611        {
612            data |= 1 << 10;
613            _dirty = true;
614        }
615
616        /** This entry needs to be written back to memory */
617        bool dirty() const
618        {
619            return _dirty;
620        }
621
622        /** Whether the subsequent levels of lookup are secure */
623        bool secureTable() const
624        {
625            assert(type() == Table);
626            return !bits(data, 63);
627        }
628
629        /** Two bit access protection flags for subsequent levels of lookup */
630        uint8_t apTable() const
631        {
632            assert(type() == Table);
633            return bits(data, 62, 61);
634        }
635
636        /** R/W protection flag for subsequent levels of lookup */
637        uint8_t rwTable() const
638        {
639            assert(type() == Table);
640            return !bits(data, 62);
641        }
642
643        /** User/privileged mode protection flag for subsequent levels of
644         * lookup */
645        uint8_t userTable() const
646        {
647            assert(type() == Table);
648            return !bits(data, 61);
649        }
650
651        /** Is execution allowed on subsequent lookup levels? */
652        bool xnTable() const
653        {
654            assert(type() == Table);
655            return bits(data, 60);
656        }
657
658        /** Is privileged execution allowed on subsequent lookup levels? */
659        bool pxnTable() const
660        {
661            assert(type() == Table);
662            return bits(data, 59);
663        }
664    };
665
666    class WalkerState
667    {
668      public:
669        /** Thread context that we're doing the walk for */
670        ThreadContext *tc;
671
672        /** If the access is performed in AArch64 state */
673        bool aarch64;
674
675        /** Current exception level */
676        ExceptionLevel el;
677
678        /** Current physical address range in bits */
679        int physAddrRange;
680
681        /** Request that is currently being serviced */
682        RequestPtr req;
683
684        /** ASID that we're servicing the request under */
685        uint16_t asid;
686        uint8_t vmid;
687        bool    isHyp;
688
689        /** Translation state for delayed requests */
690        TLB::Translation *transState;
691
692        /** The fault that we are going to return */
693        Fault fault;
694
695        /** The virtual address that is being translated with tagging removed.*/
696        Addr vaddr;
697
698        /** The virtual address that is being translated */
699        Addr vaddr_tainted;
700
701        /** Cached copy of the sctlr as it existed when translation began */
702        SCTLR sctlr;
703
704        /** Cached copy of the scr as it existed when translation began */
705        SCR scr;
706
707        /** Cached copy of the cpsr as it existed when translation began */
708        CPSR cpsr;
709
710        /** Cached copy of the ttbcr as it existed when translation began. */
711        TTBCR ttbcr;
712
713        /** Cached copy of the htcr as it existed when translation began. */
714        HTCR htcr;
715
716        /** Cached copy of the htcr as it existed when translation began. */
717        HCR  hcr;
718
719        /** Cached copy of the vtcr as it existed when translation began. */
720        VTCR_t vtcr;
721
722        /** If the access is a write */
723        bool isWrite;
724
725        /** If the access is a fetch (for execution, and no-exec) must be checked?*/
726        bool isFetch;
727
728        /** If the access comes from the secure state. */
729        bool isSecure;
730
731        /** Helper variables used to implement hierarchical access permissions
732         * when the long-desc. format is used (LPAE only) */
733        bool secureLookup;
734        bool rwTable;
735        bool userTable;
736        bool xnTable;
737        bool pxnTable;
738
739        /** Flag indicating if a second stage of lookup is required */
740        bool stage2Req;
741
742        /** Indicates whether the translation has been passed onto the second
743         *  stage mmu, and no more work is required from the first stage.
744         */
745        bool doingStage2;
746
747        /** A pointer to the stage 2 translation that's in progress */
748        TLB::Translation *stage2Tran;
749
750        /** If the mode is timing or atomic */
751        bool timing;
752
753        /** If the atomic mode should be functional */
754        bool functional;
755
756        /** Save mode for use in delayed response */
757        BaseTLB::Mode mode;
758
759        /** The translation type that has been requested */
760        TLB::ArmTranslationType tranType;
761
762        /** Short-format descriptors */
763        L1Descriptor l1Desc;
764        L2Descriptor l2Desc;
765
766        /** Long-format descriptor (LPAE and AArch64) */
767        LongDescriptor longDesc;
768
769        /** Whether the response is delayed in timing mode due to additional
770         * lookups */
771        bool delayed;
772
773        TableWalker *tableWalker;
774
775        void doL1Descriptor();
776        void doL2Descriptor();
777
778        void doLongDescriptor();
779
780        WalkerState();
781
782        std::string name() const { return tableWalker->name(); }
783    };
784
785  protected:
786
787    /**
788     * A snooping DMA port that currently does nothing besides
789     * extending the DMA port to accept snoops without complaining.
790     */
791    class SnoopingDmaPort : public DmaPort
792    {
793
794      protected:
795
796        virtual void recvTimingSnoopReq(PacketPtr pkt)
797        { }
798
799        virtual Tick recvAtomicSnoop(PacketPtr pkt)
800        { return 0; }
801
802        virtual void recvFunctionalSnoop(PacketPtr pkt)
803        { }
804
805        virtual bool isSnooping() const { return true; }
806
807      public:
808
809        /**
810         * A snooping DMA port merely calls the construtor of the DMA
811         * port.
812         */
813        SnoopingDmaPort(MemObject *dev, System *s) :
814            DmaPort(dev, s)
815        { }
816    };
817
818    /** Queues of requests for all the different lookup levels */
819    std::list<WalkerState *> stateQueues[MAX_LOOKUP_LEVELS];
820
821    /** Queue of requests that have passed are waiting because the walker is
822     * currently busy. */
823    std::list<WalkerState *> pendingQueue;
824
825
826    /** Port to issue translation requests from */
827    SnoopingDmaPort port;
828
829    /** If we're draining keep the drain event around until we're drained */
830    DrainManager *drainManager;
831
832    /** The MMU to forward second stage look upts to */
833    Stage2MMU *stage2Mmu;
834
835    /** Indicates whether this table walker is part of the stage 2 mmu */
836    const bool isStage2;
837
838    /** TLB that is initiating these table walks */
839    TLB *tlb;
840
841    /** Cached copy of the sctlr as it existed when translation began */
842    SCTLR sctlr;
843
844    WalkerState *currState;
845
846    /** If a timing translation is currently in progress */
847    bool pending;
848
849    /** Request id for requests generated by this walker */
850    MasterID masterId;
851
852    /** The number of walks belonging to squashed instructions that can be
853     * removed from the pendingQueue per cycle. */
854    unsigned numSquashable;
855
856    /** Cached copies of system-level properties */
857    bool haveSecurity;
858    bool _haveLPAE;
859    bool _haveVirtualization;
860    uint8_t physAddrRange;
861    bool _haveLargeAsid64;
862    ArmSystem *armSys;
863
864  public:
865   typedef ArmTableWalkerParams Params;
866    TableWalker(const Params *p);
867    virtual ~TableWalker();
868
869    const Params *
870    params() const
871    {
872        return dynamic_cast<const Params *>(_params);
873    }
874
875    bool haveLPAE() const { return _haveLPAE; }
876    bool haveVirtualization() const { return _haveVirtualization; }
877    bool haveLargeAsid64() const { return _haveLargeAsid64; }
878    /** Checks if all state is cleared and if so, completes drain */
879    void completeDrain();
880    unsigned int drain(DrainManager *dm);
881    virtual void drainResume();
882    virtual BaseMasterPort& getMasterPort(const std::string &if_name,
883                                          PortID idx = InvalidPortID);
884
885    /**
886     * Allow the MMU (overseeing both stage 1 and stage 2 TLBs) to
887     * access the table walker port through the TLB so that it can
888     * orchestrate staged translations.
889     *
890     * @return Our DMA port
891     */
892    DmaPort& getWalkerPort() { return port; }
893
894    Fault walk(RequestPtr req, ThreadContext *tc, uint16_t asid, uint8_t _vmid,
895               bool _isHyp, TLB::Mode mode, TLB::Translation *_trans,
896               bool timing, bool functional, bool secure,
897               TLB::ArmTranslationType tranType);
898
899    void setTlb(TLB *_tlb) { tlb = _tlb; }
900    TLB* getTlb() { return tlb; }
901    void setMMU(Stage2MMU *m) { stage2Mmu = m; }
902    void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
903                  uint8_t texcb, bool s);
904    void memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
905                      LongDescriptor &lDescriptor);
906    void memAttrsAArch64(ThreadContext *tc, TlbEntry &te, uint8_t attrIndx,
907                         uint8_t sh);
908
909    static LookupLevel toLookupLevel(uint8_t lookup_level_as_int);
910
911  private:
912
913    void doL1Descriptor();
914    void doL1DescriptorWrapper();
915    EventWrapper<TableWalker,
916                 &TableWalker::doL1DescriptorWrapper> doL1DescEvent;
917
918    void doL2Descriptor();
919    void doL2DescriptorWrapper();
920    EventWrapper<TableWalker,
921                 &TableWalker::doL2DescriptorWrapper> doL2DescEvent;
922
923    void doLongDescriptor();
924
925    void doL0LongDescriptorWrapper();
926    EventWrapper<TableWalker,
927                 &TableWalker::doL0LongDescriptorWrapper> doL0LongDescEvent;
928    void doL1LongDescriptorWrapper();
929    EventWrapper<TableWalker,
930                 &TableWalker::doL1LongDescriptorWrapper> doL1LongDescEvent;
931    void doL2LongDescriptorWrapper();
932    EventWrapper<TableWalker,
933                 &TableWalker::doL2LongDescriptorWrapper> doL2LongDescEvent;
934    void doL3LongDescriptorWrapper();
935    EventWrapper<TableWalker,
936                 &TableWalker::doL3LongDescriptorWrapper> doL3LongDescEvent;
937
938    void doLongDescriptorWrapper(LookupLevel curr_lookup_level);
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    EventWrapper<TableWalker, &TableWalker::processWalkWrapper> doProcessEvent;
955
956    void nextWalk(ThreadContext *tc);
957};
958
959} // namespace ArmISA
960
961#endif //__ARCH_ARM_TABLE_WALKER_HH__
962
963