return Status;\r
}\r
\r
+/**\r
+ Remove the last MAP_ENTRY in MapEntrys.\r
+\r
+ @param MapEntrys Pointer to MapEntrys buffer\r
+**/\r
+VOID\r
+RemoveLastMapEntry (\r
+ IN OUT MAP_ENTRYS *MapEntrys\r
+ )\r
+{\r
+ UINTN MapsIndex;\r
+\r
+ if (MapEntrys->Count == 0) {\r
+ return;\r
+ }\r
+\r
+ MapsIndex = MapEntrys->Count - 1;\r
+ ZeroMem (&(MapEntrys->Maps[MapsIndex]), sizeof (MAP_ENTRY));\r
+ MapEntrys->Count = MapsIndex;\r
+}\r
+\r
/**\r
Generate single random map entry.\r
The map entry can be the input of function PageTableMap\r
MapEntrys->Maps[MapsIndex].Mask.Uint64 = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].Mask.Uint64;\r
} else {\r
MapEntrys->Maps[MapsIndex].Attribute.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64;\r
- MapEntrys->Maps[MapsIndex].Mask.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64;\r
+ if (RandomBoolean (5)) {\r
+ //\r
+ // The probability to get random Mask should be small since all bits of a random number\r
+ // have a high probability of containing 0, which may be a invalid input.\r
+ //\r
+ MapEntrys->Maps[MapsIndex].Mask.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64;\r
+ } else {\r
+ MapEntrys->Maps[MapsIndex].Mask.Uint64 = MAX_UINT64;\r
+ }\r
+\r
if (MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey != 0) {\r
MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey = 0xF;\r
}\r
MapEntrys->Maps[MapsIndex].Attribute.Bits.PageTableBaseAddress = MapEntrys->Maps[MapsIndex].LinearAddress >> 12;\r
MapEntrys->Maps[MapsIndex].Mask.Bits.PageTableBaseAddress = 0xFFFFFFFFFF;\r
} else {\r
- //\r
- // Todo: If the mask bit for base address is zero, when dump the pagetable, every entry mapping to physical address zeor.\r
- // This means the map count will be a large number, and impossible to finish in proper time.\r
- // Need to avoid such case when remove the Random option ONLY_ONE_ONE_MAPPING\r
- //\r
MapEntrys->Maps[MapsIndex].Attribute.Bits.PageTableBaseAddress = (Random64 (0, (((UINT64)1)<<52) - 1) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)])>> 12;\r
- if (RandomBoolean (50)) {\r
- MapEntrys->Maps[MapsIndex].Mask.Bits.PageTableBaseAddress = 0;\r
- }\r
}\r
\r
MapEntrys->Count += 1;\r
IN UINTN InitMapCount\r
)\r
{\r
- UINTN MapsIndex;\r
- RETURN_STATUS Status;\r
- UINTN PageTableBufferSize;\r
- VOID *Buffer;\r
- IA32_MAP_ENTRY *Map;\r
- UINTN MapCount;\r
- UINTN Index;\r
- UINTN KeyPointCount;\r
- UINTN NewKeyPointCount;\r
- UINT64 *KeyPointBuffer;\r
- UINTN Level;\r
- UINT64 Value;\r
- UNIT_TEST_STATUS TestStatus;\r
- MAP_ENTRY *LastMapEntry;\r
-\r
- MapsIndex = MapEntrys->Count;\r
+ UINTN MapsIndex;\r
+ RETURN_STATUS Status;\r
+ UINTN PageTableBufferSize;\r
+ VOID *Buffer;\r
+ IA32_MAP_ENTRY *Map;\r
+ UINTN MapCount;\r
+ UINTN Index;\r
+ UINTN KeyPointCount;\r
+ UINTN NewKeyPointCount;\r
+ UINT64 *KeyPointBuffer;\r
+ UINTN Level;\r
+ UINT64 Value;\r
+ UNIT_TEST_STATUS TestStatus;\r
+ MAP_ENTRY *LastMapEntry;\r
+ IA32_MAP_ATTRIBUTE *Mask;\r
+ IA32_MAP_ATTRIBUTE *Attribute;\r
+ UINT64 LastNotPresentRegionStart;\r
+ BOOLEAN IsNotPresent;\r
+\r
+ MapsIndex = MapEntrys->Count;\r
+ MapCount = 0;\r
+ LastNotPresentRegionStart = 0;\r
+ IsNotPresent = FALSE;\r
\r
GenerateSingleRandomMapEntry (MaxAddress, MapEntrys);\r
LastMapEntry = &MapEntrys->Maps[MapsIndex];\r
+ Status = PageTableParse (*PageTable, PagingMode, NULL, &MapCount);\r
+\r
+ if (MapCount != 0) {\r
+ UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);\r
+ Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount * sizeof (IA32_MAP_ENTRY)));\r
+ ASSERT (Map != NULL);\r
+ Status = PageTableParse (*PageTable, PagingMode, Map, &MapCount);\r
+ }\r
+\r
+ //\r
+ // Check if the generated MapEntrys->Maps[MapsIndex] contains not-present range.\r
+ //\r
+ if (LastMapEntry->Length > 0) {\r
+ for (Index = 0; Index < MapCount; Index++) {\r
+ if ((LastNotPresentRegionStart < Map[Index].LinearAddress) &&\r
+ (LastMapEntry->LinearAddress < Map[Index].LinearAddress) && (LastMapEntry->LinearAddress + LastMapEntry->Length > LastNotPresentRegionStart))\r
+ {\r
+ //\r
+ // MapEntrys->Maps[MapsIndex] contains not-present range in exsiting page table.\r
+ //\r
+ break;\r
+ }\r
+\r
+ LastNotPresentRegionStart = Map[Index].LinearAddress + Map[Index].Length;\r
+ }\r
+\r
+ //\r
+ // Either LastMapEntry overlaps with the not-present region in the very end\r
+ // Or it overlaps with one in the middle\r
+ if (LastNotPresentRegionStart < LastMapEntry->LinearAddress + LastMapEntry->Length) {\r
+ IsNotPresent = TRUE;\r
+ }\r
+ }\r
\r
PageTableBufferSize = 0;\r
Status = PageTableMap (\r
&LastMapEntry->Attribute,\r
&LastMapEntry->Mask\r
);\r
+\r
+ Attribute = &LastMapEntry->Attribute;\r
+ Mask = &LastMapEntry->Mask;\r
+ //\r
+ // If set [LinearAddress, LinearAddress+Attribute] to not preset, all\r
+ // other attributes should not be provided.\r
+ //\r
+ if ((LastMapEntry->Length > 0) && (Attribute->Bits.Present == 0) && (Mask->Bits.Present == 1) && (Mask->Uint64 > 1)) {\r
+ RemoveLastMapEntry (MapEntrys);\r
+ UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER);\r
+ return UNIT_TEST_PASSED;\r
+ }\r
+\r
+ //\r
+ // Return Status for non-present range also should be InvalidParameter when:\r
+ // 1. Some of attributes are not provided when mapping non-present range to present.\r
+ // 2. Set any other attribute without setting the non-present range to Present.\r
+ //\r
+ if (IsNotPresent) {\r
+ if ((Mask->Bits.Present == 1) && (Attribute->Bits.Present == 1)) {\r
+ //\r
+ // Creating new page table or remapping non-present range to present.\r
+ //\r
+ if ((Mask->Bits.ReadWrite == 0) || (Mask->Bits.UserSupervisor == 0) || (Mask->Bits.WriteThrough == 0) || (Mask->Bits.CacheDisabled == 0) ||\r
+ (Mask->Bits.Accessed == 0) || (Mask->Bits.Dirty == 0) || (Mask->Bits.Pat == 0) || (Mask->Bits.Global == 0) ||\r
+ (Mask->Bits.PageTableBaseAddress == 0) || (Mask->Bits.ProtectionKey == 0) || (Mask->Bits.Nx == 0))\r
+ {\r
+ RemoveLastMapEntry (MapEntrys);\r
+ UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER);\r
+ return UNIT_TEST_PASSED;\r
+ }\r
+ } else if ((Mask->Bits.Present == 0) && (Mask->Uint64 > 1)) {\r
+ //\r
+ // Only change other attributes for non-present range is not permitted.\r
+ //\r
+ RemoveLastMapEntry (MapEntrys);\r
+ UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER);\r
+ return UNIT_TEST_PASSED;\r
+ }\r
+ }\r
+\r
if (PageTableBufferSize != 0) {\r
UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);\r
\r