TianoCore EDK2 master
Loading...
Searching...
No Matches
TestHelper.c
Go to the documentation of this file.
1
10#include "../CpuPageTable.h"
11
12#define IA32_PAE_RESERVED_MASK 0x7FF0000000000000ull
13//
14// Global Data to validate if the page table is legal
15// mValidMaskNoLeaf[0] is not used
16// mValidMaskNoLeaf[1] ... mValidMaskNoLeaf [5] represent PTE ... PML5E
17// mValidMaskNoLeaf[Index] means if it is a valid no leaf entry, entry should equal to (entry & mValidMaskNoLeaf[Index])
18// mValidMaskLeaf[Index] means if it is a valid leaf entry, entry should equal to (entry & mValidMaskLeaf[Index])
19// mValidMaskLeafFlag[Index] means if it is a leaf entry, if and only if ((entry & mValidMaskLeafFlag[Index]) == mValidMaskLeafFlag[Index])
20//
21IA32_PAGING_ENTRY mValidMaskNoLeaf[6];
22IA32_PAGING_ENTRY mValidMaskLeaf[6];
23IA32_PAGING_ENTRY mValidMaskLeafFlag[6];
24
30VOID
32 UINTN MemorySpace
33 )
34{
35 UINTN Index;
36
37 ASSERT (MemorySpace <= 52);
38 mValidMaskNoLeaf[0].Uint64 = 0;
39 mValidMaskLeaf[0].Uint64 = 0;
40 mValidMaskLeafFlag[0].Uint64 = 0;
41
42 //
43 // Set common part for all kinds of entrys.
44 //
45 for (Index = 1; Index < 6; Index++) {
46 mValidMaskNoLeaf[Index].Uint64 = MAX_UINT64;
47 mValidMaskLeaf[Index].Uint64 = MAX_UINT64;
48
49 //
50 // bit 51:M is reserved, and should be zero
51 //
52 if (MemorySpace - 1 < 51) {
53 mValidMaskNoLeaf[Index].Uint64 = BitFieldWrite64 (mValidMaskNoLeaf[Index].Uint64, MemorySpace - 1, 51, 0);
54 mValidMaskLeaf[Index].Uint64 = BitFieldWrite64 (mValidMaskLeaf[Index].Uint64, MemorySpace - 1, 51, 0);
55 }
56 }
57
58 //
59 // Handle mask for no leaf entry.
60 //
61 mValidMaskNoLeaf[1].Uint64 = 0; // PTE can't map to page structure.
62 mValidMaskNoLeaf[2].Pnle.Bits.MustBeZero = 0; // for PML4E, bit 7 must be zero.
63 mValidMaskNoLeaf[3].Pnle.Bits.MustBeZero = 0; // for PML5E, bit 7 must be zero.
64 mValidMaskNoLeaf[4].Pml4.Bits.MustBeZero = 0; // for PML4E, bit 7 must be zero.
65 mValidMaskNoLeaf[5].Pml4.Bits.MustBeZero = 0; // for PML5E, bit 7 must be zero.
66
67 //
68 // Handle mask for leaf entry.
69 // No need to modification for PTE, since it doesn't have extra reserved bit
70 //
71 mValidMaskLeaf[2].Uint64 = BitFieldWrite64 (mValidMaskLeaf[2].Uint64, 13, 20, 0); // bit 13-20 is reserved for PDE
72 mValidMaskLeaf[3].Uint64 = BitFieldWrite64 (mValidMaskLeaf[2].Uint64, 13, 29, 0); // bit 13-29 is reserved for PDPTE
73 mValidMaskLeaf[4].Uint64 = 0; // for PML4E, no possible to map to page.
74 mValidMaskLeaf[5].Uint64 = 0; // for PML5E, no possible to map to page.
75
76 //
77 // Handle Flags to indicate it is a leaf entry.
78 // for PML4E and PML5E, no possible to map to page, so the flag should be MAX_UINT64.
79 //
80 mValidMaskLeafFlag[1].Pce.Present = 1; // For PTE, as long as it is present, it maps to page
81 //
82 // For PDE and PDPTE, the bit 7 should be set to map to pages
83 //
84 mValidMaskLeafFlag[2].Pde2M.Bits.MustBeOne = 1;
85 mValidMaskLeafFlag[2].Pde2M.Bits.Present = 1;
86 mValidMaskLeafFlag[3].Pde2M.Bits.MustBeOne = 1;
87 mValidMaskLeafFlag[3].Pde2M.Bits.Present = 1;
88 mValidMaskLeafFlag[4].Uint64 = MAX_UINT64;
89 mValidMaskLeafFlag[5].Uint64 = MAX_UINT64;
90}
91
105 IN IA32_PAGING_ENTRY *PagingEntry,
106 IN UINTN Level,
107 IN UINTN MaxLeafLevel,
108 IN UINT64 Address,
109 IN PAGING_MODE PagingMode
110 )
111{
112 UINT64 Index;
113 IA32_PAGING_ENTRY *ChildPageEntry;
114 UNIT_TEST_STATUS Status;
115
116 if (PagingMode == PagingPae) {
117 UT_ASSERT_EQUAL (PagingEntry->Uint64 & IA32_PAE_RESERVED_MASK, 0);
118 }
119
120 if (PagingEntry->Pce.Present == 0) {
121 return UNIT_TEST_PASSED;
122 }
123
124 if ((PagingEntry->Uint64 & mValidMaskLeafFlag[Level].Uint64) == mValidMaskLeafFlag[Level].Uint64) {
125 //
126 // It is a Leaf
127 //
128 if (Level > MaxLeafLevel) {
129 DEBUG ((DEBUG_ERROR, "ERROR: Level %d entry 0x%lx is a leaf entry, but max leaf level is %d \n", Level, PagingEntry->Uint64, MaxLeafLevel));
130 UT_ASSERT_TRUE (Level <= MaxLeafLevel);
131 }
132
133 if ((PagingEntry->Uint64 & mValidMaskLeaf[Level].Uint64) != PagingEntry->Uint64) {
134 DEBUG ((DEBUG_ERROR, "ERROR: Level %d Leaf entry is 0x%lx, which reserved bit is set \n", Level, PagingEntry->Uint64));
135 UT_ASSERT_EQUAL ((PagingEntry->Uint64 & mValidMaskLeaf[Level].Uint64), PagingEntry->Uint64);
136 }
137
138 return UNIT_TEST_PASSED;
139 }
140
141 //
142 // Not a leaf
143 //
144 UT_ASSERT_NOT_EQUAL (Level, 1);
145 if ((PagingEntry->Uint64 & mValidMaskNoLeaf[Level].Uint64) != PagingEntry->Uint64) {
146 DEBUG ((DEBUG_ERROR, "ERROR: Level %d no Leaf entry is 0x%lx, which reserved bit is set \n", Level, PagingEntry->Uint64));
147 UT_ASSERT_EQUAL ((PagingEntry->Uint64 & mValidMaskNoLeaf[Level].Uint64), PagingEntry->Uint64);
148 }
149
150 ChildPageEntry = (IA32_PAGING_ENTRY *)(UINTN)(IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&PagingEntry->Pnle));
151 for (Index = 0; Index < 512; Index++) {
152 Status = IsPageTableEntryValid (&ChildPageEntry[Index], Level-1, MaxLeafLevel, Address + (Index<<(9*(Level-1) + 3)), PagingMode);
153 if (Status != UNIT_TEST_PASSED) {
154 return Status;
155 }
156 }
157
158 return UNIT_TEST_PASSED;
159}
160
171 IN UINTN PageTable,
172 IN PAGING_MODE PagingMode
173 )
174{
175 UINTN MaxLevel;
176 UINTN MaxLeafLevel;
177 UINT64 Index;
178 UNIT_TEST_STATUS Status;
179 IA32_PAGING_ENTRY *PagingEntry;
180
181 if (PageTable == 0) {
182 return UNIT_TEST_PASSED;
183 }
184
185 if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) {
186 //
187 // 32bit paging is never supported.
188 //
189 return UNIT_TEST_ERROR_TEST_FAILED;
190 }
191
192 MaxLeafLevel = (UINT8)PagingMode;
193 MaxLevel = (UINT8)(PagingMode >> 8);
194
195 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTable;
196 for (Index = 0; Index < ((PagingMode == PagingPae) ? 4 : 512); Index++) {
197 if (PagingMode == PagingPae) {
198 UT_ASSERT_EQUAL (PagingEntry[Index].PdptePae.Bits.MustBeZero, 0);
199 UT_ASSERT_EQUAL (PagingEntry[Index].PdptePae.Bits.MustBeZero2, 0);
200 UT_ASSERT_EQUAL (PagingEntry[Index].PdptePae.Bits.MustBeZero3, 0);
201 }
202
203 Status = IsPageTableEntryValid (&PagingEntry[Index], MaxLevel, MaxLeafLevel, Index << (9 * MaxLevel + 3), PagingMode);
204 if (Status != UNIT_TEST_PASSED) {
205 return Status;
206 }
207 }
208
209 return Status;
210}
211
223UINT64
225 IN IA32_PAGING_ENTRY *PagingEntry,
226 IN OUT UINTN *Level,
227 IN UINTN MaxLeafLevel,
228 IN UINT64 Address
229 )
230{
231 UINT64 Index;
232 IA32_PAGING_ENTRY *ChildPageEntry;
233
234 if (PagingEntry->Pce.Present == 0) {
235 return 0;
236 }
237
238 if ((PagingEntry->Uint64 & mValidMaskLeafFlag[*Level].Uint64) == mValidMaskLeafFlag[*Level].Uint64) {
239 //
240 // It is a Leaf
241 //
242 return PagingEntry->Uint64;
243 }
244
245 //
246 // Not a leaf
247 //
248 ChildPageEntry = (IA32_PAGING_ENTRY *)(UINTN)(IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&PagingEntry->Pnle));
249 *Level = *Level -1;
250 Index = Address >> (*Level * 9 + 3);
251 ASSERT (Index == (Index & ((1<< 9) - 1)));
252
253 return GetEntryFromSubPageTable (&ChildPageEntry[Index], Level, MaxLeafLevel, Address - (Index << (9 * *Level + 3)));
254}
255
266UINT64
268 IN UINTN PageTable,
269 IN PAGING_MODE PagingMode,
270 IN UINT64 Address,
271 OUT UINTN *Level
272 )
273{
274 UINTN MaxLevel;
275 UINTN MaxLeafLevel;
276 UINT64 Index;
277 IA32_PAGING_ENTRY *PagingEntry;
278
279 if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) {
280 //
281 // 32bit paging is never supported.
282 // PAE paging will be supported later.
283 //
284 return 0;
285 }
286
287 MaxLeafLevel = (UINT8)PagingMode;
288 MaxLevel = (UINT8)(PagingMode >> 8);
289
290 Index = Address >> (MaxLevel * 9 + 3);
291 ASSERT (Index == (Index & ((1<< 9) - 1)));
292 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTable;
293 *Level = MaxLevel;
294
295 return GetEntryFromSubPageTable (&PagingEntry[Index], Level, MaxLeafLevel, Address - (Index << (9 * MaxLevel + 3)));
296}
297
305UINT64
307 IN PAGING_MODE Mode
308 )
309{
310 switch (Mode) {
311 case Paging32bit:
312 case PagingPae:
313 return SIZE_4GB;
314
315 case Paging4Level:
316 case Paging4Level1GB:
317 case Paging5Level:
318 case Paging5Level1GB:
319 return 1ull << MIN (12 + (Mode >> 8) * 9, 52);
320
321 default:
322 ASSERT (0);
323 return 0;
324 }
325}
UINT64 UINTN
UINT64 EFIAPI BitFieldWrite64(IN UINT64 Operand, IN UINTN StartBit, IN UINTN EndBit, IN UINT64 Value)
Definition: BitField.c:755
#define MIN(a, b)
Definition: Base.h:1007
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
UINT64 GetEntryFromPageTable(IN UINTN PageTable, IN PAGING_MODE PagingMode, IN UINT64 Address, OUT UINTN *Level)
Definition: TestHelper.c:267
UNIT_TEST_STATUS IsPageTableValid(IN UINTN PageTable, IN PAGING_MODE PagingMode)
Definition: TestHelper.c:170
UINT64 GetEntryFromSubPageTable(IN IA32_PAGING_ENTRY *PagingEntry, IN OUT UINTN *Level, IN UINTN MaxLeafLevel, IN UINT64 Address)
Definition: TestHelper.c:224
VOID InitGlobalData(UINTN MemorySpace)
Definition: TestHelper.c:31
UNIT_TEST_STATUS IsPageTableEntryValid(IN IA32_PAGING_ENTRY *PagingEntry, IN UINTN Level, IN UINTN MaxLeafLevel, IN UINT64 Address, IN PAGING_MODE PagingMode)
Definition: TestHelper.c:104
UINT64 GetMaxAddress(IN PAGING_MODE Mode)
Definition: TestHelper.c:306
#define UT_ASSERT_NOT_EQUAL(ValueA, ValueB)
Definition: UnitTestLib.h:402
#define UT_ASSERT_TRUE(Expression)
Definition: UnitTestLib.h:350
#define UT_ASSERT_EQUAL(ValueA, ValueB)
Definition: UnitTestLib.h:375
UINT32 UNIT_TEST_STATUS
Definition: UnitTestLib.h:16