From 353f5ba92f9420266bbf5dd86c3faae35db6a478 Mon Sep 17 00:00:00 2001 From: Star Zeng Date: Mon, 27 Jul 2015 03:04:03 +0000 Subject: IntelFrameworkModulePkg AcpiS3SaveDxe: Reduce reserved memory consumption Reduce reserved memory consumption by page table buffer, then OS can have more available memory to use. Take PhysicalAddressBits = 48 and 2MB page granularity as example, 1:1 Virtual to Physical identity mapping page table buffer needs to be ((512 + 1) * 512 + 1) * 4096 = 1075843072 bytes = 0x40201000 bytes. When BIOS does not support long mode waking vector, only allocate 2 pages (1G page enabled) or 6 pages for 4G page table, and 8 extra pages to handles > 4G request by page fault. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng Reviewed-by: Jiewen Yao git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18068 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c | 193 +++++++++++++-------- .../Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf | 5 +- 2 files changed, 124 insertions(+), 74 deletions(-) diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c index 6de1871f67..177a73bc78 100644 --- a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c +++ b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c @@ -2,7 +2,7 @@ This is an implementation of the ACPI S3 Save protocol. This is defined in S3 boot path specification 0.9. -Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions @@ -32,6 +32,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "AcpiS3Save.h" +// +// 8 extra pages for PF handler. +// +#define EXTRA_PAGE_TABLE_PAGES 8 + /** Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save. **/ @@ -303,21 +308,61 @@ FindAcpiFacsTable ( } /** - Allocates and fills in the Page Directory and Page Table Entries to - establish a 1:1 Virtual to Physical mapping. + The function will check if long mode waking vector is supported. + + @param[in] Facs Pointer to FACS table. + + @retval TRUE Long mode waking vector is supported. + @retval FALSE Long mode waking vector is not supported. + +**/ +BOOLEAN +IsLongModeWakingVectorSupport ( + IN EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs + ) +{ + if ((Facs == NULL) || + (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ) { + // + // Something wrong with FACS. + // + return FALSE; + } + if (Facs->XFirmwareWakingVector != 0) { + if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) && + ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0)) { + // + // BIOS supports 64bit waking vector. + // + if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { + return TRUE; + } + } + } + return FALSE; +} + +/** + Allocates page table buffer. + + @param[in] LongModeWakingVectorSupport Support long mode waking vector or not. + If BootScriptExector driver will run in 64-bit mode, this function will establish the 1:1 - virtual to physical mapping page table. + virtual to physical mapping page table when long mode waking vector is supported, otherwise + create 4G page table when long mode waking vector is not supported and let PF handler to + handle > 4G request. If BootScriptExector driver will not run in 64-bit mode, this function will do nothing. - @return the 1:1 Virtual to Physical identity mapping page table base address. + @return Page table base address. **/ EFI_PHYSICAL_ADDRESS -S3CreateIdentityMappingPageTables ( - VOID +S3AllocatePageTablesBuffer ( + IN BOOLEAN LongModeWakingVectorSupport ) { if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { + UINTN ExtraPageTablePages; UINT32 RegEax; UINT32 RegEdx; UINT8 PhysicalAddressBits; @@ -328,74 +373,80 @@ S3CreateIdentityMappingPageTables ( VOID *Hob; BOOLEAN Page1GSupport; - S3NvsPageTableAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdIdentifyMappingPageTablePtr); - if (S3NvsPageTableAddress != 0x0) { - return S3NvsPageTableAddress; - } else { - Page1GSupport = FALSE; - if (PcdGetBool(PcdUse1GPageTable)) { - AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); - if (RegEax >= 0x80000001) { - AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); - if ((RegEdx & BIT26) != 0) { - Page1GSupport = TRUE; - } + Page1GSupport = FALSE; + if (PcdGetBool(PcdUse1GPageTable)) { + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000001) { + AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); + if ((RegEdx & BIT26) != 0) { + Page1GSupport = TRUE; } } - - // - // Get physical address bits supported. - // - Hob = GetFirstHob (EFI_HOB_TYPE_CPU); - if (Hob != NULL) { - PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; - } else { - AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); - if (RegEax >= 0x80000008) { - AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); - PhysicalAddressBits = (UINT8) RegEax; - } else { - PhysicalAddressBits = 36; - } - } - - // - // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses. - // - ASSERT (PhysicalAddressBits <= 52); - if (PhysicalAddressBits > 48) { - PhysicalAddressBits = 48; - } - - // - // Calculate the table entries needed. - // - if (PhysicalAddressBits <= 39 ) { - NumberOfPml4EntriesNeeded = 1; - NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30)); - } else { - NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39)); - NumberOfPdpEntriesNeeded = 512; - } - - // - // We need calculate whole page size then allocate once, because S3 restore page table does not know each page in Nvs. - // - if (!Page1GSupport) { - TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded); + } + + // + // Get physical address bits supported. + // + Hob = GetFirstHob (EFI_HOB_TYPE_CPU); + if (Hob != NULL) { + PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; + } else { + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + PhysicalAddressBits = (UINT8) RegEax; } else { - TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded); + PhysicalAddressBits = 36; } - DEBUG ((EFI_D_ERROR, "TotalPageTableSize - %x pages\n", TotalPageTableSize)); - + } + + // + // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses. + // + ASSERT (PhysicalAddressBits <= 52); + if (PhysicalAddressBits > 48) { + PhysicalAddressBits = 48; + } + + ExtraPageTablePages = 0; + if (!LongModeWakingVectorSupport) { // - // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. + // Create 4G page table when BIOS does not support long mode waking vector, + // and let PF handler to handle > 4G request. // - S3NvsPageTableAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, EFI_PAGES_TO_SIZE(TotalPageTableSize)); - ASSERT (S3NvsPageTableAddress != 0); - PcdSet64 (PcdIdentifyMappingPageTablePtr, S3NvsPageTableAddress); - return S3NvsPageTableAddress; + PhysicalAddressBits = 32; + ExtraPageTablePages = EXTRA_PAGE_TABLE_PAGES; + } + + // + // Calculate the table entries needed. + // + if (PhysicalAddressBits <= 39 ) { + NumberOfPml4EntriesNeeded = 1; + NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30)); + } else { + NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39)); + NumberOfPdpEntriesNeeded = 512; } + + // + // We need calculate whole page size then allocate once, because S3 restore page table does not know each page in Nvs. + // + if (!Page1GSupport) { + TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded); + } else { + TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded); + } + + TotalPageTableSize += ExtraPageTablePages; + DEBUG ((EFI_D_ERROR, "AcpiS3Save TotalPageTableSize - 0x%x pages\n", TotalPageTableSize)); + + // + // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. + // + S3NvsPageTableAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateMemoryBelow4G (EfiReservedMemoryType, EFI_PAGES_TO_SIZE(TotalPageTableSize)); + ASSERT (S3NvsPageTableAddress != 0); + return S3NvsPageTableAddress; } else { // // If DXE is running 32-bit mode, no need to establish page table. @@ -457,6 +508,7 @@ S3Ready ( STATIC BOOLEAN AlreadyEntered; IA32_DESCRIPTOR *Idtr; IA32_IDT_GATE_DESCRIPTOR *IdtGate; + EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; DEBUG ((EFI_D_INFO, "S3Ready!\n")); @@ -476,7 +528,8 @@ S3Ready ( // // Get ACPI Table because we will save its position to variable // - AcpiS3Context->AcpiFacsTable = (EFI_PHYSICAL_ADDRESS)(UINTN)FindAcpiFacsTable (); + Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) FindAcpiFacsTable (); + AcpiS3Context->AcpiFacsTable = (EFI_PHYSICAL_ADDRESS) (UINTN) Facs; ASSERT (AcpiS3Context->AcpiFacsTable != 0); IdtGate = AllocateMemoryBelow4G (EfiReservedMemoryType, sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 + sizeof(IA32_DESCRIPTOR)); @@ -498,7 +551,7 @@ S3Ready ( // // Allocate page table // - AcpiS3Context->S3NvsPageTableAddress = S3CreateIdentityMappingPageTables (); + AcpiS3Context->S3NvsPageTableAddress = S3AllocatePageTablesBuffer (IsLongModeWakingVectorSupport (Facs)); // // Allocate stack diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf index c5dec0546a..366eb147b7 100644 --- a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf +++ b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf @@ -1,7 +1,7 @@ ## @file # AcpiS3Save module installs ACPI S3 Save protocol to prepare S3 boot data. # -# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2015, 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 @@ -77,9 +77,6 @@ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize ## SOMETIMES_CONSUMES gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3BootScriptStackSize ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## CONSUMES - ## SOMETIMES_CONSUMES - ## SOMETIMES_PRODUCES - gEfiMdeModulePkgTokenSpaceGuid.PcdIdentifyMappingPageTablePtr [Depex] # -- cgit v1.2.3