From c56b65665de7a665e29107ee9c377c1e2e84d343 Mon Sep 17 00:00:00 2001 From: jyao1 Date: Tue, 13 Sep 2011 05:48:57 +0000 Subject: Use CPU_HOB to detect max address support from platform, and added 1G page table support. Sign-off-by: jyao1 Reviewed-by: li-elvin git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12332 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c | 102 +++++++++++++++------ .../Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h | 28 +++++- 2 files changed, 100 insertions(+), 30 deletions(-) (limited to 'IntelFrameworkModulePkg') diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c index 73074a2684..27e6939572 100644 --- a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c +++ b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.c @@ -20,6 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include #include #include @@ -201,46 +202,76 @@ S3CreateIdentityMappingPageTables ( { if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { UINT32 RegEax; + UINT32 RegEdx; UINT8 PhysicalAddressBits; EFI_PHYSICAL_ADDRESS PageAddress; UINTN IndexOfPml4Entries; UINTN IndexOfPdpEntries; UINTN IndexOfPageDirectoryEntries; - UINTN NumberOfPml4EntriesNeeded; - UINTN NumberOfPdpEntriesNeeded; + UINT32 NumberOfPml4EntriesNeeded; + UINT32 NumberOfPdpEntriesNeeded; PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; PAGE_MAP_AND_DIRECTORY_POINTER *PageMap; PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; PAGE_TABLE_ENTRY *PageDirectoryEntry; EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress; UINTN TotalPageTableSize; + VOID *Hob; + BOOLEAN Page1GSupport; + PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; + + Page1GSupport = FALSE; + 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. // - AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); - if (RegEax >= 0x80000008) { - AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); - PhysicalAddressBits = (UINT8) RegEax; + Hob = GetFirstHob (EFI_HOB_TYPE_CPU); + if (Hob != NULL) { + PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; } else { - PhysicalAddressBits = 36; + 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 = (UINTN)LShiftU64 (1, (PhysicalAddressBits - 30)); + NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30)); } else { - NumberOfPml4EntriesNeeded = (UINTN)LShiftU64 (1, (PhysicalAddressBits - 39)); + 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. // - TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded); + if (!Page1GSupport) { + TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded); + } else { + TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded); + } DEBUG ((EFI_D_ERROR, "TotalPageTableSize - %x pages\n", TotalPageTableSize)); // @@ -267,29 +298,44 @@ S3CreateIdentityMappingPageTables ( PageMapLevel4Entry->Bits.ReadWrite = 1; PageMapLevel4Entry->Bits.Present = 1; - for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { - // - // Each Directory Pointer entries points to a page of Page Directory entires. - // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop. - // - PageDirectoryEntry = (PAGE_TABLE_ENTRY *)(UINTN)S3NvsPageTableAddress; + if (Page1GSupport) { + PageDirectory1GEntry = (VOID *) S3NvsPageTableAddress; S3NvsPageTableAddress += SIZE_4KB; - // - // Fill in a Page Directory Pointer Entries - // - PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry; - PageDirectoryPointerEntry->Bits.ReadWrite = 1; - PageDirectoryPointerEntry->Bits.Present = 1; - - for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += 0x200000) { + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) { // // Fill in the Page Directory entries // - PageDirectoryEntry->Uint64 = (UINT64)PageAddress; - PageDirectoryEntry->Bits.ReadWrite = 1; - PageDirectoryEntry->Bits.Present = 1; - PageDirectoryEntry->Bits.MustBe1 = 1; + PageDirectory1GEntry->Uint64 = (UINT64)PageAddress; + PageDirectory1GEntry->Bits.ReadWrite = 1; + PageDirectory1GEntry->Bits.Present = 1; + PageDirectory1GEntry->Bits.MustBe1 = 1; + } + } else { + for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { + // + // Each Directory Pointer entries points to a page of Page Directory entires. + // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop. + // + PageDirectoryEntry = (PAGE_TABLE_ENTRY *)(UINTN)S3NvsPageTableAddress; + S3NvsPageTableAddress += SIZE_4KB; + + // + // Fill in a Page Directory Pointer Entries + // + PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry; + PageDirectoryPointerEntry->Bits.ReadWrite = 1; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 = (UINT64)PageAddress; + PageDirectoryEntry->Bits.ReadWrite = 1; + PageDirectoryEntry->Bits.Present = 1; + PageDirectoryEntry->Bits.MustBe1 = 1; + } } } } diff --git a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h index d9bbe932d8..c2e8b41650 100644 --- a/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h +++ b/IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3Save.h @@ -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 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions @@ -18,7 +18,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #ifndef _ACPI_S3_SAVE_H_ #define _ACPI_S3_SAVE_H_ -#pragma pack(push, 1) +#pragma pack(1) typedef union { struct { @@ -92,6 +92,30 @@ typedef union { UINT64 Uint64; } PAGE_TABLE_ENTRY; +// +// Page Table Entry 1GB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:17; // Must be zero; + UINT64 PageTableBaseAddress:22; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_1G_ENTRY; + #pragma pack() /** -- cgit v1.2.3