mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-28 16:14:04 +02:00
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 <star.zeng@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18068 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
c6368abcf0
commit
353f5ba92f
@ -2,7 +2,7 @@
|
|||||||
This is an implementation of the ACPI S3 Save protocol. This is defined in
|
This is an implementation of the ACPI S3 Save protocol. This is defined in
|
||||||
S3 boot path specification 0.9.
|
S3 boot path specification 0.9.
|
||||||
|
|
||||||
Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions
|
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"
|
#include "AcpiS3Save.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// 8 extra pages for PF handler.
|
||||||
|
//
|
||||||
|
#define EXTRA_PAGE_TABLE_PAGES 8
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save.
|
Hook point for AcpiVariableThunkPlatform for InstallAcpiS3Save.
|
||||||
**/
|
**/
|
||||||
@ -303,21 +308,61 @@ FindAcpiFacsTable (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Allocates and fills in the Page Directory and Page Table Entries to
|
The function will check if long mode waking vector is supported.
|
||||||
establish a 1:1 Virtual to Physical mapping.
|
|
||||||
|
@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
|
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.
|
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
|
EFI_PHYSICAL_ADDRESS
|
||||||
S3CreateIdentityMappingPageTables (
|
S3AllocatePageTablesBuffer (
|
||||||
VOID
|
IN BOOLEAN LongModeWakingVectorSupport
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
|
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
|
||||||
|
UINTN ExtraPageTablePages;
|
||||||
UINT32 RegEax;
|
UINT32 RegEax;
|
||||||
UINT32 RegEdx;
|
UINT32 RegEdx;
|
||||||
UINT8 PhysicalAddressBits;
|
UINT8 PhysicalAddressBits;
|
||||||
@ -328,74 +373,80 @@ S3CreateIdentityMappingPageTables (
|
|||||||
VOID *Hob;
|
VOID *Hob;
|
||||||
BOOLEAN Page1GSupport;
|
BOOLEAN Page1GSupport;
|
||||||
|
|
||||||
S3NvsPageTableAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdIdentifyMappingPageTablePtr);
|
Page1GSupport = FALSE;
|
||||||
if (S3NvsPageTableAddress != 0x0) {
|
if (PcdGetBool(PcdUse1GPageTable)) {
|
||||||
return S3NvsPageTableAddress;
|
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||||
} else {
|
if (RegEax >= 0x80000001) {
|
||||||
Page1GSupport = FALSE;
|
AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
|
||||||
if (PcdGetBool(PcdUse1GPageTable)) {
|
if ((RegEdx & BIT26) != 0) {
|
||||||
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
Page1GSupport = TRUE;
|
||||||
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);
|
|
||||||
} else {
|
|
||||||
TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded);
|
|
||||||
}
|
|
||||||
DEBUG ((EFI_D_ERROR, "TotalPageTableSize - %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);
|
|
||||||
PcdSet64 (PcdIdentifyMappingPageTablePtr, S3NvsPageTableAddress);
|
|
||||||
return S3NvsPageTableAddress;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtraPageTablePages = 0;
|
||||||
|
if (!LongModeWakingVectorSupport) {
|
||||||
|
//
|
||||||
|
// Create 4G page table when BIOS does not support long mode waking vector,
|
||||||
|
// and let PF handler to handle > 4G request.
|
||||||
|
//
|
||||||
|
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 {
|
} else {
|
||||||
//
|
//
|
||||||
// If DXE is running 32-bit mode, no need to establish page table.
|
// If DXE is running 32-bit mode, no need to establish page table.
|
||||||
@ -457,6 +508,7 @@ S3Ready (
|
|||||||
STATIC BOOLEAN AlreadyEntered;
|
STATIC BOOLEAN AlreadyEntered;
|
||||||
IA32_DESCRIPTOR *Idtr;
|
IA32_DESCRIPTOR *Idtr;
|
||||||
IA32_IDT_GATE_DESCRIPTOR *IdtGate;
|
IA32_IDT_GATE_DESCRIPTOR *IdtGate;
|
||||||
|
EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
|
||||||
|
|
||||||
DEBUG ((EFI_D_INFO, "S3Ready!\n"));
|
DEBUG ((EFI_D_INFO, "S3Ready!\n"));
|
||||||
|
|
||||||
@ -476,7 +528,8 @@ S3Ready (
|
|||||||
//
|
//
|
||||||
// Get ACPI Table because we will save its position to variable
|
// 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);
|
ASSERT (AcpiS3Context->AcpiFacsTable != 0);
|
||||||
|
|
||||||
IdtGate = AllocateMemoryBelow4G (EfiReservedMemoryType, sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 + sizeof(IA32_DESCRIPTOR));
|
IdtGate = AllocateMemoryBelow4G (EfiReservedMemoryType, sizeof(IA32_IDT_GATE_DESCRIPTOR) * 0x100 + sizeof(IA32_DESCRIPTOR));
|
||||||
@ -498,7 +551,7 @@ S3Ready (
|
|||||||
//
|
//
|
||||||
// Allocate page table
|
// Allocate page table
|
||||||
//
|
//
|
||||||
AcpiS3Context->S3NvsPageTableAddress = S3CreateIdentityMappingPageTables ();
|
AcpiS3Context->S3NvsPageTableAddress = S3AllocatePageTablesBuffer (IsLongModeWakingVectorSupport (Facs));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate stack
|
// Allocate stack
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
## @file
|
## @file
|
||||||
# AcpiS3Save module installs ACPI S3 Save protocol to prepare S3 boot data.
|
# AcpiS3Save module installs ACPI S3 Save protocol to prepare S3 boot data.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
#
|
#
|
||||||
# This program and the accompanying materials are
|
# This program and the accompanying materials are
|
||||||
# licensed and made available under the terms and conditions of the BSD License
|
# licensed and made available under the terms and conditions of the BSD License
|
||||||
@ -77,9 +77,6 @@
|
|||||||
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize ## SOMETIMES_CONSUMES
|
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize ## SOMETIMES_CONSUMES
|
||||||
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3BootScriptStackSize ## CONSUMES
|
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3BootScriptStackSize ## CONSUMES
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## CONSUMES
|
||||||
## SOMETIMES_CONSUMES
|
|
||||||
## SOMETIMES_PRODUCES
|
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdIdentifyMappingPageTablePtr
|
|
||||||
|
|
||||||
[Depex]
|
[Depex]
|
||||||
#
|
#
|
||||||
|
Loading…
x
Reference in New Issue
Block a user