table_walker.hh revision 10474:799c8ee4ecba
1/*
2 * Copyright (c) 2010-2014 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
55class ThreadContext;
56
57namespace ArmISA {
58class Translation;
59class TLB;
60class Stage2MMU;
61
62class TableWalker : public MemObject
63{
64  public:
65    class WalkerState;
66
67    class DescriptorBase {
68      public:
69        /** Current lookup level for this descriptor */
70        LookupLevel lookupLevel;
71
72        virtual Addr pfn() const = 0;
73        virtual TlbEntry::DomainType domain() const = 0;
74        virtual bool xn() const = 0;
75        virtual uint8_t ap() const = 0;
76        virtual bool global(WalkerState *currState) const = 0;
77        virtual uint8_t offsetBits() const = 0;
78        virtual bool secure(bool have_security, WalkerState *currState) const = 0;
79        virtual std::string dbgHeader() const = 0;
80        virtual uint64_t getRawData() const = 0;
81        virtual uint8_t texcb() const
82        {
83            panic("texcb() not implemented for this class\n");
84        }
85        virtual bool shareable() const
86        {
87            panic("shareable() not implemented for this class\n");
88        }
89    };
90
91    class L1Descriptor : public DescriptorBase {
92      public:
93        /** Type of page table entry ARM DDI 0406B: B3-8*/
94        enum EntryType {
95            Ignore,
96            PageTable,
97            Section,
98            Reserved
99        };
100
101        /** The raw bits of the entry */
102        uint32_t data;
103
104        /** This entry has been modified (access flag set) and needs to be
105         * written back to memory */
106        bool _dirty;
107
108        /** Default ctor */
109        L1Descriptor()
110        {
111            lookupLevel = L1;
112        }
113
114        virtual uint64_t getRawData() const
115        {
116            return (data);
117        }
118
119        virtual std::string dbgHeader() const
120        {
121            return "Inserting Section Descriptor into TLB\n";
122        }
123
124        virtual uint8_t offsetBits() const
125        {
126            return 20;
127        }
128
129        EntryType type() const
130        {
131            return (EntryType)(data & 0x3);
132        }
133
134        /** Is the page a Supersection (16MB)?*/
135        bool supersection() const
136        {
137            return bits(data, 18);
138        }
139
140        /** Return the physcal address of the entry, bits in position*/
141        Addr paddr() const
142        {
143            if (supersection())
144                panic("Super sections not implemented\n");
145            return mbits(data, 31, 20);
146        }
147        /** Return the physcal address of the entry, bits in position*/
148        Addr paddr(Addr va) const
149        {
150            if (supersection())
151                panic("Super sections not implemented\n");
152            return mbits(data, 31, 20) | mbits(va, 19, 0);
153        }
154
155
156        /** Return the physical frame, bits shifted right */
157        Addr pfn() const
158        {
159            if (supersection())
160                panic("Super sections not implemented\n");
161            return bits(data, 31, 20);
162        }
163
164        /** Is the translation global (no asid used)? */
165        bool global(WalkerState *currState) const
166        {
167            return !bits(data, 17);
168        }
169
170        /** Is the translation not allow execution? */
171        bool xn() const
172        {
173            return bits(data, 4);
174        }
175
176        /** Three bit access protection flags */
177        uint8_t ap() const
178        {
179            return (bits(data, 15) << 2) | bits(data, 11, 10);
180        }
181
182        /** Domain Client/Manager: ARM DDI 0406B: B3-31 */
183        TlbEntry::DomainType domain() const
184        {
185            return static_cast<TlbEntry::DomainType>(bits(data, 8, 5));
186        }
187
188        /** Address of L2 descriptor if it exists */
189        Addr l2Addr() const
190        {
191            return mbits(data, 31, 10);
192        }
193
194        /** Memory region attributes: ARM DDI 0406B: B3-32.
195         * These bits are largly ignored by M5 and only used to
196         * provide the illusion that the memory system cares about
197         * anything but cachable vs. uncachable.
198         */
199        uint8_t texcb() const
200        {
201            return bits(data, 2) | bits(data, 3) << 1 | bits(data, 14, 12) << 2;
202        }
203
204        /** If the section is shareable. See texcb() comment. */
205        bool shareable() const
206        {
207            return bits(data, 16);
208        }
209
210        /** Set access flag that this entry has been touched. Mark
211         * the entry as requiring a writeback, in the future.
212         */
213        void setAp0()
214        {
215            data |= 1 << 10;
216            _dirty = true;
217        }
218
219        /** This entry needs to be written back to memory */
220        bool dirty() const
221        {
222            return _dirty;
223        }
224
225        /**
226         * Returns true if this entry targets the secure physical address
227         * map.
228         */
229        bool secure(bool have_security, WalkerState *currState) const
230        {
231            if (have_security) {
232                if (type() == PageTable)
233                    return !bits(data, 3);
234                else
235                    return !bits(data, 19);
236            }
237            return false;
238        }
239    };
240
241    /** Level 2 page table descriptor */
242    class L2Descriptor : public DescriptorBase {
243      public:
244        /** The raw bits of the entry. */
245        uint32_t     data;
246        L1Descriptor *l1Parent;
247
248        /** This entry has been modified (access flag set) and needs to be
249         * written back to memory */
250        bool _dirty;
251
252        /** Default ctor */
253        L2Descriptor()
254        {
255            lookupLevel = L2;
256        }
257
258        L2Descriptor(L1Descriptor &parent) : l1Parent(&parent)
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        void doL1Descriptor();
797        void doL2Descriptor();
798
799        void doLongDescriptor();
800
801        WalkerState();
802
803        std::string name() const { return tableWalker->name(); }
804    };
805
806  protected:
807
808    /**
809     * A snooping DMA port that currently does nothing besides
810     * extending the DMA port to accept snoops without complaining.
811     */
812    class SnoopingDmaPort : public DmaPort
813    {
814
815      protected:
816
817        virtual void recvTimingSnoopReq(PacketPtr pkt)
818        { }
819
820        virtual Tick recvAtomicSnoop(PacketPtr pkt)
821        { return 0; }
822
823        virtual void recvFunctionalSnoop(PacketPtr pkt)
824        { }
825
826        virtual bool isSnooping() const { return true; }
827
828      public:
829
830        /**
831         * A snooping DMA port merely calls the construtor of the DMA
832         * port.
833         */
834        SnoopingDmaPort(MemObject *dev, System *s) :
835            DmaPort(dev, s)
836        { }
837    };
838
839    /** Queues of requests for all the different lookup levels */
840    std::list<WalkerState *> stateQueues[MAX_LOOKUP_LEVELS];
841
842    /** Queue of requests that have passed are waiting because the walker is
843     * currently busy. */
844    std::list<WalkerState *> pendingQueue;
845
846
847    /** Port to issue translation requests from */
848    SnoopingDmaPort port;
849
850    /** If we're draining keep the drain event around until we're drained */
851    DrainManager *drainManager;
852
853    /** The MMU to forward second stage look upts to */
854    Stage2MMU *stage2Mmu;
855
856    /** Indicates whether this table walker is part of the stage 2 mmu */
857    const bool isStage2;
858
859    /** TLB that is initiating these table walks */
860    TLB *tlb;
861
862    /** Cached copy of the sctlr as it existed when translation began */
863    SCTLR sctlr;
864
865    WalkerState *currState;
866
867    /** If a timing translation is currently in progress */
868    bool pending;
869
870    /** Request id for requests generated by this walker */
871    MasterID masterId;
872
873    /** The number of walks belonging to squashed instructions that can be
874     * removed from the pendingQueue per cycle. */
875    unsigned numSquashable;
876
877    /** Cached copies of system-level properties */
878    bool haveSecurity;
879    bool _haveLPAE;
880    bool _haveVirtualization;
881    uint8_t physAddrRange;
882    bool _haveLargeAsid64;
883    ArmSystem *armSys;
884
885  public:
886   typedef ArmTableWalkerParams Params;
887    TableWalker(const Params *p);
888    virtual ~TableWalker();
889
890    const Params *
891    params() const
892    {
893        return dynamic_cast<const Params *>(_params);
894    }
895
896    bool haveLPAE() const { return _haveLPAE; }
897    bool haveVirtualization() const { return _haveVirtualization; }
898    bool haveLargeAsid64() const { return _haveLargeAsid64; }
899    /** Checks if all state is cleared and if so, completes drain */
900    void completeDrain();
901    unsigned int drain(DrainManager *dm);
902    virtual void drainResume();
903    virtual BaseMasterPort& getMasterPort(const std::string &if_name,
904                                          PortID idx = InvalidPortID);
905
906    /**
907     * Allow the MMU (overseeing both stage 1 and stage 2 TLBs) to
908     * access the table walker port through the TLB so that it can
909     * orchestrate staged translations.
910     *
911     * @return Our DMA port
912     */
913    DmaPort& getWalkerPort() { return port; }
914
915    Fault walk(RequestPtr req, ThreadContext *tc, uint16_t asid, uint8_t _vmid,
916               bool _isHyp, TLB::Mode mode, TLB::Translation *_trans,
917               bool timing, bool functional, bool secure,
918               TLB::ArmTranslationType tranType);
919
920    void setTlb(TLB *_tlb) { tlb = _tlb; }
921    TLB* getTlb() { return tlb; }
922    void setMMU(Stage2MMU *m) { stage2Mmu = m; }
923    void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
924                  uint8_t texcb, bool s);
925    void memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
926                      LongDescriptor &lDescriptor);
927    void memAttrsAArch64(ThreadContext *tc, TlbEntry &te, uint8_t attrIndx,
928                         uint8_t sh);
929
930    static LookupLevel toLookupLevel(uint8_t lookup_level_as_int);
931
932  private:
933
934    void doL1Descriptor();
935    void doL1DescriptorWrapper();
936    EventWrapper<TableWalker,
937                 &TableWalker::doL1DescriptorWrapper> doL1DescEvent;
938
939    void doL2Descriptor();
940    void doL2DescriptorWrapper();
941    EventWrapper<TableWalker,
942                 &TableWalker::doL2DescriptorWrapper> doL2DescEvent;
943
944    void doLongDescriptor();
945
946    void doL0LongDescriptorWrapper();
947    EventWrapper<TableWalker,
948                 &TableWalker::doL0LongDescriptorWrapper> doL0LongDescEvent;
949    void doL1LongDescriptorWrapper();
950    EventWrapper<TableWalker,
951                 &TableWalker::doL1LongDescriptorWrapper> doL1LongDescEvent;
952    void doL2LongDescriptorWrapper();
953    EventWrapper<TableWalker,
954                 &TableWalker::doL2LongDescriptorWrapper> doL2LongDescEvent;
955    void doL3LongDescriptorWrapper();
956    EventWrapper<TableWalker,
957                 &TableWalker::doL3LongDescriptorWrapper> doL3LongDescEvent;
958
959    void doLongDescriptorWrapper(LookupLevel curr_lookup_level);
960
961    bool fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
962        Request::Flags flags, int queueIndex, Event *event,
963        void (TableWalker::*doDescriptor)());
964
965    void insertTableEntry(DescriptorBase &descriptor, bool longDescriptor);
966
967    Fault processWalk();
968    Fault processWalkLPAE();
969    static unsigned adjustTableSizeAArch64(unsigned tsz);
970    /// Returns true if the address exceeds the range permitted by the
971    /// system-wide setting or by the TCR_ELx IPS/PS setting
972    static bool checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange);
973    Fault processWalkAArch64();
974    void processWalkWrapper();
975    EventWrapper<TableWalker, &TableWalker::processWalkWrapper> doProcessEvent;
976
977    void nextWalk(ThreadContext *tc);
978};
979
980} // namespace ArmISA
981
982#endif //__ARCH_ARM_TABLE_WALKER_HH__
983
984