mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-29 08:34:07 +02:00
UefiCpuPkg/CpuPageTableLib:Modify RandomTest to check Mask/Attr
Modify RandomTest to check invalid input. When creating new page table or updating exsiting page table: 1.If set [LinearAddress, LinearAddress+Length] to non-present, all other attributes should not be provided. 2.If [LinearAddress, LinearAddress+Length] contain non-present range, the Returnstatus of PageTableMap() should be InvalidParameter when: 2.1Some of attributes are not provided when mapping non-present range to present. 2.2Set any other attribute without setting the non-present range to Present. Signed-off-by: Dun Tan <dun.tan@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Tested-by: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Cc: Zhiguang Liu <zhiguang.liu@intel.com>
This commit is contained in:
parent
ecfe6382c1
commit
cecf279c32
@ -273,6 +273,27 @@ ValidateAndRandomeModifyPageTable (
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Remove the last MAP_ENTRY in MapEntrys.
|
||||||
|
|
||||||
|
@param MapEntrys Pointer to MapEntrys buffer
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
RemoveLastMapEntry (
|
||||||
|
IN OUT MAP_ENTRYS *MapEntrys
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN MapsIndex;
|
||||||
|
|
||||||
|
if (MapEntrys->Count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MapsIndex = MapEntrys->Count - 1;
|
||||||
|
ZeroMem (&(MapEntrys->Maps[MapsIndex]), sizeof (MAP_ENTRY));
|
||||||
|
MapEntrys->Count = MapsIndex;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Generate single random map entry.
|
Generate single random map entry.
|
||||||
The map entry can be the input of function PageTableMap
|
The map entry can be the input of function PageTableMap
|
||||||
@ -327,7 +348,16 @@ GenerateSingleRandomMapEntry (
|
|||||||
MapEntrys->Maps[MapsIndex].Mask.Uint64 = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].Mask.Uint64;
|
MapEntrys->Maps[MapsIndex].Mask.Uint64 = MapEntrys->Maps[Random32 (0, (UINT32)MapsIndex-1)].Mask.Uint64;
|
||||||
} else {
|
} else {
|
||||||
MapEntrys->Maps[MapsIndex].Attribute.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64;
|
MapEntrys->Maps[MapsIndex].Attribute.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64;
|
||||||
MapEntrys->Maps[MapsIndex].Mask.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64;
|
if (RandomBoolean (5)) {
|
||||||
|
//
|
||||||
|
// The probability to get random Mask should be small since all bits of a random number
|
||||||
|
// have a high probability of containing 0, which may be a invalid input.
|
||||||
|
//
|
||||||
|
MapEntrys->Maps[MapsIndex].Mask.Uint64 = Random64 (0, MAX_UINT64) & mSupportedBit.Uint64;
|
||||||
|
} else {
|
||||||
|
MapEntrys->Maps[MapsIndex].Mask.Uint64 = MAX_UINT64;
|
||||||
|
}
|
||||||
|
|
||||||
if (MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey != 0) {
|
if (MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey != 0) {
|
||||||
MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey = 0xF;
|
MapEntrys->Maps[MapsIndex].Mask.Bits.ProtectionKey = 0xF;
|
||||||
}
|
}
|
||||||
@ -337,15 +367,7 @@ GenerateSingleRandomMapEntry (
|
|||||||
MapEntrys->Maps[MapsIndex].Attribute.Bits.PageTableBaseAddress = MapEntrys->Maps[MapsIndex].LinearAddress >> 12;
|
MapEntrys->Maps[MapsIndex].Attribute.Bits.PageTableBaseAddress = MapEntrys->Maps[MapsIndex].LinearAddress >> 12;
|
||||||
MapEntrys->Maps[MapsIndex].Mask.Bits.PageTableBaseAddress = 0xFFFFFFFFFF;
|
MapEntrys->Maps[MapsIndex].Mask.Bits.PageTableBaseAddress = 0xFFFFFFFFFF;
|
||||||
} else {
|
} else {
|
||||||
//
|
|
||||||
// Todo: If the mask bit for base address is zero, when dump the pagetable, every entry mapping to physical address zeor.
|
|
||||||
// This means the map count will be a large number, and impossible to finish in proper time.
|
|
||||||
// Need to avoid such case when remove the Random option ONLY_ONE_ONE_MAPPING
|
|
||||||
//
|
|
||||||
MapEntrys->Maps[MapsIndex].Attribute.Bits.PageTableBaseAddress = (Random64 (0, (((UINT64)1)<<52) - 1) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)])>> 12;
|
MapEntrys->Maps[MapsIndex].Attribute.Bits.PageTableBaseAddress = (Random64 (0, (((UINT64)1)<<52) - 1) & AlignedTable[Random32 (0, ARRAY_SIZE (AlignedTable) -1)])>> 12;
|
||||||
if (RandomBoolean (50)) {
|
|
||||||
MapEntrys->Maps[MapsIndex].Mask.Bits.PageTableBaseAddress = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MapEntrys->Count += 1;
|
MapEntrys->Count += 1;
|
||||||
@ -608,25 +630,65 @@ SingleMapEntryTest (
|
|||||||
IN UINTN InitMapCount
|
IN UINTN InitMapCount
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINTN MapsIndex;
|
UINTN MapsIndex;
|
||||||
RETURN_STATUS Status;
|
RETURN_STATUS Status;
|
||||||
UINTN PageTableBufferSize;
|
UINTN PageTableBufferSize;
|
||||||
VOID *Buffer;
|
VOID *Buffer;
|
||||||
IA32_MAP_ENTRY *Map;
|
IA32_MAP_ENTRY *Map;
|
||||||
UINTN MapCount;
|
UINTN MapCount;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
UINTN KeyPointCount;
|
UINTN KeyPointCount;
|
||||||
UINTN NewKeyPointCount;
|
UINTN NewKeyPointCount;
|
||||||
UINT64 *KeyPointBuffer;
|
UINT64 *KeyPointBuffer;
|
||||||
UINTN Level;
|
UINTN Level;
|
||||||
UINT64 Value;
|
UINT64 Value;
|
||||||
UNIT_TEST_STATUS TestStatus;
|
UNIT_TEST_STATUS TestStatus;
|
||||||
MAP_ENTRY *LastMapEntry;
|
MAP_ENTRY *LastMapEntry;
|
||||||
|
IA32_MAP_ATTRIBUTE *Mask;
|
||||||
|
IA32_MAP_ATTRIBUTE *Attribute;
|
||||||
|
UINT64 LastNotPresentRegionStart;
|
||||||
|
BOOLEAN IsNotPresent;
|
||||||
|
|
||||||
MapsIndex = MapEntrys->Count;
|
MapsIndex = MapEntrys->Count;
|
||||||
|
MapCount = 0;
|
||||||
|
LastNotPresentRegionStart = 0;
|
||||||
|
IsNotPresent = FALSE;
|
||||||
|
|
||||||
GenerateSingleRandomMapEntry (MaxAddress, MapEntrys);
|
GenerateSingleRandomMapEntry (MaxAddress, MapEntrys);
|
||||||
LastMapEntry = &MapEntrys->Maps[MapsIndex];
|
LastMapEntry = &MapEntrys->Maps[MapsIndex];
|
||||||
|
Status = PageTableParse (*PageTable, PagingMode, NULL, &MapCount);
|
||||||
|
|
||||||
|
if (MapCount != 0) {
|
||||||
|
UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);
|
||||||
|
Map = AllocatePages (EFI_SIZE_TO_PAGES (MapCount * sizeof (IA32_MAP_ENTRY)));
|
||||||
|
ASSERT (Map != NULL);
|
||||||
|
Status = PageTableParse (*PageTable, PagingMode, Map, &MapCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check if the generated MapEntrys->Maps[MapsIndex] contains not-present range.
|
||||||
|
//
|
||||||
|
if (LastMapEntry->Length > 0) {
|
||||||
|
for (Index = 0; Index < MapCount; Index++) {
|
||||||
|
if ((LastNotPresentRegionStart < Map[Index].LinearAddress) &&
|
||||||
|
(LastMapEntry->LinearAddress < Map[Index].LinearAddress) && (LastMapEntry->LinearAddress + LastMapEntry->Length > LastNotPresentRegionStart))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// MapEntrys->Maps[MapsIndex] contains not-present range in exsiting page table.
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LastNotPresentRegionStart = Map[Index].LinearAddress + Map[Index].Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Either LastMapEntry overlaps with the not-present region in the very end
|
||||||
|
// Or it overlaps with one in the middle
|
||||||
|
if (LastNotPresentRegionStart < LastMapEntry->LinearAddress + LastMapEntry->Length) {
|
||||||
|
IsNotPresent = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PageTableBufferSize = 0;
|
PageTableBufferSize = 0;
|
||||||
Status = PageTableMap (
|
Status = PageTableMap (
|
||||||
@ -639,6 +701,47 @@ SingleMapEntryTest (
|
|||||||
&LastMapEntry->Attribute,
|
&LastMapEntry->Attribute,
|
||||||
&LastMapEntry->Mask
|
&LastMapEntry->Mask
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Attribute = &LastMapEntry->Attribute;
|
||||||
|
Mask = &LastMapEntry->Mask;
|
||||||
|
//
|
||||||
|
// If set [LinearAddress, LinearAddress+Attribute] to not preset, all
|
||||||
|
// other attributes should not be provided.
|
||||||
|
//
|
||||||
|
if ((LastMapEntry->Length > 0) && (Attribute->Bits.Present == 0) && (Mask->Bits.Present == 1) && (Mask->Uint64 > 1)) {
|
||||||
|
RemoveLastMapEntry (MapEntrys);
|
||||||
|
UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER);
|
||||||
|
return UNIT_TEST_PASSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Return Status for non-present range also should be InvalidParameter when:
|
||||||
|
// 1. Some of attributes are not provided when mapping non-present range to present.
|
||||||
|
// 2. Set any other attribute without setting the non-present range to Present.
|
||||||
|
//
|
||||||
|
if (IsNotPresent) {
|
||||||
|
if ((Mask->Bits.Present == 1) && (Attribute->Bits.Present == 1)) {
|
||||||
|
//
|
||||||
|
// Creating new page table or remapping non-present range to present.
|
||||||
|
//
|
||||||
|
if ((Mask->Bits.ReadWrite == 0) || (Mask->Bits.UserSupervisor == 0) || (Mask->Bits.WriteThrough == 0) || (Mask->Bits.CacheDisabled == 0) ||
|
||||||
|
(Mask->Bits.Accessed == 0) || (Mask->Bits.Dirty == 0) || (Mask->Bits.Pat == 0) || (Mask->Bits.Global == 0) ||
|
||||||
|
(Mask->Bits.PageTableBaseAddress == 0) || (Mask->Bits.ProtectionKey == 0) || (Mask->Bits.Nx == 0))
|
||||||
|
{
|
||||||
|
RemoveLastMapEntry (MapEntrys);
|
||||||
|
UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER);
|
||||||
|
return UNIT_TEST_PASSED;
|
||||||
|
}
|
||||||
|
} else if ((Mask->Bits.Present == 0) && (Mask->Uint64 > 1)) {
|
||||||
|
//
|
||||||
|
// Only change other attributes for non-present range is not permitted.
|
||||||
|
//
|
||||||
|
RemoveLastMapEntry (MapEntrys);
|
||||||
|
UT_ASSERT_EQUAL (Status, RETURN_INVALID_PARAMETER);
|
||||||
|
return UNIT_TEST_PASSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (PageTableBufferSize != 0) {
|
if (PageTableBufferSize != 0) {
|
||||||
UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);
|
UT_ASSERT_EQUAL (Status, RETURN_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
helper file for Unit tests of the CpuPageTableLib instance of the CpuPageTableLib class
|
helper file for Unit tests of the CpuPageTableLib instance of the CpuPageTableLib class
|
||||||
|
|
||||||
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR>
|
||||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
**/
|
**/
|
||||||
@ -171,6 +171,10 @@ IsPageTableValid (
|
|||||||
UNIT_TEST_STATUS Status;
|
UNIT_TEST_STATUS Status;
|
||||||
IA32_PAGING_ENTRY *PagingEntry;
|
IA32_PAGING_ENTRY *PagingEntry;
|
||||||
|
|
||||||
|
if (PageTable == 0) {
|
||||||
|
return UNIT_TEST_PASSED;
|
||||||
|
}
|
||||||
|
|
||||||
if ((PagingMode == Paging32bit) || (PagingMode == PagingPae) || (PagingMode >= PagingModeMax)) {
|
if ((PagingMode == Paging32bit) || (PagingMode == PagingPae) || (PagingMode >= PagingModeMax)) {
|
||||||
//
|
//
|
||||||
// 32bit paging is never supported.
|
// 32bit paging is never supported.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user