TianoCore EDK2 master
Loading...
Searching...
No Matches
CpuPageTableLibUnitTestHost.c
Go to the documentation of this file.
1
10
11// ----------------------------------------------------------------------- PageMode--TestCount-TestRangeCount---RandomOptions
12// static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPaging4Level = { Paging4Level, 30, 20, USE_RANDOM_ARRAY };
13// static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPaging4Level1GB = { Paging4Level1GB, 30, 20, USE_RANDOM_ARRAY };
14// static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPaging5Level = { Paging5Level, 30, 20, USE_RANDOM_ARRAY };
15// static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPaging5Level1GB = { Paging5Level1GB, 30, 20, USE_RANDOM_ARRAY };
16// static CPU_PAGE_TABLE_LIB_RANDOM_TEST_CONTEXT mTestContextPagingPae = { PagingPae, 30, 20, USE_RANDOM_ARRAY };
17
34EFIAPI
36 IN UNIT_TEST_CONTEXT Context
37 )
38{
39 UINTN PageTable;
40 PAGING_MODE PagingMode;
41 UINTN Buffer;
42 UINTN PageTableBufferSize;
43 IA32_MAP_ATTRIBUTE MapAttribute;
44 IA32_MAP_ATTRIBUTE MapMask;
45
46 MapAttribute.Uint64 = 0;
47 MapMask.Uint64 = 0;
48 PagingMode = Paging5Level1GB;
49 PageTableBufferSize = 0;
50 PageTable = 0;
51
52 //
53 // If the input linear address is not 4K align, it should return invalid parameter
54 //
55 UT_ASSERT_EQUAL (PageTableMap (&PageTable, PagingMode, &Buffer, &PageTableBufferSize, 1, SIZE_4KB, &MapAttribute, &MapMask, NULL), RETURN_INVALID_PARAMETER);
56
57 //
58 // If the input PageTableBufferSize is not 4K align, it should return invalid parameter
59 //
60 PageTableBufferSize = 10;
61 UT_ASSERT_EQUAL (PageTableMap (&PageTable, PagingMode, &Buffer, &PageTableBufferSize, 0, SIZE_4KB, &MapAttribute, &MapMask, NULL), RETURN_INVALID_PARAMETER);
62
63 //
64 // If the input PagingMode is Paging32bit, it should return invalid parameter
65 //
66 PageTableBufferSize = 0;
67 PagingMode = Paging32bit;
68 UT_ASSERT_EQUAL (PageTableMap (&PageTable, PagingMode, &Buffer, &PageTableBufferSize, 1, SIZE_4KB, &MapAttribute, &MapMask, NULL), RETURN_UNSUPPORTED);
69
70 //
71 // If the input MapMask is NULL, it should return invalid parameter
72 //
73 PagingMode = Paging5Level1GB;
74 UT_ASSERT_EQUAL (PageTableMap (&PageTable, PagingMode, &Buffer, &PageTableBufferSize, 1, SIZE_4KB, &MapAttribute, NULL, NULL), RETURN_INVALID_PARAMETER);
75
76 return UNIT_TEST_PASSED;
77}
78
95EFIAPI
97 IN UNIT_TEST_CONTEXT Context
98 )
99{
100 UINTN PageTable;
101 PAGING_MODE PagingMode;
102 VOID *Buffer;
103 UINTN PageTableBufferSize;
104 IA32_MAP_ATTRIBUTE MapAttribute;
105 IA32_MAP_ATTRIBUTE MapMask;
106 RETURN_STATUS Status;
107 UNIT_TEST_STATUS TestStatus;
108
109 MapAttribute.Uint64 = 0;
110 MapMask.Uint64 = 0;
111 PagingMode = Paging4Level1GB;
112 PageTableBufferSize = 0;
113 PageTable = 0;
114 Buffer = NULL;
115 MapAttribute.Bits.Present = 1;
116 MapAttribute.Bits.Nx = 1;
117 MapMask.Bits.Present = 1;
118 MapMask.Uint64 = MAX_UINT64;
119
120 //
121 // Create page table to cover [0, 10M], it should have 5 PTE
122 //
123 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, (UINT64)SIZE_2MB * 5, &MapAttribute, &MapMask, NULL);
125 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize));
126 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, (UINT64)SIZE_2MB * 5, &MapAttribute, &MapMask, NULL);
128 TestStatus = IsPageTableValid (PageTable, PagingMode);
129 if (TestStatus != UNIT_TEST_PASSED) {
130 return TestStatus;
131 }
132
133 //
134 // call library to cover [0, 4K], because the page table is already cover [0, 10M], and no attribute change,
135 // We assume the fucntion doesn't need to change page table, return success and output BufferSize is 0
136 //
137 Buffer = NULL;
138 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, (UINT64)SIZE_4KB, &MapAttribute, &MapMask, NULL);
139 UT_ASSERT_EQUAL (PageTableBufferSize, 0);
141 TestStatus = IsPageTableValid (PageTable, PagingMode);
142 if (TestStatus != UNIT_TEST_PASSED) {
143 return TestStatus;
144 }
145
146 //
147 // Same range and same attribute, only clear one mask attribute bit
148 // We assume the fucntion doesn't need to change page table, return success and output BufferSize is 0
149 //
150 MapMask.Bits.Nx = 0;
151 PageTableBufferSize = 0;
152 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, 0, (UINT64)SIZE_4KB, &MapAttribute, &MapMask, NULL);
154 UT_ASSERT_EQUAL (PageTableBufferSize, 0);
155 TestStatus = IsPageTableValid (PageTable, PagingMode);
156 if (TestStatus != UNIT_TEST_PASSED) {
157 return TestStatus;
158 }
159
160 //
161 // call library to cover [2M, 4M], while the page table is already cover [0, 10M],
162 // only change one attribute bit, we assume the page table change be modified even if the
163 // input Buffer is NULL, and BufferSize is 0
164 //
165 MapAttribute.Bits.Accessed = 1;
166 MapMask.Bits.Accessed = 1;
167 PageTableBufferSize = 0;
168 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, (UINT64)SIZE_2MB, (UINT64)SIZE_2MB, &MapAttribute, &MapMask, NULL);
170 UT_ASSERT_EQUAL (PageTableBufferSize, 0);
171 TestStatus = IsPageTableValid (PageTable, PagingMode);
172 if (TestStatus != UNIT_TEST_PASSED) {
173 return TestStatus;
174 }
175
176 return UNIT_TEST_PASSED;
177}
178
195EFIAPI
197 IN UNIT_TEST_CONTEXT Context
198 )
199{
200 UINTN PageTable;
201 PAGING_MODE PagingMode;
202 VOID *Buffer;
203 UINTN PageTableBufferSize;
204 IA32_MAP_ATTRIBUTE MapAttribute;
205 IA32_MAP_ATTRIBUTE MapMask;
206 RETURN_STATUS Status;
207 UNIT_TEST_STATUS TestStatus;
208
209 //
210 // Create Page table to map [0,1G] to [8K, 1G+8K]
211 //
212 PagingMode = Paging4Level1GB;
213 PageTableBufferSize = 0;
214 PageTable = 0;
215 Buffer = NULL;
216 MapAttribute.Uint64 = (UINT64)SIZE_4KB * 2;
217 MapMask.Uint64 = (UINT64)SIZE_4KB * 2;
218 MapAttribute.Bits.Present = 1;
219 MapMask.Bits.Present = 1;
220 MapMask.Uint64 = MAX_UINT64;
221 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB, &MapAttribute, &MapMask, NULL);
223 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize));
224 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB, &MapAttribute, &MapMask, NULL);
226
227 //
228 // Page table should be valid. (All reserved bits are zero)
229 //
230 TestStatus = IsPageTableValid (PageTable, PagingMode);
231 if (TestStatus != UNIT_TEST_PASSED) {
232 return TestStatus;
233 }
234
235 return UNIT_TEST_PASSED;
236}
237
254EFIAPI
256 IN UNIT_TEST_CONTEXT Context
257 )
258{
259 UINTN PageTable;
260 PAGING_MODE PagingMode;
261 VOID *Buffer;
262 UINTN PageTableBufferSize;
263 IA32_MAP_ATTRIBUTE MapAttribute;
264 IA32_MAP_ATTRIBUTE ExpectedMapAttribute;
265 IA32_MAP_ATTRIBUTE MapMask;
266 RETURN_STATUS Status;
267 IA32_MAP_ENTRY *Map;
268 UINTN MapCount;
269 IA32_PAGING_ENTRY *PagingEntry;
270 VOID *BackupBuffer;
271 UINTN BackupPageTableBufferSize;
272
273 PagingMode = Paging4Level;
274 PageTableBufferSize = 0;
275 PageTable = 0;
276 Buffer = NULL;
277 MapAttribute.Uint64 = 0;
278 MapMask.Uint64 = MAX_UINT64;
279 MapAttribute.Bits.Present = 1;
280 MapAttribute.Bits.ReadWrite = 1;
281
282 //
283 // Create Page table to cover [0,2G], with ReadWrite = 1
284 //
285 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, SIZE_2GB, &MapAttribute, &MapMask, NULL);
287 BackupPageTableBufferSize = PageTableBufferSize;
288 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize));
289 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, SIZE_2GB, &MapAttribute, &MapMask, NULL);
291 IsPageTableValid (PageTable, PagingMode);
292
293 MapCount = 0;
294 Status = PageTableParse (PageTable, PagingMode, NULL, &MapCount);
296 IsPageTableValid (PageTable, PagingMode);
297 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount));
298 Status = PageTableParse (PageTable, PagingMode, Map, &MapCount);
300 UT_ASSERT_EQUAL (MapCount, 1);
301 UT_ASSERT_EQUAL (Map[0].LinearAddress, 0);
302 UT_ASSERT_EQUAL (Map[0].Length, SIZE_2GB);
303 ExpectedMapAttribute.Uint64 = MapAttribute.Uint64;
304 UT_ASSERT_EQUAL (Map[0].Attribute.Uint64, ExpectedMapAttribute.Uint64);
305
306 //
307 // Manually change ReadWrite to 0 for non-leaf entry, which covers [0,2G]
308 //
309 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTable;
310 PagingEntry->Uint64 = PagingEntry->Uint64 & (~(UINT64)0x2);
311 MapCount = 0;
312 Status = PageTableParse (PageTable, PagingMode, NULL, &MapCount);
314 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount));
315 Status = PageTableParse (PageTable, PagingMode, Map, &MapCount);
316
318 UT_ASSERT_EQUAL (MapCount, 1);
319 UT_ASSERT_EQUAL (Map[0].LinearAddress, 0);
320 UT_ASSERT_EQUAL (Map[0].Length, SIZE_2GB);
321 ExpectedMapAttribute.Uint64 = MapAttribute.Uint64;
322 ExpectedMapAttribute.Bits.ReadWrite = 0;
323 UT_ASSERT_EQUAL (Map[0].Attribute.Uint64, ExpectedMapAttribute.Uint64);
324
325 //
326 // Copy the page entry structure memory for future compare
327 //
328 BackupBuffer = AllocateCopyPool (BackupPageTableBufferSize, Buffer);
329 UT_ASSERT_MEM_EQUAL (Buffer, BackupBuffer, BackupPageTableBufferSize);
330
331 //
332 // Call library to change ReadWrite to 0 for [0,2M]
333 //
334 MapAttribute.Bits.ReadWrite = 0;
335 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, 0, SIZE_2MB, &MapAttribute, &MapMask, NULL);
337 IsPageTableValid (PageTable, PagingMode);
338 MapCount = 0;
339 Status = PageTableParse (PageTable, PagingMode, NULL, &MapCount);
341 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount));
342 Status = PageTableParse (PageTable, PagingMode, Map, &MapCount);
343 //
344 // There should be 1 range [0, 2G] with ReadWrite = 0
345 //
347 UT_ASSERT_EQUAL (MapCount, 1);
348 UT_ASSERT_EQUAL (Map[0].LinearAddress, 0);
349 UT_ASSERT_EQUAL (Map[0].Length, SIZE_2GB);
350 ExpectedMapAttribute.Uint64 = MapAttribute.Uint64;
351 UT_ASSERT_EQUAL (Map[0].Attribute.Uint64, ExpectedMapAttribute.Uint64);
352
353 //
354 // The latest PageTableMap call should change nothing.
355 // The memory should be identical before and after the funtion is called.
356 //
357 UT_ASSERT_MEM_EQUAL (Buffer, BackupBuffer, BackupPageTableBufferSize);
358
359 //
360 // Call library to change ReadWrite to 1 for [0, 2M]
361 //
362 MapAttribute.Bits.ReadWrite = 1;
363 PageTableBufferSize = 0;
364 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, 0, SIZE_2MB, &MapAttribute, &MapMask, NULL);
366 IsPageTableValid (PageTable, PagingMode);
367 MapCount = 0;
368 Status = PageTableParse (PageTable, PagingMode, NULL, &MapCount);
370 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount));
371 Status = PageTableParse (PageTable, PagingMode, Map, &MapCount);
372 //
373 // There should be 2 range [0, 2M] with ReadWrite = 1 and [2M, 2G] with ReadWrite = 0
374 //
376 UT_ASSERT_EQUAL (MapCount, 2);
377
378 UT_ASSERT_EQUAL (Map[0].LinearAddress, 0);
379 UT_ASSERT_EQUAL (Map[0].Length, SIZE_2MB);
380 ExpectedMapAttribute.Uint64 = MapAttribute.Uint64;
381 UT_ASSERT_EQUAL (Map[0].Attribute.Uint64, ExpectedMapAttribute.Uint64);
382
383 UT_ASSERT_EQUAL (Map[1].LinearAddress, SIZE_2MB);
384 UT_ASSERT_EQUAL (Map[1].Length, SIZE_2GB - SIZE_2MB);
385 ExpectedMapAttribute.Uint64 = SIZE_2MB;
386 ExpectedMapAttribute.Bits.ReadWrite = 0;
387 ExpectedMapAttribute.Bits.Present = 1;
388 UT_ASSERT_EQUAL (Map[1].Attribute.Uint64, ExpectedMapAttribute.Uint64);
389
390 return UNIT_TEST_PASSED;
391}
392
409EFIAPI
411 IN UNIT_TEST_CONTEXT Context
412 )
413{
414 UINTN PageTable;
415 PAGING_MODE PagingMode;
416 VOID *Buffer;
417 UINTN PageTableBufferSize;
418 IA32_MAP_ATTRIBUTE MapAttribute;
419 IA32_MAP_ATTRIBUTE ExpectedMapAttribute;
420 IA32_MAP_ATTRIBUTE MapMask;
421 RETURN_STATUS Status;
422 IA32_MAP_ENTRY *Map;
423 UINTN MapCount;
424 IA32_PAGING_ENTRY *PagingEntry;
425
426 PagingMode = Paging4Level;
427 PageTableBufferSize = 0;
428 PageTable = 0;
429 Buffer = NULL;
430 MapMask.Uint64 = MAX_UINT64;
431 MapAttribute.Uint64 = (SIZE_2MB - SIZE_4KB);
432 MapAttribute.Bits.Present = 1;
433 MapAttribute.Bits.ReadWrite = 1;
434 //
435 // Create Page table to cover [2M-4K, 4M], with ReadWrite = 1
436 //
437 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2MB - SIZE_4KB, SIZE_4KB + SIZE_2MB, &MapAttribute, &MapMask, NULL);
439 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize));
440 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2MB - SIZE_4KB, SIZE_4KB + SIZE_2MB, &MapAttribute, &MapMask, NULL);
442 IsPageTableValid (PageTable, PagingMode);
443
444 MapCount = 0;
445 Status = PageTableParse (PageTable, PagingMode, NULL, &MapCount);
447 IsPageTableValid (PageTable, PagingMode);
448 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount));
449 Status = PageTableParse (PageTable, PagingMode, Map, &MapCount);
451 UT_ASSERT_EQUAL (MapCount, 1);
452 UT_ASSERT_EQUAL (Map[0].LinearAddress, SIZE_2MB - SIZE_4KB);
453 UT_ASSERT_EQUAL (Map[0].Length, SIZE_4KB + SIZE_2MB);
454 ExpectedMapAttribute.Uint64 = MapAttribute.Uint64;
455 UT_ASSERT_EQUAL (Map[0].Attribute.Uint64, ExpectedMapAttribute.Uint64);
456
457 //
458 // Manually change ReadWrite to 0 for 3 level non-leaf entry, which covers [0,2M]
459 // Then the map is:
460 // [2M-4K,2M], R/W = 0
461 // [2M ,4M], R/W = 1
462 //
463 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTable; // Get 4 level entry
464 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (PagingEntry); // Get 3 level entry
465 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (PagingEntry); // Get 2 level entry
466 PagingEntry->Uint64 = PagingEntry->Uint64 & (~(UINT64)0x2);
467 MapCount = 0;
468 Status = PageTableParse (PageTable, PagingMode, NULL, &MapCount);
470 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount));
471 Status = PageTableParse (PageTable, PagingMode, Map, &MapCount);
472
474 UT_ASSERT_EQUAL (MapCount, 2);
475 UT_ASSERT_EQUAL (Map[0].LinearAddress, SIZE_2MB - SIZE_4KB);
476 UT_ASSERT_EQUAL (Map[0].Length, SIZE_4KB);
477 ExpectedMapAttribute.Uint64 = MapAttribute.Uint64;
478 ExpectedMapAttribute.Bits.ReadWrite = 0;
479 UT_ASSERT_EQUAL (Map[0].Attribute.Uint64, ExpectedMapAttribute.Uint64);
480
481 UT_ASSERT_EQUAL (Map[1].LinearAddress, SIZE_2MB);
482 UT_ASSERT_EQUAL (Map[1].Length, SIZE_2MB);
483 ExpectedMapAttribute.Uint64 = MapAttribute.Uint64 + SIZE_4KB;
484 ExpectedMapAttribute.Bits.ReadWrite = 1;
485 UT_ASSERT_EQUAL (Map[1].Attribute.Uint64, ExpectedMapAttribute.Uint64);
486
487 //
488 // Set Page table [2M-4K, 2M+4K]'s ReadWrite = 1, [2M,2M+4K]'s ReadWrite is already 1
489 // Just need to set [2M-4K,2M], won't need extra size, so the status should be success
490 //
491 MapAttribute.Uint64 = SIZE_2MB - SIZE_4KB;
492 MapAttribute.Bits.Present = 1;
493 MapAttribute.Bits.ReadWrite = 1;
494 PageTableBufferSize = 0;
495 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2MB - SIZE_4KB, SIZE_4KB * 2, &MapAttribute, &MapMask, NULL);
497 return UNIT_TEST_PASSED;
498}
499
516EFIAPI
518 IN UNIT_TEST_CONTEXT Context
519 )
520{
521 UINTN PageTable;
522 PAGING_MODE PagingMode;
523 VOID *Buffer;
524 UINTN PageTableBufferSize;
525 IA32_MAP_ATTRIBUTE MapAttribute;
526 IA32_MAP_ATTRIBUTE MapMask;
527 RETURN_STATUS Status;
528 UNIT_TEST_STATUS TestStatus;
529
530 PagingMode = Paging4Level1GB;
531 PageTableBufferSize = 0;
532 PageTable = 0;
533 Buffer = NULL;
534 MapAttribute.Uint64 = 0;
535 MapMask.Uint64 = MAX_UINT64;
536 MapAttribute.Bits.Present = 1;
537 MapMask.Bits.Present = 1;
538
539 //
540 // Create Page table to cover [0,4M], and [4M, 1G] is not present
541 //
542 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_2MB * 2, &MapAttribute, &MapMask, NULL);
544 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize));
545 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_2MB * 2, &MapAttribute, &MapMask, NULL);
547 TestStatus = IsPageTableValid (PageTable, PagingMode);
548 if (TestStatus != UNIT_TEST_PASSED) {
549 return TestStatus;
550 }
551
552 //
553 // Let Page table to cover [0,1G], we assume it won't use a big 1G entry to cover whole range
554 // It looks like the chioce is not bad, but sometime, we need to keep some small entry
555 //
556 PageTableBufferSize = 0;
557 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB, &MapAttribute, &MapMask, NULL);
559 TestStatus = IsPageTableValid (PageTable, PagingMode);
560 if (TestStatus != UNIT_TEST_PASSED) {
561 return TestStatus;
562 }
563
564 MapAttribute.Bits.Accessed = 1;
565 PageTableBufferSize = 0;
566 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_2MB, &MapAttribute, &MapMask, NULL);
567 //
568 // If it didn't use a big 1G entry to cover whole range, only change [0,2M] for some attribute won't need extra memory
569 //
571
572 return UNIT_TEST_PASSED;
573}
574
591EFIAPI
593 IN UNIT_TEST_CONTEXT Context
594 )
595{
596 UINTN PageTable;
597 PAGING_MODE PagingMode;
598 VOID *Buffer;
599 UINTN PageTableBufferSize;
600 IA32_MAP_ATTRIBUTE MapAttribute;
601 IA32_MAP_ATTRIBUTE ExpectedMapAttribute;
602 IA32_MAP_ATTRIBUTE MapMask;
603 RETURN_STATUS Status;
604 IA32_MAP_ENTRY *Map;
605 UINTN MapCount;
606 IA32_PAGING_ENTRY *PagingEntry;
607 UNIT_TEST_STATUS TestStatus;
608
609 PagingMode = Paging4Level1GB;
610 PageTableBufferSize = 0;
611 PageTable = 0;
612 Buffer = NULL;
613 MapAttribute.Uint64 = 0;
614 MapMask.Uint64 = MAX_UINT64;
615 MapAttribute.Bits.Present = 1;
616 MapAttribute.Bits.Nx = 0;
617
618 //
619 // Create Page table to cover [0,2G], with Nx = 0
620 //
621 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB * 2, &MapAttribute, &MapMask, NULL);
623 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize));
624 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB * 2, &MapAttribute, &MapMask, NULL);
626 TestStatus = IsPageTableValid (PageTable, PagingMode);
627 if (TestStatus != UNIT_TEST_PASSED) {
628 return TestStatus;
629 }
630
631 MapCount = 0;
632 Status = PageTableParse (PageTable, PagingMode, NULL, &MapCount);
634 TestStatus = IsPageTableValid (PageTable, PagingMode);
635 if (TestStatus != UNIT_TEST_PASSED) {
636 return TestStatus;
637 }
638
639 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount* sizeof (IA32_MAP_ENTRY)));
640 Status = PageTableParse (PageTable, PagingMode, Map, &MapCount);
642 UT_ASSERT_EQUAL (MapCount, 1);
643 UT_ASSERT_EQUAL (Map[0].LinearAddress, 0);
644 UT_ASSERT_EQUAL (Map[0].Length, SIZE_2GB);
645 ExpectedMapAttribute.Uint64 = MapAttribute.Uint64;
646 UT_ASSERT_EQUAL (Map[0].Attribute.Uint64, ExpectedMapAttribute.Uint64);
647
648 //
649 // Manually change Nx to 1 for non-leaf entry, which covers [0,2G]
650 //
651 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTable;
652 PagingEntry->Uint64 = PagingEntry->Uint64 | BIT63;
653 MapCount = 0;
654 Status = PageTableParse (PageTable, PagingMode, NULL, &MapCount);
656 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount* sizeof (IA32_MAP_ENTRY)));
657 Status = PageTableParse (PageTable, PagingMode, Map, &MapCount);
659 UT_ASSERT_EQUAL (MapCount, 1);
660 UT_ASSERT_EQUAL (Map[0].LinearAddress, 0);
661 UT_ASSERT_EQUAL (Map[0].Length, SIZE_2GB);
662 ExpectedMapAttribute.Bits.Nx = 1;
663 UT_ASSERT_EQUAL (Map[0].Attribute.Uint64, ExpectedMapAttribute.Uint64);
664
665 //
666 // Call library to change Nx to 0 for [0,1G]
667 //
668 Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, (UINT64)0, (UINT64)SIZE_1GB, &MapAttribute, &MapMask, NULL);
670 TestStatus = IsPageTableValid (PageTable, PagingMode);
671 if (TestStatus != UNIT_TEST_PASSED) {
672 return TestStatus;
673 }
674
675 MapCount = 0;
676 Status = PageTableParse (PageTable, PagingMode, NULL, &MapCount);
678 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount* sizeof (IA32_MAP_ENTRY)));
679 Status = PageTableParse (PageTable, PagingMode, Map, &MapCount);
681
682 //
683 // There should be two ranges [0, 1G] with Nx = 0 and [1G, 2G] with Nx = 1
684 //
685 UT_ASSERT_EQUAL (MapCount, 2);
686 UT_ASSERT_EQUAL (Map[0].LinearAddress, 0);
687 UT_ASSERT_EQUAL (Map[0].Length, SIZE_1GB);
688 ExpectedMapAttribute.Uint64 = MapAttribute.Uint64;
689 UT_ASSERT_EQUAL (Map[0].Attribute.Uint64, ExpectedMapAttribute.Uint64);
690 UT_ASSERT_EQUAL (Map[1].LinearAddress, SIZE_1GB);
691 UT_ASSERT_EQUAL (Map[1].Length, SIZE_1GB);
692 ExpectedMapAttribute.Uint64 = SIZE_1GB;
693 ExpectedMapAttribute.Bits.Present = 1;
694 ExpectedMapAttribute.Bits.Nx = 1;
695 UT_ASSERT_EQUAL (Map[1].Attribute.Uint64, ExpectedMapAttribute.Uint64);
696 return UNIT_TEST_PASSED;
697}
698
716EFIAPI
718 IN UNIT_TEST_CONTEXT Context
719 )
720{
721 UINTN PageTable;
722 PAGING_MODE PagingMode;
723 VOID *Buffer;
724 UINTN PageTableBufferSize;
725 IA32_MAP_ATTRIBUTE MapAttribute;
726 IA32_MAP_ATTRIBUTE ExpectedMapAttribute;
727 IA32_MAP_ATTRIBUTE MapMask;
728 RETURN_STATUS Status;
729 IA32_MAP_ENTRY *Map;
730 UINTN MapCount;
731
732 PagingMode = Paging4Level;
733 PageTableBufferSize = 0;
734 PageTable = 0;
735 Buffer = NULL;
736 MapAttribute.Uint64 = 0;
737 MapAttribute.Bits.Present = 1;
738 MapMask.Uint64 = 0;
739 MapMask.Bits.Present = 1;
740 //
741 // Create Page table to cover [0, 2G]. All fields of MapMask should be set.
742 //
743 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, SIZE_2GB, &MapAttribute, &MapMask, NULL);
745 MapMask.Uint64 = MAX_UINT64;
746 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, SIZE_2GB, &MapAttribute, &MapMask, NULL);
748 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize));
749 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, 0, SIZE_2GB, &MapAttribute, &MapMask, NULL);
751
752 //
753 // Update Page table to set [2G - 8K, 2G] from present to non-present. All fields of MapMask except present should not be set.
754 //
755 PageTableBufferSize = 0;
756 MapAttribute.Uint64 = 0;
757 MapMask.Uint64 = 0;
758 MapMask.Bits.Present = 1;
759 MapMask.Bits.ReadWrite = 1;
760 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL);
762 MapMask.Bits.ReadWrite = 0;
763 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL);
765 Buffer = AllocatePages (EFI_SIZE_TO_PAGES (PageTableBufferSize));
766 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL);
768
769 //
770 // Still set [2G - 8K, 2G] as not present, this case is permitted. But set [2G - 8K, 2G] as RW is not permitted.
771 //
772 PageTableBufferSize = 0;
773 MapAttribute.Uint64 = 0;
774 MapMask.Uint64 = 0;
775 MapMask.Bits.Present = 1;
776 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL);
778 MapAttribute.Bits.ReadWrite = 1;
779 MapMask.Bits.ReadWrite = 1;
780 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL);
782
783 //
784 // Update Page table to set [2G - 8K, 2G] as present and RW. All fields of MapMask should be set.
785 //
786 PageTableBufferSize = 0;
787 MapAttribute.Uint64 = SIZE_2GB - SIZE_8KB;
788 MapAttribute.Bits.ReadWrite = 1;
789 MapAttribute.Bits.Present = 1;
790 MapMask.Uint64 = 0;
791 MapMask.Bits.ReadWrite = 1;
792 MapMask.Bits.Present = 1;
793 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL);
795 MapMask.Uint64 = MAX_UINT64;
796 Status = PageTableMap (&PageTable, PagingMode, Buffer, &PageTableBufferSize, SIZE_2GB - SIZE_8KB, SIZE_8KB, &MapAttribute, &MapMask, NULL);
798
799 MapCount = 0;
800 Status = PageTableParse (PageTable, PagingMode, NULL, &MapCount);
802 Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount* sizeof (IA32_MAP_ENTRY)));
803 Status = PageTableParse (PageTable, PagingMode, Map, &MapCount);
805
806 //
807 // There should be two ranges [0, 2G-8k] with RW = 0 and [2G-8k, 2G] with RW = 1
808 //
809 UT_ASSERT_EQUAL (MapCount, 2);
810 UT_ASSERT_EQUAL (Map[0].LinearAddress, 0);
811 UT_ASSERT_EQUAL (Map[0].Length, SIZE_2GB - SIZE_8KB);
812 ExpectedMapAttribute.Uint64 = 0;
813 ExpectedMapAttribute.Bits.Present = 1;
814 UT_ASSERT_EQUAL (Map[0].Attribute.Uint64, ExpectedMapAttribute.Uint64);
815 UT_ASSERT_EQUAL (Map[1].LinearAddress, SIZE_2GB - SIZE_8KB);
816 UT_ASSERT_EQUAL (Map[1].Length, SIZE_8KB);
817 ExpectedMapAttribute.Uint64 = SIZE_2GB - SIZE_8KB;
818 ExpectedMapAttribute.Bits.Present = 1;
819 ExpectedMapAttribute.Bits.ReadWrite = 1;
820 UT_ASSERT_EQUAL (Map[1].Attribute.Uint64, ExpectedMapAttribute.Uint64);
821 return UNIT_TEST_PASSED;
822}
823
833EFIAPI
835 VOID
836 )
837{
838 EFI_STATUS Status;
839 UNIT_TEST_FRAMEWORK_HANDLE Framework;
840 UNIT_TEST_SUITE_HANDLE ManualTestCase;
841
842 // UNIT_TEST_SUITE_HANDLE RandomTestCase;
843
844 Framework = NULL;
845
846 DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION));
847
848 //
849 // Start setting up the test framework for running the tests.
850 //
851 Status = InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCallerBaseName, UNIT_TEST_APP_VERSION);
852 if (EFI_ERROR (Status)) {
853 DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
854 goto EXIT;
855 }
856
857 //
858 // Populate the Manual Test Cases.
859 //
860 Status = CreateUnitTestSuite (&ManualTestCase, Framework, "Manual Test Cases", "CpuPageTableLib.Manual", NULL, NULL);
861 if (EFI_ERROR (Status)) {
862 DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for Manual Test Cases\n"));
863 Status = EFI_OUT_OF_RESOURCES;
864 goto EXIT;
865 }
866
867 AddTestCase (ManualTestCase, "Check if the input parameters are not supported.", "Manual Test Case1", TestCaseForParameter, NULL, NULL, NULL);
868 AddTestCase (ManualTestCase, "Check the case that modifying page table doesn't need extra buffer", "Manual Test Case2", TestCaseWhichNoNeedExtraSize, NULL, NULL, NULL);
869 AddTestCase (ManualTestCase, "Check the case to map [0, 1G] to [8K, 1G+8K]", "Manual Test Case3", TestCase1Gmapto4K, NULL, NULL, NULL);
870 AddTestCase (ManualTestCase, "Check won't merge entries", "Manual Test Case4", TestCaseManualNotMergeEntry, NULL, NULL, NULL);
871 AddTestCase (ManualTestCase, "Check if the parent entry has different ReadWrite attribute", "Manual Test Case5", TestCaseManualChangeReadWrite, NULL, NULL, NULL);
872 AddTestCase (ManualTestCase, "Check if the parent entry has different Nx attribute", "Manual Test Case6", TestCaseManualChangeNx, NULL, NULL, NULL);
873 AddTestCase (ManualTestCase, "Check if the needed size is expected", "Manual Test Case7", TestCaseManualSizeNotMatch, NULL, NULL, NULL);
874 AddTestCase (ManualTestCase, "Check MapMask when creating new page table or mapping not-present range", "Manual Test Case8", TestCaseToCheckMapMaskAndAttr, NULL, NULL, NULL);
875 //
876 // Populate the Random Test Cases.
877 //
878 // Status = CreateUnitTestSuite (&RandomTestCase, Framework, "Random Test Cases", "CpuPageTableLib.Random", NULL, NULL);
879 // if (EFI_ERROR (Status)) {
880 // DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for Random Test Cases\n"));
881 // Status = EFI_OUT_OF_RESOURCES;
882 // goto EXIT;
883 // }
884
885 // AddTestCase (RandomTestCase, "Random Test for Paging4Level", "Random Test Case1", TestCaseforRandomTest, NULL, NULL, &mTestContextPaging4Level);
886 // AddTestCase (RandomTestCase, "Random Test for Paging4Level1G", "Random Test Case2", TestCaseforRandomTest, NULL, NULL, &mTestContextPaging4Level1GB);
887 // AddTestCase (RandomTestCase, "Random Test for Paging5Level", "Random Test Case3", TestCaseforRandomTest, NULL, NULL, &mTestContextPaging5Level);
888 // AddTestCase (RandomTestCase, "Random Test for Paging5Level1G", "Random Test Case4", TestCaseforRandomTest, NULL, NULL, &mTestContextPaging5Level1GB);
889 // AddTestCase (RandomTestCase, "Random Test for PagingPae", "Random Test Case5", TestCaseforRandomTest, NULL, NULL, &mTestContextPagingPae);
890
891 //
892 // Execute the tests.
893 //
894 Status = RunAllTestSuites (Framework);
895
896EXIT:
897 if (Framework) {
898 FreeUnitTestFramework (Framework);
899 }
900
901 return Status;
902}
903
912INT32
914 INT32 Argc,
915 CHAR8 *Argv[]
916 )
917{
918 InitGlobalData (52);
919 return UefiTestMain ();
920}
UINT64 UINTN
RETURN_STATUS EFIAPI PageTableMap(IN OUT UINTN *PageTable OPTIONAL, IN PAGING_MODE PagingMode, IN VOID *Buffer, IN OUT UINTN *BufferSize, IN UINT64 LinearAddress, IN UINT64 Length, IN IA32_MAP_ATTRIBUTE *Attribute, IN IA32_MAP_ATTRIBUTE *Mask, OUT BOOLEAN *IsModified OPTIONAL)
RETURN_STATUS EFIAPI PageTableParse(IN UINTN PageTable, IN PAGING_MODE PagingMode, IN IA32_MAP_ENTRY *Map, IN OUT UINTN *MapCount)
UNIT_TEST_STATUS IsPageTableValid(IN UINTN PageTable, IN PAGING_MODE PagingMode)
Definition: TestHelper.c:170
VOID InitGlobalData(UINTN MemorySpace)
Definition: TestHelper.c:31
EFI_STATUS EFIAPI UefiTestMain(VOID)
UNIT_TEST_STATUS EFIAPI TestCaseManualChangeReadWrite(IN UNIT_TEST_CONTEXT Context)
UNIT_TEST_STATUS EFIAPI TestCase1Gmapto4K(IN UNIT_TEST_CONTEXT Context)
UNIT_TEST_STATUS EFIAPI TestCaseForParameter(IN UNIT_TEST_CONTEXT Context)
UNIT_TEST_STATUS EFIAPI TestCaseManualSizeNotMatch(IN UNIT_TEST_CONTEXT Context)
UNIT_TEST_STATUS EFIAPI TestCaseToCheckMapMaskAndAttr(IN UNIT_TEST_CONTEXT Context)
UNIT_TEST_STATUS EFIAPI TestCaseManualChangeNx(IN UNIT_TEST_CONTEXT Context)
UNIT_TEST_STATUS EFIAPI TestCaseManualNotMergeEntry(IN UNIT_TEST_CONTEXT Context)
UNIT_TEST_STATUS EFIAPI TestCaseWhichNoNeedExtraSize(IN UNIT_TEST_CONTEXT Context)
int main()
=== TEST ENGINE ================================================================================
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define NULL
Definition: Base.h:319
#define RETURN_BUFFER_TOO_SMALL
Definition: Base.h:1093
#define RETURN_UNSUPPORTED
Definition: Base.h:1081
#define RETURN_SUCCESS
Definition: Base.h:1066
#define IN
Definition: Base.h:279
#define RETURN_INVALID_PARAMETER
Definition: Base.h:1076
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID *EFIAPI AllocatePages(IN UINTN Pages)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
EFI_STATUS EFIAPI RunAllTestSuites(IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle)
Definition: RunTests.c:145
VOID * UNIT_TEST_CONTEXT
Definition: UnitTestLib.h:54
#define UT_ASSERT_MEM_EQUAL(BufferA, BufferB, Length)
Definition: UnitTestLib.h:389
#define UT_ASSERT_EQUAL(ValueA, ValueB)
Definition: UnitTestLib.h:375
EFI_STATUS EFIAPI CreateUnitTestSuite(OUT UNIT_TEST_SUITE_HANDLE *SuiteHandle, IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle, IN CHAR8 *Title, IN CHAR8 *Name, IN UNIT_TEST_SUITE_SETUP Setup OPTIONAL, IN UNIT_TEST_SUITE_TEARDOWN Teardown OPTIONAL)
Definition: UnitTestLib.c:326
EFI_STATUS EFIAPI FreeUnitTestFramework(IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle)
Definition: UnitTestLib.c:150
EFI_STATUS EFIAPI AddTestCase(IN UNIT_TEST_SUITE_HANDLE SuiteHandle, IN CHAR8 *Description, IN CHAR8 *Name, IN UNIT_TEST_FUNCTION Function, IN UNIT_TEST_PREREQUISITE Prerequisite OPTIONAL, IN UNIT_TEST_CLEANUP CleanUp OPTIONAL, IN UNIT_TEST_CONTEXT Context OPTIONAL)
Definition: UnitTestLib.c:426
EFI_STATUS EFIAPI InitUnitTestFramework(OUT UNIT_TEST_FRAMEWORK_HANDLE *FrameworkHandle, IN CHAR8 *Title, IN CHAR8 *ShortTitle, IN CHAR8 *VersionString)
Definition: UnitTestLib.c:204
UINT32 UNIT_TEST_STATUS
Definition: UnitTestLib.h:16