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.88, mailfrom: hao.a.wu@intel.com) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by groups.io with SMTP; Mon, 22 Jul 2019 19:05:43 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 22 Jul 2019 19:05:43 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,297,1559545200"; d="scan'208";a="177158302" Received: from fmsmsx103.amr.corp.intel.com ([10.18.124.201]) by FMSMGA003.fm.intel.com with ESMTP; 22 Jul 2019 19:05:43 -0700 Received: from fmsmsx117.amr.corp.intel.com (10.18.116.17) by FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS) id 14.3.439.0; Mon, 22 Jul 2019 19:05:42 -0700 Received: from shsmsx152.ccr.corp.intel.com (10.239.6.52) by fmsmsx117.amr.corp.intel.com (10.18.116.17) with Microsoft SMTP Server (TLS) id 14.3.439.0; Mon, 22 Jul 2019 19:05:42 -0700 Received: from shsmsx104.ccr.corp.intel.com ([169.254.5.110]) by SHSMSX152.ccr.corp.intel.com ([169.254.6.22]) with mapi id 14.03.0439.000; Tue, 23 Jul 2019 10:05:40 +0800 From: "Wu, Hao A" To: "devel@edk2.groups.io" , "Ni, Ray" CC: "Dong, Eric" , Laszlo Ersek Subject: Re: [edk2-devel] [PATCH 4/4] MdeModulePkg/DxeIpl: Create 5-level page table for long mode Thread-Topic: [edk2-devel] [PATCH 4/4] MdeModulePkg/DxeIpl: Create 5-level page table for long mode Thread-Index: AQHVQGXQcbYWoDCQaUekb4lsAe3OuKbXcxlQ Date: Tue, 23 Jul 2019 02:05:39 +0000 Message-ID: References: <20190722081547.56100-1-ray.ni@intel.com> <20190722081547.56100-5-ray.ni@intel.com> In-Reply-To: <20190722081547.56100-5-ray.ni@intel.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Return-Path: hao.a.wu@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable > -----Original Message----- > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Ni= , > Ray > Sent: Monday, July 22, 2019 4:16 PM > To: devel@edk2.groups.io > Cc: Dong, Eric; Laszlo Ersek > Subject: [edk2-devel] [PATCH 4/4] 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 in 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 > running 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 > --- > MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 1 + > .../Core/DxeIplPeim/X64/VirtualMemory.c | 227 ++++++++++++------ > 2 files changed, 151 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..a5bcdcc734 100644 > --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c > +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c > @@ -15,7 +15,7 @@ > 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 > @@ -626,14 +626,19 @@ CreateIdentityMappingPageTables ( > ) > { > UINT32 RegEax; > + UINT32 RegEbx; > + UINT32 RegEcx; > UINT32 RegEdx; > UINT8 PhysicalAddressBits; > EFI_PHYSICAL_ADDRESS PageAddress; > + UINTN IndexOfPml5Entries; > UINTN IndexOfPml4Entries; > UINTN IndexOfPdpEntries; > UINTN IndexOfPageDirectoryEnt= ries; > + UINT32 NumberOfPml5EntriesNeed= ed; > UINT32 NumberOfPml4EntriesNeed= ed; > UINT32 NumberOfPdpEntriesNeede= d; > + 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 addres= s > field > @@ -677,33 +684,66 @@ CreateIdentityMappingPageTables ( > } > } >=20 > + Page5LevelSupport =3D FALSE; > + if (PcdGetBool (PcdUse5LevelPageTable)) { > + AsmCpuidEx (0x7, 0, &RegEax, &RegEbx, &RegEcx, &RegEdx); > + DEBUG ((DEBUG_INFO, "Cpuid(7/0): %08x/%08x/%08x/%08x\n", RegEax, > RegEbx, RegEcx, RegEdx)); > + if ((RegEcx & BIT16) !=3D 0) { > + Page5LevelSupport =3D TRUE; > + } > + } > + > + DEBUG ((DEBUG_INFO, "AddressBits/5LevelPaging/1GPage > =3D %d/%d/%d\n", PhysicalAddressBits, Page5LevelSupport, Page1GSupport))= ; > + > // > - // IA-32e paging translates 48-bit linear addresses to 52-bit physica= l > addresses. > + // IA-32e paging translates 48-bit linear addresses to 52-bit physica= l > 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; > } >=20 > + NumberOfPml4EntriesNeeded =3D 1; > + if (PhysicalAddressBits > 39) { > + NumberOfPml4EntriesNeeded =3D (UINT32) LShiftU64 (1, > PhysicalAddressBits - 39); > + PhysicalAddressBits =3D 39; > + } > + > + NumberOfPdpEntriesNeeded =3D 1; > + ASSERT (PhysicalAddressBits > 30); > + NumberOfPdpEntriesNeeded =3D (UINT32) LShiftU64 (1, PhysicalAddressBi= ts > - 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 = is > disabled. > + // > + if (!Page5LevelSupport) { > + TotalPagesNum--; > } > + > + DEBUG ((DEBUG_INFO, "Pml5/Pml4/Pdp/TotalPage =3D %d/%d/%d/%d\n", > + NumberOfPml5EntriesNeeded, NumberOfPml4EntriesNeeded, > + NumberOfPdpEntriesNeeded, TotalPagesNum)); > + > BigPageAddress =3D (UINTN) AllocatePageTableMemory (TotalPagesNum); > ASSERT (BigPageAddress !=3D 0); >=20 > @@ -711,92 +751,125 @@ CreateIdentityMappingPageTables ( > // By architecture only one PageMapLevel4 exists - so lets allocate s= torage > 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 entir= es. > - // So lets allocate space for them and fill them in in the IndexOfP= dpEntries > 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 o= nce. > // > - 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) PageMapLevel4Entr= y; Hello, Do we need to bitwise-or with 'AddressEncMask' here? Best Regards, Hao Wu > + PageMapLevel5Entry->Bits.ReadWrite =3D 1; > + PageMapLevel5Entry->Bits.Present =3D 1; > + } >=20 > - for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntri= es < 512; > IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress +=3D > SIZE_1GB) { > - if (ToSplitPageTable (PageAddress, SIZE_1GB, StackBase, StackSi= ze)) { > - 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 Dire= ctory > 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 ent= ires. > + // 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; IndexOfPageDirectoryEnt= ries < > 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += =3D > SIZE_2MB) { > - if (ToSplitPageTable (PageAddress, SIZE_2MB, StackBase, Stack= Size)) { > - // > - // Need to split this 2M page that covers NULL or stack ran= ge. > - // > - Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry= , > StackBase, StackSize); > + if (Page1GSupport) { > + PageDirectory1GEntry =3D (VOID *) PageDirectoryPointerEntry; > + > + for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEnt= ries < > 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress > +=3D SIZE_1GB) { > + if (ToSplitPageTable (PageAddress, SIZE_1GB, StackBase, Stack= Size)) { > + Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEnt= ry, > 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 Di= rectory > 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; IndexOfPageDirectoryE= ntries < > 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += =3D > SIZE_2MB) { > + if (ToSplitPageTable (PageAddress, SIZE_2MB, StackBase, Sta= ckSize)) { > + // > + // Need to split this 2M page that covers NULL or stack r= ange. > + // > + Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEnt= ry, > 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 >=20 >=20 >=20