From 714c2603018a99a514c42c2b511c821f30ba9cdf Mon Sep 17 00:00:00 2001 From: Star Zeng Date: Thu, 24 Aug 2017 10:59:14 +0800 Subject: [PATCH] UefiCpuPkg/PiSmmCpuDxeSmm: Fix memory protection crash https://bugzilla.tianocore.org/show_bug.cgi?id=624 reports memory protection crash in PiSmmCpuDxeSmm, Ia32 build with RAM above 4GB (of which 2GB are placed in 64-bit address). It is because UEFI builds identity mapping page tables, >4G address is not supported at Ia32 build. This patch is to get the PhysicalAddressBits that is used to build in PageTbl.c(Ia32/X64), and use it to check whether the address is supported or not in ConvertMemoryPageAttributes(). With this patch, the debug messages will be like below. UefiMemory protection: 0x0 - 0x9F000 Success UefiMemory protection: 0x100000 - 0x807000 Success UefiMemory protection: 0x808000 - 0x810000 Success UefiMemory protection: 0x818000 - 0x820000 Success UefiMemory protection: 0x1510000 - 0x7B798000 Success UefiMemory protection: 0x7B79B000 - 0x7E538000 Success UefiMemory protection: 0x7E539000 - 0x7E545000 Success UefiMemory protection: 0x7E55A000 - 0x7E61F000 Success UefiMemory protection: 0x7E62B000 - 0x7F6AB000 Success UefiMemory protection: 0x7F703000 - 0x7F70B000 Success UefiMemory protection: 0x7F70F000 - 0x7F778000 Success UefiMemory protection: 0x100000000 - 0x180000000 Unsupported Cc: Jiewen Yao Cc: Laszlo Ersek Cc: Eric Dong Originally-suggested-by: Jiewen Yao Reported-by: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Star Zeng Reviewed-by: Jiewen Yao Tested-by: Laszlo Ersek --- UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c | 4 +++ UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h | 1 + .../PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 31 +++++++++++++++---- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c index 32ce5958c5..e88b42d733 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c @@ -16,6 +16,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "PiSmmCpuDxeSmm.h" +UINT8 mPhysicalAddressBits; + /** Create PageTable for SMM use. @@ -36,6 +38,8 @@ SmmInitPageTable ( // InitializeSpinLock (mPFLock); + mPhysicalAddressBits = 32; + if (FeaturePcdGet (PcdCpuSmmProfileEnable)) { // // Set own Page Fault entry instead of the default one, because SMM Profile diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h index dbce9ec520..1cf85c1481 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h @@ -419,6 +419,7 @@ extern SPIN_LOCK *mConfigSmmCodeAccessCheckLock; extern SPIN_LOCK *mMemoryMappedLock; extern EFI_SMRAM_DESCRIPTOR *mSmmCpuSmramRanges; extern UINTN mSmmCpuSmramRangeCount; +extern UINT8 mPhysicalAddressBits; // // Copy of the PcdPteMemoryEncryptionAddressOrMask diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c index a535389c26..3ad5256f1e 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c @@ -1,6 +1,6 @@ /** @file -Copyright (c) 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -380,6 +380,7 @@ ConvertMemoryPageAttributes ( PAGE_ATTRIBUTE SplitAttribute; RETURN_STATUS Status; BOOLEAN IsEntryModified; + EFI_PHYSICAL_ADDRESS MaximumSupportMemAddress; ASSERT (Attributes != 0); ASSERT ((Attributes & ~(EFI_MEMORY_RP | EFI_MEMORY_RO | EFI_MEMORY_XP)) == 0); @@ -391,6 +392,17 @@ ConvertMemoryPageAttributes ( return RETURN_INVALID_PARAMETER; } + MaximumSupportMemAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, mPhysicalAddressBits) - 1); + if (BaseAddress > MaximumSupportMemAddress) { + return RETURN_UNSUPPORTED; + } + if (Length > MaximumSupportMemAddress) { + return RETURN_UNSUPPORTED; + } + if ((Length != 0) && (BaseAddress > MaximumSupportMemAddress - (Length - 1))) { + return RETURN_UNSUPPORTED; + } + // DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - %016lx, %016lx, %02lx\n", IsSet, BaseAddress, Length, Attributes)); if (IsSplitted != NULL) { @@ -1037,6 +1049,7 @@ SetUefiMemMapAttributes ( VOID ) { + EFI_STATUS Status; EFI_MEMORY_DESCRIPTOR *MemoryMap; UINTN MemoryMapEntryCount; UINTN Index; @@ -1052,12 +1065,18 @@ SetUefiMemMapAttributes ( MemoryMap = mUefiMemoryMap; for (Index = 0; Index < MemoryMapEntryCount; Index++) { if (IsUefiPageNotPresent(MemoryMap)) { - DEBUG ((DEBUG_INFO, "UefiMemory protection: 0x%lx - 0x%lx\n", MemoryMap->PhysicalStart, MemoryMap->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages))); - SmmSetMemoryAttributes ( + Status = SmmSetMemoryAttributes ( + MemoryMap->PhysicalStart, + EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages), + EFI_MEMORY_RP + ); + DEBUG (( + DEBUG_INFO, + "UefiMemory protection: 0x%lx - 0x%lx %r\n", MemoryMap->PhysicalStart, - EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages), - EFI_MEMORY_RP - ); + MemoryMap->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages), + Status + )); } MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, mUefiDescriptorSize); } -- 2.39.2