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