gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
table_walker.hh
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2016, 2019, 2021-2024 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/mmu.hh"
45#include "arch/arm/regs/misc.hh"
46#include "arch/arm/system.hh"
47#include "arch/arm/tlb.hh"
48#include "arch/arm/types.hh"
49#include "arch/generic/mmu.hh"
50#include "mem/packet_queue.hh"
51#include "mem/qport.hh"
52#include "mem/request.hh"
53#include "sim/clocked_object.hh"
54#include "sim/eventq.hh"
55
56namespace gem5
57{
58
59struct ArmTableWalkerParams;
60
61class ThreadContext;
62
63namespace ArmISA {
64class Translation;
65class TLB;
66
68{
69 using LookupLevel = enums::ArmLookupLevel;
70
71 public:
72 class WalkerState;
73
75 {
76 public:
78 virtual ~DescriptorBase() = default;
79
82
83 virtual Addr pfn() const = 0;
84 virtual DomainType domain() const = 0;
85 virtual bool xn() const = 0;
86 virtual uint8_t ap() const = 0;
87 virtual bool global(WalkerState *currState) const = 0;
88 virtual uint8_t offsetBits() const = 0;
89 virtual bool secure(bool have_security, WalkerState *currState) const = 0;
90 virtual std::string dbgHeader() const = 0;
91 virtual uint8_t* getRawPtr() = 0;
92 virtual uint64_t getRawData() const = 0;
93 virtual uint8_t texcb() const
94 {
95 panic("texcb() not implemented for this class\n");
96 }
97 virtual bool shareable() const
98 {
99 panic("shareable() not implemented for this class\n");
100 }
101 };
102
104 {
105 public:
114
116 uint32_t data;
117
120 bool _dirty;
121
123 L1Descriptor() : data(0), _dirty(false)
124 {
125 lookupLevel = LookupLevel::L1;
126 }
127 virtual ~L1Descriptor() = default;
128
129 uint8_t*
130 getRawPtr() override
131 {
132 return reinterpret_cast<uint8_t*>(&data);
133 }
134
135 uint64_t
136 getRawData() const override
137 {
138 return (data);
139 }
140
141 std::string
142 dbgHeader() const override
143 {
144 return "Inserting Section Descriptor into TLB\n";
145 }
146
147 uint8_t
148 offsetBits() const override
149 {
150 return 20;
151 }
152
154 type() const
155 {
156 return (EntryType)(data & 0x3);
157 }
158
160 bool
162 {
163 return bits(data, 18);
164 }
165
167 Addr
168 paddr() const
169 {
170 if (supersection())
171 panic("Super sections not implemented\n");
172 return mbits(data, 31, 20);
173 }
174
176 Addr
177 paddr(Addr va) const
178 {
179 if (supersection())
180 panic("Super sections not implemented\n");
181 return mbits(data, 31, 20) | mbits(va, 19, 0);
182 }
183
185 Addr
186 pfn() const override
187 {
188 if (supersection())
189 panic("Super sections not implemented\n");
190 return bits(data, 31, 20);
191 }
192
194 bool
195 global(WalkerState *currState) const override
196 {
197 return !bits(data, 17);
198 }
199
201 bool
202 xn() const override
203 {
204 return bits(data, 4);
205 }
206
208 uint8_t
209 ap() const override
210 {
211 return (bits(data, 15) << 2) | bits(data, 11, 10);
212 }
213
216 domain() const override
217 {
218 return static_cast<DomainType>(bits(data, 8, 5));
219 }
220
222 Addr
223 l2Addr() const
224 {
225 return mbits(data, 31, 10);
226 }
227
233 uint8_t
234 texcb() const override
235 {
236 return bits(data, 2) | bits(data, 3) << 1 | bits(data, 14, 12) << 2;
237 }
238
240 bool
241 shareable() const override
242 {
243 return bits(data, 16);
244 }
245
249 void
251 {
252 data |= 1 << 10;
253 _dirty = true;
254 }
255
257 bool
258 dirty() const
259 {
260 return _dirty;
261 }
262
267 bool
268 secure(bool have_security, WalkerState *currState) const override
269 {
270 if (have_security && currState->secureLookup) {
271 if (type() == PageTable)
272 return !bits(data, 3);
273 else
274 return !bits(data, 19);
275 }
276 return false;
277 }
278 };
279
282 {
283 public:
285 uint32_t data;
287
290 bool _dirty;
291
293 L2Descriptor() : data(0), l1Parent(nullptr), _dirty(false)
294 {
295 lookupLevel = LookupLevel::L2;
296 }
297
298 L2Descriptor(L1Descriptor &parent) : data(0), l1Parent(&parent),
299 _dirty(false)
300 {
301 lookupLevel = LookupLevel::L2;
302 }
303
304 virtual ~L2Descriptor() = default;
305
306 uint8_t*
307 getRawPtr() override
308 {
309 return reinterpret_cast<uint8_t*>(&data);
310 }
311
312 uint64_t
313 getRawData() const override
314 {
315 return (data);
316 }
317
318 std::string
319 dbgHeader() const override
320 {
321 return "Inserting L2 Descriptor into TLB\n";
322 }
323
325 domain() const override
326 {
327 return l1Parent->domain();
328 }
329
330 bool
331 secure(bool have_security, WalkerState *currState) const override
332 {
333 return l1Parent->secure(have_security, currState);
334 }
335
336 uint8_t
337 offsetBits() const override
338 {
339 return large() ? 16 : 12;
340 }
341
343 bool
344 invalid() const
345 {
346 return bits(data, 1, 0) == 0;
347 }
348
350 bool
351 large() const
352 {
353 return bits(data, 1) == 0;
354 }
355
357 bool
358 xn() const override
359 {
360 return large() ? bits(data, 15) : bits(data, 0);
361 }
362
364 bool
365 global(WalkerState *currState) const override
366 {
367 return !bits(data, 11);
368 }
369
371 uint8_t
372 ap() const override
373 {
374 return bits(data, 5, 4) | (bits(data, 9) << 2);
375 }
376
378 uint8_t
379 texcb() const override
380 {
381 return large() ?
382 (bits(data, 2) | (bits(data, 3) << 1) | (bits(data, 14, 12) << 2)) :
383 (bits(data, 2) | (bits(data, 3) << 1) | (bits(data, 8, 6) << 2));
384 }
385
387 Addr
388 pfn() const override
389 {
390 return large() ? bits(data, 31, 16) : bits(data, 31, 12);
391 }
392
394 Addr
395 paddr(Addr va) const
396 {
397 if (large())
398 return mbits(data, 31, 16) | mbits(va, 15, 0);
399 else
400 return mbits(data, 31, 12) | mbits(va, 11, 0);
401 }
402
404 bool
405 shareable() const override
406 {
407 return bits(data, 10);
408 }
409
413 void
415 {
416 data |= 1 << 4;
417 _dirty = true;
418 }
419
421 bool
422 dirty() const
423 {
424 return _dirty;
425 }
426
427 };
428
431 {
432 public:
441
443 : data(0), _dirty(false), aarch64(false), grainSize(Grain4KB),
444 physAddrRange(0), isStage2(false)
445 {}
446
448 uint64_t data;
449
452 bool _dirty;
453
456
459
461
463
464 uint8_t*
465 getRawPtr() override
466 {
467 return reinterpret_cast<uint8_t*>(&data);
468 }
469
470 uint64_t
471 getRawData() const override
472 {
473 return (data);
474 }
475
476 std::string
477 dbgHeader() const override
478 {
479 switch (type()) {
481 assert(lookupLevel == LookupLevel::L3);
482 return "Inserting Page descriptor into TLB\n";
484 assert(lookupLevel < LookupLevel::L3);
485 return "Inserting Block descriptor into TLB\n";
487 return "Inserting Table descriptor into TLB\n";
488 default:
489 panic("Trying to insert and invalid descriptor\n");
490 }
491 }
492
497 bool
498 secure(bool have_security, WalkerState *currState) const override
499 {
500 if (type() == Block || type() == Page) {
501 if (isStage2) {
502 return have_security && currState->secureLookup &&
503 !currState->vtcr.nsa;
504 } else {
505 return have_security &&
506 (currState->secureLookup && !bits(data, 5));
507 }
508 } else {
509 return have_security && currState->secureLookup;
510 }
511 }
512
515 type() const
516 {
517 switch (bits(data, 1, 0)) {
518 case 0x1:
519 // In AArch64 blocks are not allowed at L0 for the
520 // 4 KiB granule and at L1 for 16/64 KiB granules
521 switch (grainSize) {
522 case Grain4KB:
523 if (lookupLevel == LookupLevel::L0 ||
524 lookupLevel == LookupLevel::L3)
525 return Invalid;
526 else
527 return Block;
528
529 case Grain16KB:
530 if (lookupLevel == LookupLevel::L2)
531 return Block;
532 else
533 return Invalid;
534
535 case Grain64KB:
536 // With Armv8.2-LPA (52bit PA) L1 Block descriptors
537 // are allowed for 64KiB granule
538 if ((lookupLevel == LookupLevel::L1 && physAddrRange == 52) ||
539 lookupLevel == LookupLevel::L2)
540 return Block;
541 else
542 return Invalid;
543
544 default:
545 return Invalid;
546 }
547 case 0x3:
548 return lookupLevel == LookupLevel::L3 ? Page : Table;
549 default:
550 return Invalid;
551 }
552 }
553
555 uint8_t
556 offsetBits() const override
557 {
558 if (type() == Block) {
559 switch (grainSize) {
560 case Grain4KB:
561 return lookupLevel == LookupLevel::L1 ?
562 30 /* 1 GiB */ : 21 /* 2 MiB */;
563 case Grain16KB:
564 return 25 /* 32 MiB */;
565 case Grain64KB:
566 return lookupLevel == LookupLevel::L1 ?
567 42 /* 4 TiB */ : 29 /* 512 MiB */;
568 default:
569 panic("Invalid AArch64 VM granule size\n");
570 }
571 } else if (type() == Page) {
572 switch (grainSize) {
573 case Grain4KB:
574 case Grain16KB:
575 case Grain64KB:
576 return grainSize; /* enum -> uint okay */
577 default:
578 panic("Invalid AArch64 VM granule size\n");
579 }
580 } else if (type() == Table) {
581 const auto* ptops = getPageTableOps(grainSize);
582 return ptops->walkBits(lookupLevel);
583 }
584 panic("AArch64 page table entry must be block or page\n");
585 }
586
588 Addr
589 pfn() const override
590 {
591 return paddr() >> offsetBits();
592 }
593
595 Addr
596 paddr() const
597 {
598 Addr addr = 0;
599 if (aarch64) {
600 addr = mbits(data, 47, offsetBits());
601 if (physAddrRange == 52 && grainSize == Grain64KB) {
602 addr |= bits(data, 15, 12) << 48;
603 }
604 } else {
605 addr = mbits(data, 39, offsetBits());
606 }
607 return addr;
608 }
609
611 Addr
613 {
614 assert(type() == Table);
615 Addr table_address = 0;
616 if (aarch64) {
617 table_address = mbits(data, 47, grainSize);
618 // Using 52bit if Armv8.2-LPA is implemented
619 if (physAddrRange == 52 && grainSize == Grain64KB)
620 table_address |= bits(data, 15, 12) << 48;
621 } else {
622 table_address = mbits(data, 39, 12);
623 }
624
625 return table_address;
626 }
627
629 Addr
631 {
632 assert(type() == Table);
633 Addr pa = 0;
634 if (aarch64) {
635 int stride = grainSize - 3;
636 int va_lo = stride * (3 - (lookupLevel + 1)) + grainSize;
637 int va_hi = va_lo + stride - 1;
638 pa = nextTableAddr() | (bits(va, va_hi, va_lo) << 3);
639 } else {
640 if (lookupLevel == LookupLevel::L1)
641 pa = nextTableAddr() | (bits(va, 29, 21) << 3);
642 else // lookupLevel == L2
643 pa = nextTableAddr() | (bits(va, 20, 12) << 3);
644 }
645 return pa;
646 }
647
649 bool
650 xn() const override
651 {
652 assert(type() == Block || type() == Page);
653 return bits(data, 54);
654 }
655
657 bool
658 pxn() const
659 {
660 assert(type() == Block || type() == Page);
661 return bits(data, 53);
662 }
663
665 bool
667 {
668 assert(type() == Block || type() == Page);
669 return bits(data, 52);
670 }
671
673 bool
674 global(WalkerState *currState) const override
675 {
676 assert(currState && (type() == Block || type() == Page));
677 const bool secure_state = currState->ss == SecurityState::Secure;
678 if (!currState->aarch64 && secure_state &&
679 !currState->secureLookup) {
680 return false; // ARM ARM issue C B3.6.3
681 } else if (currState->aarch64) {
682 if (!MMU::hasUnprivRegime(currState->regime)) {
683 // By default translations are treated as global
684 // in AArch64 for regimes without an unpriviledged
685 // component
686 return true;
687 } else if (secure_state && !currState->secureLookup) {
688 return false;
689 }
690 }
691 return !bits(data, 11);
692 }
693
695 bool
696 fnxs() const
697 {
698 assert((type() == Block || type() == Page));
699 return bits(data, 11);
700 }
701
703 bool
704 af() const
705 {
706 assert(type() == Block || type() == Page);
707 return bits(data, 10);
708 }
709
711 uint8_t
712 sh() const
713 {
714 assert(type() == Block || type() == Page);
715 return bits(data, 9, 8);
716 }
717
719 uint8_t
720 ap() const override
721 {
722 assert(type() == Block || type() == Page);
723 // Long descriptors only support the AP[2:1] scheme
724 return bits(data, 7, 6);
725 }
726
728 uint8_t
729 piindex() const
730 {
731 assert(type() == Block || type() == Page);
732 return (bits(data, 54) << 3) +
733 (bits(data, 53) << 2) +
734 (bits(data, 51) << 1) +
735 bits(data, 6);
736 }
737
739 bool
740 rw() const
741 {
742 assert(type() == Block || type() == Page);
743 return !bits(data, 7);
744 }
745
747 bool
748 user() const
749 {
750 assert(type() == Block || type() == Page);
751 return bits(data, 6);
752 }
753
757 static uint8_t
758 ap(bool rw, bool user)
759 {
760 return ((!rw) << 2) | (user << 1);
761 }
762
764 domain() const override
765 {
766 // Long-desc. format only supports Client domain
767 return DomainType::Client;
768 }
769
771 uint8_t
772 attrIndx() const
773 {
774 assert(type() == Block || type() == Page);
775 return bits(data, 4, 2);
776 }
777
779 uint8_t
780 memAttr() const
781 {
782 assert(type() == Block || type() == Page);
783 return bits(data, 5, 2);
784 }
785
788 void
790 {
791 data |= 1 << 10;
792 _dirty = true;
793 }
794
796 bool
797 dirty() const
798 {
799 return _dirty;
800 }
801
803 bool
805 {
806 assert(type() == Table);
807 return !bits(data, 63);
808 }
809
811 uint8_t
812 apTable() const
813 {
814 assert(type() == Table);
815 return bits(data, 62, 61);
816 }
817
819 uint8_t
820 rwTable() const
821 {
822 assert(type() == Table);
823 return !bits(data, 62);
824 }
825
828 uint8_t
829 userTable() const
830 {
831 assert(type() == Table);
832 return !bits(data, 61);
833 }
834
836 bool
837 xnTable() const
838 {
839 assert(type() == Table);
840 return bits(data, 60);
841 }
842
844 bool
845 pxnTable() const
846 {
847 assert(type() == Table);
848 return bits(data, 59);
849 }
850 };
851
853 {
854 public:
857
860
863
866
869
872
875
877 uint16_t asid;
879
882
885
888
891
893 SCTLR sctlr;
894
896 SCR scr;
897
899 CPSR cpsr;
900
902 union
903 {
904 TTBCR ttbcr; // AArch32 translations
905 TCR tcr; // AArch64 translations
906 };
907
909 HTCR htcr;
910
912 HCR hcr;
913
915 VTCR_t vtcr;
916
919
922
928 bool secureLookup = false;
929
934
937
941 {
942 bool rwTable = false;
943 bool userTable = false;
944 bool xnTable = false;
945 bool pxnTable = false;
946 };
947 std::optional<LongDescData> longDescData;
948
950 bool hpd;
951
952 uint8_t sh;
953 uint8_t irgn;
954 uint8_t orgn;
955
958
961
963 bool timing;
964
967
970
973
977
980
984
986
989
991 unsigned levels;
992
995
997
998 WalkerState();
999
1000 std::string name() const { return tableWalker->name(); }
1001 };
1002
1004 {
1005 public:
1007 Event *event = nullptr;
1008 };
1009
1011 {
1012 public:
1013 Port(TableWalker& _walker);
1014
1015 void sendFunctionalReq(const RequestPtr &req, uint8_t *data);
1016 void sendAtomicReq(const RequestPtr &req, uint8_t *data, Tick delay);
1017 void sendTimingReq(const RequestPtr &req, uint8_t *data, Tick delay,
1018 Event *event);
1019
1020 bool recvTimingResp(PacketPtr pkt) override;
1021
1022 private:
1023 void handleRespPacket(PacketPtr pkt, Tick delay=0);
1024 void handleResp(TableWalkerState *state, Addr addr,
1025 Addr size, Tick delay=0);
1026
1027 PacketPtr createPacket(const RequestPtr &req, uint8_t *data,
1028 Tick delay, Event *event);
1029
1030 private:
1032
1035
1038 };
1039
1043 {
1044 private:
1045 uint8_t *data;
1053
1054 public:
1056
1057 Stage2Walk(TableWalker &_parent, uint8_t *_data, Event *_event,
1059 MMU::ArmTranslationType tran_type);
1060
1061 void markDelayed() {}
1062
1063 void finish(const Fault &fault, const RequestPtr &req,
1065
1066 void
1068 int requestorId)
1069 {
1070 numBytes = size;
1071 req->setVirt(vaddr, size, flags, requestorId, 0);
1072 }
1073
1075 };
1076
1078 uint8_t *data, int num_bytes, Request::Flags flags,
1080 bool functional);
1081 void readDataTimed(ThreadContext *tc, Addr desc_addr,
1082 Stage2Walk *translation, int num_bytes,
1083 Request::Flags flags);
1084
1085 protected:
1086
1088 std::list<WalkerState *> stateQueues[LookupLevel::Num_ArmLookupLevel];
1089
1093
1096
1099
1102
1104 const bool isStage2;
1105
1108
1110 SCTLR sctlr;
1111
1113
1116
1120
1125
1144
1145 mutable unsigned pendingReqs;
1147
1148 static const unsigned REQUESTED = 0;
1149 static const unsigned COMPLETED = 1;
1150
1151 public:
1152 PARAMS(ArmTableWalker);
1153 TableWalker(const Params &p);
1154 virtual ~TableWalker();
1155
1156 bool haveLargeAsid64() const { return _haveLargeAsid64; }
1157 uint8_t physAddrRange() const { return _physAddrRange; }
1159 void completeDrain();
1160 DrainState drain() override;
1161 void drainResume() override;
1162
1163 gem5::Port &getPort(const std::string &if_name,
1164 PortID idx=InvalidPortID) override;
1165
1167
1168 Fault walk(const RequestPtr &req, ThreadContext *tc,
1169 uint16_t asid, vmid_t _vmid,
1171 bool timing, bool functional, SecurityState ss,
1172 PASpace ipaspace,
1173 MMU::ArmTranslationType tran_type, bool stage2,
1174 const TlbEntry *walk_entry);
1175
1176 void setMmu(MMU *_mmu);
1177 void setTlb(TLB *_tlb) { tlb = _tlb; }
1178 TLB* getTlb() { return tlb; }
1179 void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
1180 uint8_t texcb, bool s);
1182 LongDescriptor &lDescriptor);
1184 LongDescriptor &lDescriptor);
1186 bool uncacheableFromAttrs(uint8_t attrs);
1187
1188 static LookupLevel toLookupLevel(uint8_t lookup_level_as_int);
1189
1190 private:
1191
1192 void doL1Descriptor();
1193 void doL1DescriptorWrapper();
1195
1196 void doL2Descriptor();
1197 void doL2DescriptorWrapper();
1199
1200 void doLongDescriptor();
1201
1210
1211 void doLongDescriptorWrapper(LookupLevel curr_lookup_level);
1213
1214 void fetchDescriptor(Addr desc_addr,
1215 DescriptorBase &descriptor, int num_bytes,
1216 Request::Flags flags, LookupLevel lookup_lvl, Event *event,
1217 void (TableWalker::*doDescriptor)());
1218
1220
1221 void insertTableEntry(DescriptorBase &descriptor, bool longDescriptor);
1222 void insertPartialTableEntry(LongDescriptor &descriptor);
1223
1229 std::tuple<Addr, Addr, LookupLevel> walkAddresses(
1230 Addr ttbr, GrainSize tg, int tsz, int pa_range);
1231
1234
1235 Addr maxTxSz(GrainSize tg) const;
1236 Addr s1MinTxSz(GrainSize tg) const;
1237 bool s1TxSzFault(GrainSize tg, int tsz) const;
1238 bool checkVAOutOfRange(Addr addr, int top_bit,
1239 int tsz, bool low_range);
1240
1243 bool checkAddrSizeFaultAArch64(Addr addr, int pa_range);
1244
1246 bool uncacheableWalk() const;
1247
1249 void processWalkWrapper();
1251
1252 void nextWalk(ThreadContext *tc);
1253
1254 void pendingChange();
1255
1257 void stashCurrState(int queue_idx);
1258
1259 static uint8_t pageSizeNtoStatBin(uint8_t N);
1260
1261 void mpamTagTableWalk(RequestPtr &req) const;
1262
1263 public: /* Testing */
1265
1267
1268 Fault testWalk(const RequestPtr &walk_req, DomainType domain,
1269 LookupLevel lookup_level);
1270};
1271
1272} // namespace ArmISA
1273} // namespace gem5
1274
1275#endif //__ARCH_ARM_TABLE_WALKER_HH__
const char data[]
FaultSource
Generic fault source enums used to index into {short/long/aarch64}DescFaultSources[] to get the actua...
Definition faults.hh:96
static bool hasUnprivRegime(TranslationRegime regime)
Definition mmu.cc:990
virtual bool global(WalkerState *currState) const =0
virtual uint64_t getRawData() const =0
virtual DomainType domain() const =0
virtual std::string dbgHeader() const =0
virtual uint8_t offsetBits() const =0
LookupLevel lookupLevel
Current lookup level for this descriptor.
virtual bool secure(bool have_security, WalkerState *currState) const =0
uint64_t getRawData() const override
EntryType
Type of page table entry ARM DDI 0406B: B3-8.
void setAp0()
Set access flag that this entry has been touched.
bool dirty() const
This entry needs to be written back to memory.
Addr paddr(Addr va) const
Return the physcal address of the entry, bits in position.
uint32_t data
The raw bits of the entry.
bool supersection() const
Is the page a Supersection (16 MiB)?
bool secure(bool have_security, WalkerState *currState) const override
Returns true if this entry targets the secure physical address map.
bool xn() const override
Is the translation not allow execution?
Addr l2Addr() const
Address of L2 descriptor if it exists.
bool global(WalkerState *currState) const override
Is the translation global (no asid used)?
DomainType domain() const override
Domain Client/Manager: ARM DDI 0406B: B3-31.
Addr pfn() const override
Return the physical frame, bits shifted right.
bool shareable() const override
If the section is shareable.
uint8_t texcb() const override
Memory region attributes: ARM DDI 0406B: B3-32.
uint8_t ap() const override
Three bit access protection flags.
bool _dirty
This entry has been modified (access flag set) and needs to be written back to memory.
Addr paddr() const
Return the physcal address of the entry, bits in position.
std::string dbgHeader() const override
Level 2 page table descriptor.
bool xn() const override
Is execution allowed on this mapping?
uint64_t getRawData() const override
uint8_t ap() const override
Three bit access protection flags.
bool global(WalkerState *currState) const override
Is the translation global (no asid used)?
void setAp0()
Set access flag that this entry has been touched.
Addr pfn() const override
Return the physical frame, bits shifted right.
bool secure(bool have_security, WalkerState *currState) const override
std::string dbgHeader() const override
bool _dirty
This entry has been modified (access flag set) and needs to be written back to memory.
uint32_t data
The raw bits of the entry.
bool shareable() const override
If the section is shareable.
bool invalid() const
Is the entry invalid.
bool large() const
What is the size of the mapping?
uint8_t texcb() const override
Memory region attributes: ARM DDI 0406B: B3-32.
Addr paddr(Addr va) const
Return complete physical address given a VA.
DomainType domain() const override
bool dirty() const
This entry needs to be written back to memory.
Long-descriptor format (LPAE)
uint8_t sh() const
2-bit shareability field
uint8_t memAttr() const
Memory attributes, only used by stage 2 translations.
uint8_t rwTable() const
R/W protection flag for subsequent levels of lookup.
void setAf()
Set access flag that this entry has been touched.
uint8_t offsetBits() const override
Return the bit width of the page/block offset.
bool contiguousHint() const
Contiguous hint bit.
bool pxn() const
Is privileged execution allowed on this mapping?
bool af() const
Returns true if the access flag (AF) is set.
bool pxnTable() const
Is privileged execution allowed on subsequent lookup levels?
bool aarch64
True if the current lookup is performed in AArch64 state.
EntryType type() const
Return the descriptor type.
bool xn() const override
Is execution allowed on this mapping?
uint8_t piindex() const
Stage 1 Indirect permissions.
bool secure(bool have_security, WalkerState *currState) const override
Returns true if this entry targets the secure physical address map.
std::string dbgHeader() const override
bool rw() const
Read/write access protection flag.
Addr nextTableAddr() const
Return the address of the next page table.
bool global(WalkerState *currState) const override
Is the translation global (no asid used)?
GrainSize grainSize
Width of the granule size in bits.
uint8_t attrIndx() const
Attribute index.
uint8_t ap() const override
2-bit access protection flags
uint64_t data
The raw bits of the entry.
bool _dirty
This entry has been modified (access flag set) and needs to be written back to memory.
Addr pfn() const override
Return the physical frame, bits shifted right.
Addr nextDescAddr(Addr va) const
Return the address of the next descriptor.
uint8_t apTable() const
Two bit access protection flags for subsequent levels of lookup.
Addr paddr() const
Return the physical address of the entry.
bool user() const
User/privileged level access protection flag.
bool fnxs() const
FNXS for FEAT_XS only.
uint8_t userTable() const
User/privileged mode protection flag for subsequent levels of lookup.
bool secureTable() const
Whether the subsequent levels of lookup are secure.
static uint8_t ap(bool rw, bool user)
Return the AP bits as compatible with the AP[2:0] format.
bool xnTable() const
Is execution allowed on subsequent lookup levels?
bool dirty() const
This entry needs to be written back to memory.
SnoopRespPacketQueue snoopRespQueue
Packet queue used to store outgoing snoop responses.
ReqPacketQueue reqQueue
Packet queue used to store outgoing requests.
void sendAtomicReq(const RequestPtr &req, uint8_t *data, Tick delay)
void handleResp(TableWalkerState *state, Addr addr, Addr size, Tick delay=0)
void sendFunctionalReq(const RequestPtr &req, uint8_t *data)
void handleRespPacket(PacketPtr pkt, Tick delay=0)
void sendTimingReq(const RequestPtr &req, uint8_t *data, Tick delay, Event *event)
PacketPtr createPacket(const RequestPtr &req, uint8_t *data, Tick delay, Event *event)
bool recvTimingResp(PacketPtr pkt) override
Receive a timing response from the peer.
void markDelayed()
Signal that the translation has been delayed due to a hw page table walk.
void finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode)
void setVirt(Addr vaddr, int size, Request::Flags flags, int requestorId)
Stage2Walk(TableWalker &_parent, uint8_t *_data, Event *_event, Addr vaddr, BaseMMU::Mode mode, MMU::ArmTranslationType tran_type)
void translateTiming(ThreadContext *tc)
bool isWrite
If the access is a write.
CPSR cpsr
Cached copy of the cpsr as it existed when translation began.
Addr vaddr_tainted
The virtual address that is being translated.
RequestPtr req
Request that is currently being serviced.
VTCR_t vtcr
Cached copy of the vtcr as it existed when translation began.
HCR hcr
Cached copy of the htcr as it existed when translation began.
Addr vaddr
The virtual address that is being translated with tagging removed.
bool functional
If the atomic mode should be functional.
bool secureLookup
Whether lookups should be treated as using the secure state.
bool isUncacheable
True if table walks are uncacheable (for table descriptors)
ThreadContext * tc
Thread context that we're doing the walk for.
bool hpd
Hierarchical access permission disable.
BaseMMU::Translation * transState
Translation state for delayed requests.
SecurityState ss
Security State of the access.
std::optional< LongDescData > longDescData
unsigned levels
Page entries walked during service (for stats)
BaseMMU::Mode mode
Save mode for use in delayed response.
HTCR htcr
Cached copy of the htcr as it existed when translation began.
SCR scr
Cached copy of the scr as it existed when translation began.
ExceptionLevel el
Current exception level.
MMU::ArmTranslationType tranType
The translation type that has been requested.
SCTLR sctlr
Cached copy of the sctlr as it existed when translation began.
Fault fault
The fault that we are going to return.
Tick startTime
Timestamp for calculating elapsed time in service (for stats)
bool isFetch
If the access is a fetch (for execution, and no-exec) must be checked?
bool stage2Req
Flag indicating if a second stage of lookup is required.
TlbEntry walkEntry
Initial walk entry allowing to skip lookup levels.
TranslationRegime regime
Current translation regime.
bool timing
If the mode is timing or atomic.
LongDescriptor longDesc
Long-format descriptor (LPAE and AArch64)
int physAddrRange
Current physical address range in bits.
PASpace ipaSpace
IPA space (Secure vs NonSecure); stage2 only.
bool delayed
Whether the response is delayed in timing mode due to additional lookups.
uint16_t asid
ASID that we're servicing the request under.
L1Descriptor l1Desc
Short-format descriptors.
bool aarch64
If the access is performed in AArch64 state.
BaseMMU::Translation * stage2Tran
A pointer to the stage 2 translation that's in progress.
static LookupLevel toLookupLevel(uint8_t lookup_level_as_int)
enums::ArmLookupLevel LookupLevel
void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, uint8_t texcb, bool s)
EventFunctionWrapper doL0LongDescEvent
const ArmRelease * release
Cached copies of system-level properties.
bool checkVAOutOfRange(Addr addr, int top_bit, int tsz, bool low_range)
Fault generateLongDescFault(ArmFault::FaultSource src)
EventFunctionWrapper doL1DescEvent
EventFunctionWrapper doProcessEvent
static const unsigned REQUESTED
static const unsigned COMPLETED
bool uncacheableWalk() const
Returns true if the table walk should be uncacheable.
void memAttrsAArch64(ThreadContext *tc, TlbEntry &te, LongDescriptor &lDescriptor)
void insertPartialTableEntry(LongDescriptor &descriptor)
void fetchDescriptor(Addr desc_addr, DescriptorBase &descriptor, int num_bytes, Request::Flags flags, LookupLevel lookup_lvl, Event *event, void(TableWalker::*doDescriptor)())
void drainResume() override
Resume execution after a successful drain.
void doLongDescriptorWrapper(LookupLevel curr_lookup_level)
bool pending
If a timing translation is currently in progress.
Port * port
Port shared by the two table walkers.
Fault testWalk(const RequestPtr &walk_req, DomainType domain, LookupLevel lookup_level)
PARAMS(ArmTableWalker)
Addr s1MinTxSz(GrainSize tg) const
std::tuple< Addr, Addr, LookupLevel > walkAddresses(Addr ttbr, GrainSize tg, int tsz, int pa_range)
Returns a tuple made of: 1) The address of the first page table 2) The address of the first descripto...
Fault readDataUntimed(ThreadContext *tc, Addr vaddr, Addr desc_addr, uint8_t *data, int num_bytes, Request::Flags flags, BaseMMU::Mode mode, MMU::ArmTranslationType tran_type, bool functional)
TableWalker(const Params &p)
void nextWalk(ThreadContext *tc)
TlbTestInterface * test
void readDataTimed(ThreadContext *tc, Addr desc_addr, Stage2Walk *translation, int num_bytes, Request::Flags flags)
EventFunctionWrapper doL2DescEvent
gem5::Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
std::list< WalkerState * > pendingQueue
Queue of requests that have passed are waiting because the walker is currently busy.
bool s1TxSzFault(GrainSize tg, int tsz) const
MMU * mmu
The MMU to forward second stage look upts to.
RequestorID requestorId
Requestor id assigned by the MMU.
gem5::ArmISA::TableWalker::TableWalkerStats stats
Fault walk(const RequestPtr &req, ThreadContext *tc, uint16_t asid, vmid_t _vmid, BaseMMU::Mode mode, BaseMMU::Translation *_trans, bool timing, bool functional, SecurityState ss, PASpace ipaspace, MMU::ArmTranslationType tran_type, bool stage2, const TlbEntry *walk_entry)
const bool isStage2
Indicates whether this table walker is part of the stage 2 mmu.
EventFunctionWrapper doL1LongDescEvent
bool uncacheableFromAttrs(uint8_t attrs)
bool checkAddrSizeFaultAArch64(Addr addr, int pa_range)
Returns true if the address exceeds the range permitted by the system-wide setting or by the TCR_ELx ...
void mpamTagTableWalk(RequestPtr &req) const
static uint8_t pageSizeNtoStatBin(uint8_t N)
void completeDrain()
Checks if all state is cleared and if so, completes drain.
void insertTableEntry(DescriptorBase &descriptor, bool longDescriptor)
DrainState drain() override
Provide a default implementation of the drain interface for objects that don't need draining.
std::list< WalkerState * > stateQueues[LookupLevel::Num_ArmLookupLevel]
Queues of requests for all the different lookup levels.
unsigned numSquashable
The number of walks belonging to squashed instructions that can be removed from the pendingQueue per ...
TLB * tlb
TLB that is initiating these table walks.
void memAttrsLPAE(ThreadContext *tc, TlbEntry &te, LongDescriptor &lDescriptor)
void setTestInterface(TlbTestInterface *ti)
EventFunctionWrapper doL2LongDescEvent
uint8_t physAddrRange() const
void memAttrsWalkAArch64(TlbEntry &te)
Addr maxTxSz(GrainSize tg) const
SCTLR sctlr
Cached copy of the sctlr as it existed when translation began.
EventFunctionWrapper doL3LongDescEvent
void stashCurrState(int queue_idx)
Timing mode: saves the currState into the stateQueues.
ClockedObject(const ClockedObjectParams &p)
ClockedObjectParams Params
Parameters of ClockedObject.
Ports are used to interface objects to each other.
Definition port.hh:62
QueuedRequestPort(const std::string &name, ReqPacketQueue &req_queue, SnoopRespPacketQueue &snoop_resp_queue, PortID id=InvalidPortID)
Create a QueuedPort with a given name, and a supplied implementation of two packet queues.
Definition qport.hh:134
gem5::Flags< FlagsType > Flags
Definition request.hh:102
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Statistics container.
Definition group.hh:93
A simple histogram stat.
This is a simple scalar statistic, like a counter.
A 2-Dimensional vecto of scalar stats.
A vector of scalar stats.
STL list class.
Definition stl.hh:51
ClockedObject declaration and implementation.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
constexpr T mbits(T val, unsigned first, unsigned last)
Mask off the given bits in place like bits() but without shifting.
Definition bitfield.hh:106
DrainState
Object drain/handover states.
Definition drain.hh:76
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
Bitfield< 30 > te
const PageTableOps * getPageTableOps(GrainSize trans_granule)
Definition pagetable.cc:477
Bitfield< 4, 0 > mode
Definition misc_types.hh:74
Bitfield< 21, 20 > stride
Bitfield< 4 > s
Bitfield< 7, 4 > domain
SecurityState
Security State.
Definition types.hh:273
uint16_t vmid_t
Definition types.hh:57
PASpace
Physical Address Space.
Definition types.hh:280
Bitfield< 21 > ss
Definition misc_types.hh:60
Bitfield< 39, 12 > pa
Bitfield< 8 > va
Bitfield< 10, 5 > event
Bitfield< 0 > p
Bitfield< 30 > ti
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
std::shared_ptr< FaultBase > Fault
Definition types.hh:249
std::shared_ptr< Request > RequestPtr
Definition request.hh:94
const PortID InvalidPortID
Definition types.hh:246
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition types.hh:245
uint64_t Tick
Tick count type.
Definition types.hh:58
uint16_t RequestorID
Definition request.hh:95
Packet * PacketPtr
Declaration of a simple PacketQueue that is associated with a port on which it attempts to send packe...
Declaration of the queued port.
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
TableWalkerStats(statistics::Group *parent)
Helper variables used to implement hierarchical access permissions when the long-desc.
A virtual base opaque structure used to hold state associated with the packet (e.g....
Definition packet.hh:469

Generated on Mon Oct 27 2025 04:12:55 for gem5 by doxygen 1.14.0