diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c index 3a829854af..bee229f4c8 100644 --- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c +++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c @@ -768,6 +768,7 @@ UnsetGuardForMemory ( ) { EFI_PHYSICAL_ADDRESS GuardPage; + UINT64 GuardBitmap; if (NumberOfPages == 0) { return; @@ -776,16 +777,29 @@ UnsetGuardForMemory ( // // Head Guard must be one page before, if any. // + // MSB-> 1 0 <-LSB + // ------------------- + // Head Guard -> 0 1 -> Don't free Head Guard (shared Guard) + // Head Guard -> 0 0 -> Free Head Guard either (not shared Guard) + // 1 X -> Don't free first page (need a new Guard) + // (it'll be turned into a Guard page later) + // ------------------- + // Start -> -1 -2 + // GuardPage = Memory - EFI_PAGES_TO_SIZE (1); - if (IsHeadGuard (GuardPage)) { - if (!IsMemoryGuarded (GuardPage - EFI_PAGES_TO_SIZE (1))) { + GuardBitmap = GetGuardedMemoryBits (Memory - EFI_PAGES_TO_SIZE (2), 2); + if ((GuardBitmap & BIT1) == 0) { + // + // Head Guard exists. + // + if ((GuardBitmap & BIT0) == 0) { // // If the head Guard is not a tail Guard of adjacent memory block, // unset it. // UnsetGuardPage (GuardPage); } - } else if (IsMemoryGuarded (GuardPage)) { + } else { // // Pages before memory to free are still in Guard. It's a partial free // case. Turn first page of memory block to free into a new Guard. @@ -796,16 +810,29 @@ UnsetGuardForMemory ( // // Tail Guard must be the page after this memory block to free, if any. // + // MSB-> 1 0 <-LSB + // -------------------- + // 1 0 <- Tail Guard -> Don't free Tail Guard (shared Guard) + // 0 0 <- Tail Guard -> Free Tail Guard either (not shared Guard) + // X 1 -> Don't free last page (need a new Guard) + // (it'll be turned into a Guard page later) + // -------------------- + // +1 +0 <- End + // GuardPage = Memory + EFI_PAGES_TO_SIZE (NumberOfPages); - if (IsTailGuard (GuardPage)) { - if (!IsMemoryGuarded (GuardPage + EFI_PAGES_TO_SIZE (1))) { + GuardBitmap = GetGuardedMemoryBits (GuardPage, 2); + if ((GuardBitmap & BIT0) == 0) { + // + // Tail Guard exists. + // + if ((GuardBitmap & BIT1) == 0) { // // If the tail Guard is not a head Guard of adjacent memory block, // free it; otherwise, keep it. // UnsetGuardPage (GuardPage); } - } else if (IsMemoryGuarded (GuardPage)) { + } else { // // Pages after memory to free are still in Guard. It's a partial free // case. We need to keep one page to be a head Guard. @@ -895,6 +922,7 @@ AdjustMemoryF ( EFI_PHYSICAL_ADDRESS Start; EFI_PHYSICAL_ADDRESS MemoryToTest; UINTN PagesToFree; + UINT64 GuardBitmap; if (Memory == NULL || NumberOfPages == NULL || *NumberOfPages == 0) { return; @@ -906,9 +934,22 @@ AdjustMemoryF ( // // Head Guard must be one page before, if any. // - MemoryToTest = Start - EFI_PAGES_TO_SIZE (1); - if (IsHeadGuard (MemoryToTest)) { - if (!IsMemoryGuarded (MemoryToTest - EFI_PAGES_TO_SIZE (1))) { + // MSB-> 1 0 <-LSB + // ------------------- + // Head Guard -> 0 1 -> Don't free Head Guard (shared Guard) + // Head Guard -> 0 0 -> Free Head Guard either (not shared Guard) + // 1 X -> Don't free first page (need a new Guard) + // (it'll be turned into a Guard page later) + // ------------------- + // Start -> -1 -2 + // + MemoryToTest = Start - EFI_PAGES_TO_SIZE (2); + GuardBitmap = GetGuardedMemoryBits (MemoryToTest, 2); + if ((GuardBitmap & BIT1) == 0) { + // + // Head Guard exists. + // + if ((GuardBitmap & BIT0) == 0) { // // If the head Guard is not a tail Guard of adjacent memory block, // free it; otherwise, keep it. @@ -916,10 +957,10 @@ AdjustMemoryF ( Start -= EFI_PAGES_TO_SIZE (1); PagesToFree += 1; } - } else if (IsMemoryGuarded (MemoryToTest)) { + } else { // - // Pages before memory to free are still in Guard. It's a partial free - // case. We need to keep one page to be a tail Guard. + // No Head Guard, and pages before memory to free are still in Guard. It's a + // partial free case. We need to keep one page to be a tail Guard. // Start += EFI_PAGES_TO_SIZE (1); PagesToFree -= 1; @@ -928,19 +969,32 @@ AdjustMemoryF ( // // Tail Guard must be the page after this memory block to free, if any. // + // MSB-> 1 0 <-LSB + // -------------------- + // 1 0 <- Tail Guard -> Don't free Tail Guard (shared Guard) + // 0 0 <- Tail Guard -> Free Tail Guard either (not shared Guard) + // X 1 -> Don't free last page (need a new Guard) + // (it'll be turned into a Guard page later) + // -------------------- + // +1 +0 <- End + // MemoryToTest = Start + EFI_PAGES_TO_SIZE (PagesToFree); - if (IsTailGuard (MemoryToTest)) { - if (!IsMemoryGuarded (MemoryToTest + EFI_PAGES_TO_SIZE (1))) { + GuardBitmap = GetGuardedMemoryBits (MemoryToTest, 2); + if ((GuardBitmap & BIT0) == 0) { + // + // Tail Guard exists. + // + if ((GuardBitmap & BIT1) == 0) { // // If the tail Guard is not a head Guard of adjacent memory block, // free it; otherwise, keep it. // PagesToFree += 1; } - } else if (IsMemoryGuarded (MemoryToTest)) { + } else if (PagesToFree > 0) { // - // Pages after memory to free are still in Guard. It's a partial free - // case. We need to keep one page to be a head Guard. + // No Tail Guard, and pages after memory to free are still in Guard. It's a + // partial free case. We need to keep one page to be a head Guard. // PagesToFree -= 1; } @@ -1054,11 +1108,14 @@ CoreConvertPagesWithGuard ( { if (NewType == EfiConventionalMemory) { AdjustMemoryF (&Start, &NumberOfPages); + if (NumberOfPages == 0) { + return EFI_SUCCESS; + } } else { AdjustMemoryA (&Start, &NumberOfPages); } - return CoreConvertPages(Start, NumberOfPages, NewType); + return CoreConvertPages (Start, NumberOfPages, NewType); } /** diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h index bd7abd7c53..30ac0e678f 100644 --- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h +++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h @@ -158,8 +158,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // // Memory type to guard (matching the related PCD definition) // -#define GUARD_HEAP_TYPE_POOL BIT0 -#define GUARD_HEAP_TYPE_PAGE BIT1 +#define GUARD_HEAP_TYPE_PAGE BIT0 +#define GUARD_HEAP_TYPE_POOL BIT1 // // Debug message level diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c index 853606653c..db32d0f940 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -920,21 +920,22 @@ CoreConvertPagesEx ( UINT64 EndToClear; StartToClear = Start; - EndToClear = RangeEnd; + EndToClear = RangeEnd + 1; if (PcdGet8 (PcdHeapGuardPropertyMask) & (BIT1|BIT0)) { if (IsGuardPage(StartToClear)) { StartToClear += EFI_PAGE_SIZE; } - if (IsGuardPage (EndToClear)) { + if (IsGuardPage (EndToClear - 1)) { EndToClear -= EFI_PAGE_SIZE; } - ASSERT (EndToClear > StartToClear); } - DEBUG_CLEAR_MEMORY( - (VOID *)(UINTN)StartToClear, - (UINTN)(EndToClear - StartToClear + 1) - ); + if (EndToClear > StartToClear) { + DEBUG_CLEAR_MEMORY( + (VOID *)(UINTN)StartToClear, + (UINTN)(EndToClear - StartToClear) + ); + } } } diff --git a/MdeModulePkg/Core/Dxe/Mem/Pool.c b/MdeModulePkg/Core/Dxe/Mem/Pool.c index b82b51595c..7464d8773a 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Pool.c +++ b/MdeModulePkg/Core/Dxe/Mem/Pool.c @@ -642,7 +642,9 @@ CoreFreePoolPagesWithGuard ( NoPagesGuarded = NoPages; AdjustMemoryF (&Memory, &NoPages); - CoreFreePoolPagesI (PoolType, Memory, NoPages); + if (NoPages > 0) { + CoreFreePoolPagesI (PoolType, Memory, NoPages); + } UnsetGuardForMemory (MemoryGuarded, NoPagesGuarded); }