From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 192.55.52.43, mailfrom: liming.gao@intel.com) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by groups.io with SMTP; Sat, 10 Aug 2019 07:10:32 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 10 Aug 2019 07:10:32 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,369,1559545200"; d="scan'208";a="199668214" Received: from lgao4-mobl1.ccr.corp.intel.com ([10.249.168.23]) by fmsmga004.fm.intel.com with ESMTP; 10 Aug 2019 07:10:31 -0700 From: "Liming Gao" To: devel@edk2.groups.io Cc: Mike Turner , Jian J Wang , Hao A Wu , Dandan Bi Subject: [Patch] MdeModulePkg DxeCore: Fix for missing MAT update Date: Sat, 10 Aug 2019 22:10:22 +0800 Message-Id: <20190810141022.18228-1-liming.gao@intel.com> X-Mailer: git-send-email 2.16.2.windows.1 From: Mike Turner The Fpdt driver (FirmwarePerformanceDxe) saves a memory address across reboots, and then does an AllocatePage for that memory address. If, on this boot, that memory comes from a Runtime memory bucket, the MAT table is not updated. This causes Windows to boot into Recovery. This patch blocks the memory manager from changing the page from a special bucket to a different memory type. Once the buckets are allocated, we freeze the memory ranges for the OS, and fragmenting the special buckets will cause errors resuming from hibernate. This patch is cherry pick from Project Mu: https://github.com/microsoft/mu_basecore/commit/a9be767d9be96af94016ebd391ea6f340920735a With the minor change, 1. Update commit message format to keep the message in 80 characters one line. 2. Remove // MU_CHANGE comments in source code. Cc: Jian J Wang Cc: Hao A Wu Cc: Dandan Bi Signed-off-by: Liming Gao --- MdeModulePkg/Core/Dxe/Mem/Page.c | 43 ++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c index bd9e116aa5..637518889d 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -1265,12 +1265,13 @@ CoreInternalAllocatePages ( IN BOOLEAN NeedGuard ) { - EFI_STATUS Status; - UINT64 Start; - UINT64 NumberOfBytes; - UINT64 End; - UINT64 MaxAddress; - UINTN Alignment; + EFI_STATUS Status; + UINT64 Start; + UINT64 NumberOfBytes; + UINT64 End; + UINT64 MaxAddress; + UINTN Alignment; + EFI_MEMORY_TYPE CheckType; if ((UINT32)Type >= MaxAllocateType) { return EFI_INVALID_PARAMETER; @@ -1321,6 +1322,7 @@ CoreInternalAllocatePages ( // if (Start + NumberOfBytes) rolls over 0 or // if Start is above MAX_ALLOC_ADDRESS or // if End is above MAX_ALLOC_ADDRESS, + // if Start..End overlaps any tracked MemoryTypeStatistics range // return EFI_NOT_FOUND. // if (Type == AllocateAddress) { @@ -1336,6 +1338,35 @@ CoreInternalAllocatePages ( (End > MaxAddress)) { return EFI_NOT_FOUND; } + + // Problem summary + + /* + A driver is allowed to call AllocatePages using an AllocateAddress type. This type of + AllocatePage request the exact physical address if it is not used. The existing code + will allow this request even in 'special' pages. The problem with this is that the + reason to have 'special' pages for OS hibernate/resume is defeated as memory is + fragmented. + */ + + for (CheckType = (EFI_MEMORY_TYPE) 0; CheckType < EfiMaxMemoryType; CheckType++) { + if (MemoryType != CheckType && + mMemoryTypeStatistics[CheckType].Special && + mMemoryTypeStatistics[CheckType].NumberOfPages > 0) { + if (Start >= mMemoryTypeStatistics[CheckType].BaseAddress && + Start <= mMemoryTypeStatistics[CheckType].MaximumAddress) { + return EFI_NOT_FOUND; + } + if (End >= mMemoryTypeStatistics[CheckType].BaseAddress && + End <= mMemoryTypeStatistics[CheckType].MaximumAddress) { + return EFI_NOT_FOUND; + } + if (Start < mMemoryTypeStatistics[CheckType].BaseAddress && + End > mMemoryTypeStatistics[CheckType].MaximumAddress) { + return EFI_NOT_FOUND; + } + } + } } if (Type == AllocateMaxAddress) { -- 2.13.0.windows.1