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.151, mailfrom: eric.dong@intel.com) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by groups.io with SMTP; Thu, 01 Aug 2019 19:23:55 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 01 Aug 2019 19:23:54 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,336,1559545200"; d="scan'208";a="191759032" Received: from fmsmsx106.amr.corp.intel.com ([10.18.124.204]) by fmsmga001.fm.intel.com with ESMTP; 01 Aug 2019 19:23:54 -0700 Received: from fmsmsx154.amr.corp.intel.com (10.18.116.70) by FMSMSX106.amr.corp.intel.com (10.18.124.204) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 1 Aug 2019 19:23:54 -0700 Received: from shsmsx153.ccr.corp.intel.com (10.239.6.53) by FMSMSX154.amr.corp.intel.com (10.18.116.70) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 1 Aug 2019 19:23:53 -0700 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.19]) by SHSMSX153.ccr.corp.intel.com ([169.254.12.215]) with mapi id 14.03.0439.000; Fri, 2 Aug 2019 10:23:52 +0800 From: "Dong, Eric" To: "Ni, Ray" , "devel@edk2.groups.io" CC: Laszlo Ersek , "Wu, Hao A" , "Wang, Jian J" Subject: Re: [PATCH v4 6/8] MdeModulePkg/DxeIpl: Create 5-level page table for long mode Thread-Topic: [PATCH v4 6/8] MdeModulePkg/DxeIpl: Create 5-level page table for long mode Thread-Index: AQHVSE/PtB5NyvDq4E2DBFR8vP5bwqbnIepA Date: Fri, 2 Aug 2019 02:23:51 +0000 Message-ID: References: <20190801095831.274356-1-ray.ni@intel.com> <20190801095831.274356-7-ray.ni@intel.com> In-Reply-To: <20190801095831.274356-7-ray.ni@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Return-Path: eric.dong@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Eric Dong > -----Original Message----- > From: Ni, Ray > Sent: Thursday, August 1, 2019 5:58 PM > To: devel@edk2.groups.io > Cc: Dong, Eric ; Laszlo Ersek ; > Wu, Hao A ; Wang, Jian J > Subject: [PATCH v4 6/8] MdeModulePkg/DxeIpl: Create 5-level page table > for long mode >=20 > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2008 >=20 > DxeIpl is responsible to create page table for DXE phase running either i= n > long mode or in 32bit mode with certain protection mechanism enabled > (refer to ToBuildPageTable()). >=20 > The patch updates DxeIpl to create 5-level page table for DXE phase runni= ng > in long mode when PcdUse5LevelPageTable is TRUE and CPU supports 5- > level page table. >=20 > Signed-off-by: Ray Ni > Cc: Eric Dong > Cc: Laszlo Ersek > Cc: Hao A Wu > Cc: Jian J Wang > --- > MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 1 + > .../Core/DxeIplPeim/X64/VirtualMemory.c | 229 ++++++++++++------ > 2 files changed, 153 insertions(+), 77 deletions(-) >=20 > diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf > b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf > index abc3217b01..98bc17fc9d 100644 > --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf > +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf > @@ -110,6 +110,7 @@ [Pcd.IA32,Pcd.X64] >=20 > gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask > ## CONSUMES > gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask > ## CONSUMES > gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard = ## > CONSUMES > + gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable = ## > SOMETIMES_CONSUMES >=20 > [Pcd.IA32,Pcd.X64,Pcd.ARM,Pcd.AARCH64] > gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## > SOMETIMES_CONSUMES > diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c > b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c > index edc38e4525..fe95cd4683 100644 > --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c > +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c > @@ -15,13 +15,14 @@ > 2) IA-32 Intel(R) Architecture Software Developer's Manual Volume > 2:Instruction Set Reference, Intel > 3) IA-32 Intel(R) Architecture Software Developer's Manual Volume > 3:System Programmer's Guide, Intel >=20 > -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
> +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> Copyright (c) 2017, AMD Incorporated. All rights reserved.
>=20 > SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > **/ >=20 > +#include > #include "DxeIpl.h" > #include "VirtualMemory.h" >=20 > @@ -626,14 +627,18 @@ CreateIdentityMappingPageTables ( > ) > { > UINT32 RegEax; > + CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX EcxFlags; > UINT32 RegEdx; > UINT8 PhysicalAddressBits; > EFI_PHYSICAL_ADDRESS PageAddress; > + UINTN IndexOfPml5Entries; > UINTN IndexOfPml4Entries; > UINTN IndexOfPdpEntries; > UINTN IndexOfPageDirectoryEntr= ies; > + UINT32 NumberOfPml5EntriesNeede= d; > UINT32 NumberOfPml4EntriesNeede= d; > UINT32 NumberOfPdpEntriesNeeded= ; > + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel5Entry; > PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; > PAGE_MAP_AND_DIRECTORY_POINTER *PageMap; > PAGE_MAP_AND_DIRECTORY_POINTER > *PageDirectoryPointerEntry; > @@ -641,9 +646,11 @@ CreateIdentityMappingPageTables ( > UINTN TotalPagesNum; > UINTN BigPageAddress; > VOID *Hob; > + BOOLEAN Page5LevelSupport; > BOOLEAN Page1GSupport; > PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; > UINT64 AddressEncMask; > + IA32_CR4 Cr4; >=20 > // > // Make sure AddressEncMask is contained to smallest supported address > field @@ -677,33 +684,68 @@ CreateIdentityMappingPageTables ( > } > } >=20 > + Page5LevelSupport =3D FALSE; > + if (PcdGetBool (PcdUse5LevelPageTable)) { > + AsmCpuidEx ( > + CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, > CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, NULL, > + &EcxFlags.Uint32, NULL, NULL > + ); > + if (EcxFlags.Bits.FiveLevelPage !=3D 0) { > + Page5LevelSupport =3D TRUE; > + } > + } > + > + DEBUG ((DEBUG_INFO, "AddressBits=3D%u 5LevelPaging=3D%u > 1GPage=3D%u\n", > + PhysicalAddressBits, Page5LevelSupport, Page1GSupport)); > + > // > - // IA-32e paging translates 48-bit linear addresses to 52-bit physical > addresses. > + // IA-32e paging translates 48-bit linear addresses to 52-bit > + physical addresses // when 5-Level Paging is disabled, // due to > + either unsupported by HW, or disabled by PCD. > // > ASSERT (PhysicalAddressBits <=3D 52); > - if (PhysicalAddressBits > 48) { > + if (!Page5LevelSupport && PhysicalAddressBits > 48) { > PhysicalAddressBits =3D 48; > } >=20 > // > // Calculate the table entries needed. > // > - if (PhysicalAddressBits <=3D 39 ) { > - NumberOfPml4EntriesNeeded =3D 1; > - NumberOfPdpEntriesNeeded =3D (UINT32)LShiftU64 (1, > (PhysicalAddressBits - 30)); > - } else { > - NumberOfPml4EntriesNeeded =3D (UINT32)LShiftU64 (1, > (PhysicalAddressBits - 39)); > - NumberOfPdpEntriesNeeded =3D 512; > + NumberOfPml5EntriesNeeded =3D 1; > + if (PhysicalAddressBits > 48) { > + NumberOfPml5EntriesNeeded =3D (UINT32) LShiftU64 (1, > PhysicalAddressBits - 48); > + PhysicalAddressBits =3D 48; > + } > + > + NumberOfPml4EntriesNeeded =3D 1; > + if (PhysicalAddressBits > 39) { > + NumberOfPml4EntriesNeeded =3D (UINT32) LShiftU64 (1, > PhysicalAddressBits - 39); > + PhysicalAddressBits =3D 39; > } >=20 > + NumberOfPdpEntriesNeeded =3D 1; > + ASSERT (PhysicalAddressBits > 30); > + NumberOfPdpEntriesNeeded =3D (UINT32) LShiftU64 (1, PhysicalAddressBit= s > + - 30); > + > // > // Pre-allocate big pages to avoid later allocations. > // > if (!Page1GSupport) { > - TotalPagesNum =3D (NumberOfPdpEntriesNeeded + 1) * > NumberOfPml4EntriesNeeded + 1; > + TotalPagesNum =3D ((NumberOfPdpEntriesNeeded + 1) * > + NumberOfPml4EntriesNeeded + 1) * NumberOfPml5EntriesNeeded + 1; > } else { > - TotalPagesNum =3D NumberOfPml4EntriesNeeded + 1; > + TotalPagesNum =3D (NumberOfPml4EntriesNeeded + 1) * > + NumberOfPml5EntriesNeeded + 1; } > + > + // > + // Substract the one page occupied by PML5 entries if 5-Level Paging i= s > disabled. > + // > + if (!Page5LevelSupport) { > + TotalPagesNum--; > } > + > + DEBUG ((DEBUG_INFO, "Pml5=3D%u Pml4=3D%u Pdp=3D%u TotalPage=3D%u\n", > + NumberOfPml5EntriesNeeded, NumberOfPml4EntriesNeeded, > + NumberOfPdpEntriesNeeded, TotalPagesNum)); > + > BigPageAddress =3D (UINTN) AllocatePageTableMemory (TotalPagesNum); > ASSERT (BigPageAddress !=3D 0); >=20 > @@ -711,92 +753,125 @@ CreateIdentityMappingPageTables ( > // By architecture only one PageMapLevel4 exists - so lets allocate st= orage > for it. > // > PageMap =3D (VOID *) BigPageAddress; > - BigPageAddress +=3D SIZE_4KB; > - > - PageMapLevel4Entry =3D PageMap; > - PageAddress =3D 0; > - for (IndexOfPml4Entries =3D 0; IndexOfPml4Entries < > NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, > PageMapLevel4Entry++) { > + if (Page5LevelSupport) { > // > - // Each PML4 entry points to a page of Page Directory Pointer entire= s. > - // So lets allocate space for them and fill them in in the IndexOfPd= pEntries > loop. > + // By architecture only one PageMapLevel5 exists - so lets allocate = storage > for it. > // > - PageDirectoryPointerEntry =3D (VOID *) BigPageAddress; > - BigPageAddress +=3D SIZE_4KB; > + PageMapLevel5Entry =3D PageMap; > + BigPageAddress +=3D SIZE_4KB; > + } > + PageAddress =3D 0; >=20 > + for ( IndexOfPml5Entries =3D 0 > + ; IndexOfPml5Entries < NumberOfPml5EntriesNeeded > + ; IndexOfPml5Entries++, PageMapLevel5Entry++) { > // > - // Make a PML4 Entry > + // Each PML5 entry points to a page of PML4 entires. > + // So lets allocate space for them and fill them in in the > IndexOfPml4Entries loop. > + // When 5-Level Paging is disabled, below allocation happens only on= ce. > // > - PageMapLevel4Entry->Uint64 =3D > (UINT64)(UINTN)PageDirectoryPointerEntry | AddressEncMask; > - PageMapLevel4Entry->Bits.ReadWrite =3D 1; > - PageMapLevel4Entry->Bits.Present =3D 1; > + PageMapLevel4Entry =3D (VOID *) BigPageAddress; > + BigPageAddress +=3D SIZE_4KB; >=20 > - if (Page1GSupport) { > - PageDirectory1GEntry =3D (VOID *) PageDirectoryPointerEntry; > + if (Page5LevelSupport) { > + // > + // Make a PML5 Entry > + // > + PageMapLevel5Entry->Uint64 =3D (UINT64) (UINTN) PageMapLevel4Entry > | AddressEncMask; > + PageMapLevel5Entry->Bits.ReadWrite =3D 1; > + PageMapLevel5Entry->Bits.Present =3D 1; > + } >=20 > - for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntrie= s < 512; > IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress +=3D > SIZE_1GB) { > - if (ToSplitPageTable (PageAddress, SIZE_1GB, StackBase, StackSiz= e)) { > - Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, > StackBase, StackSize); > - } else { > - // > - // Fill in the Page Directory entries > - // > - PageDirectory1GEntry->Uint64 =3D (UINT64)PageAddress | > AddressEncMask; > - PageDirectory1GEntry->Bits.ReadWrite =3D 1; > - PageDirectory1GEntry->Bits.Present =3D 1; > - PageDirectory1GEntry->Bits.MustBe1 =3D 1; > - } > - } > - } else { > - for (IndexOfPdpEntries =3D 0; IndexOfPdpEntries < > NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, > PageDirectoryPointerEntry++) { > - // > - // Each Directory Pointer entries points to a page of Page Direc= tory > entires. > - // So allocate space for them and fill them in in the > IndexOfPageDirectoryEntries loop. > - // > - PageDirectoryEntry =3D (VOID *) BigPageAddress; > - BigPageAddress +=3D SIZE_4KB; > + for ( IndexOfPml4Entries =3D 0 > + ; IndexOfPml4Entries < (NumberOfPml5EntriesNeeded =3D=3D 1 ? > NumberOfPml4EntriesNeeded : 512) > + ; IndexOfPml4Entries++, PageMapLevel4Entry++) { > + // > + // Each PML4 entry points to a page of Page Directory Pointer enti= res. > + // So lets allocate space for them and fill them in in the > IndexOfPdpEntries loop. > + // > + PageDirectoryPointerEntry =3D (VOID *) BigPageAddress; > + BigPageAddress +=3D SIZE_4KB; >=20 > - // > - // Fill in a Page Directory Pointer Entries > - // > - PageDirectoryPointerEntry->Uint64 =3D > (UINT64)(UINTN)PageDirectoryEntry | AddressEncMask; > - PageDirectoryPointerEntry->Bits.ReadWrite =3D 1; > - PageDirectoryPointerEntry->Bits.Present =3D 1; > + // > + // Make a PML4 Entry > + // > + PageMapLevel4Entry->Uint64 =3D > (UINT64)(UINTN)PageDirectoryPointerEntry | AddressEncMask; > + PageMapLevel4Entry->Bits.ReadWrite =3D 1; > + PageMapLevel4Entry->Bits.Present =3D 1; >=20 > - for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntr= ies < > 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += =3D > SIZE_2MB) { > - if (ToSplitPageTable (PageAddress, SIZE_2MB, StackBase, StackS= ize)) { > - // > - // Need to split this 2M page that covers NULL or stack rang= e. > - // > - Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, > StackBase, StackSize); > + if (Page1GSupport) { > + PageDirectory1GEntry =3D (VOID *) PageDirectoryPointerEntry; > + > + for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntr= ies < > 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress > +=3D SIZE_1GB) { > + if (ToSplitPageTable (PageAddress, SIZE_1GB, StackBase, StackS= ize)) { > + Split1GPageTo2M (PageAddress, (UINT64 *) > + PageDirectory1GEntry, StackBase, StackSize); > } else { > // > // Fill in the Page Directory entries > // > - PageDirectoryEntry->Uint64 =3D (UINT64)PageAddress | > AddressEncMask; > - PageDirectoryEntry->Bits.ReadWrite =3D 1; > - PageDirectoryEntry->Bits.Present =3D 1; > - PageDirectoryEntry->Bits.MustBe1 =3D 1; > + PageDirectory1GEntry->Uint64 =3D (UINT64)PageAddress | > AddressEncMask; > + PageDirectory1GEntry->Bits.ReadWrite =3D 1; > + PageDirectory1GEntry->Bits.Present =3D 1; > + PageDirectory1GEntry->Bits.MustBe1 =3D 1; > } > } > - } > + } else { > + for ( IndexOfPdpEntries =3D 0 > + ; IndexOfPdpEntries < (NumberOfPml4EntriesNeeded =3D=3D 1 ? > NumberOfPdpEntriesNeeded : 512) > + ; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { > + // > + // Each Directory Pointer entries points to a page of Page Dir= ectory > entires. > + // So allocate space for them and fill them in in the > IndexOfPageDirectoryEntries loop. > + // > + PageDirectoryEntry =3D (VOID *) BigPageAddress; > + BigPageAddress +=3D SIZE_4KB; >=20 > - for (; IndexOfPdpEntries < 512; IndexOfPdpEntries++, > PageDirectoryPointerEntry++) { > - ZeroMem ( > - PageDirectoryPointerEntry, > - sizeof(PAGE_MAP_AND_DIRECTORY_POINTER) > - ); > + // > + // Fill in a Page Directory Pointer Entries > + // > + PageDirectoryPointerEntry->Uint64 =3D > (UINT64)(UINTN)PageDirectoryEntry | AddressEncMask; > + PageDirectoryPointerEntry->Bits.ReadWrite =3D 1; > + PageDirectoryPointerEntry->Bits.Present =3D 1; > + > + for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEn= tries < > 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += =3D > SIZE_2MB) { > + if (ToSplitPageTable (PageAddress, SIZE_2MB, StackBase, Stac= kSize)) { > + // > + // Need to split this 2M page that covers NULL or stack ra= nge. > + // > + Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntr= y, > StackBase, StackSize); > + } else { > + // > + // Fill in the Page Directory entries > + // > + PageDirectoryEntry->Uint64 =3D (UINT64)PageAddress | > AddressEncMask; > + PageDirectoryEntry->Bits.ReadWrite =3D 1; > + PageDirectoryEntry->Bits.Present =3D 1; > + PageDirectoryEntry->Bits.MustBe1 =3D 1; > + } > + } > + } > + > + // > + // Fill with null entry for unused PDPTE > + // > + ZeroMem (PageDirectoryPointerEntry, (512 - IndexOfPdpEntries) * > + sizeof(PAGE_MAP_AND_DIRECTORY_POINTER)); > } > } > + > + // > + // For the PML4 entries we are not using fill in a null entry. > + // > + ZeroMem (PageMapLevel4Entry, (512 - IndexOfPml4Entries) * sizeof > + (PAGE_MAP_AND_DIRECTORY_POINTER)); > } >=20 > - // > - // For the PML4 entries we are not using fill in a null entry. > - // > - for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, > PageMapLevel4Entry++) { > - ZeroMem ( > - PageMapLevel4Entry, > - sizeof (PAGE_MAP_AND_DIRECTORY_POINTER) > - ); > + if (Page5LevelSupport) { > + Cr4.UintN =3D AsmReadCr4 (); > + Cr4.Bits.LA57 =3D 1; > + AsmWriteCr4 (Cr4.UintN); > + // > + // For the PML5 entries we are not using fill in a null entry. > + // > + ZeroMem (PageMapLevel5Entry, (512 - IndexOfPml5Entries) * sizeof > + (PAGE_MAP_AND_DIRECTORY_POINTER)); > } >=20 > // > -- > 2.21.0.windows.1