From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by mx.groups.io with SMTP id smtpd.web11.115.1686245022561638053 for ; Thu, 08 Jun 2023 10:23:42 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=pIcQOJc5; spf=pass (domain: kernel.org, ip: 139.178.84.217, mailfrom: ardb@kernel.org) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 0EC3964FBB; Thu, 8 Jun 2023 17:23:42 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 77525C4339C; Thu, 8 Jun 2023 17:23:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1686245021; bh=zO39EGH05Uh9v//KcYXsLQDhT7T0g7N4a7Z12i+B+fc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pIcQOJc5r6wSipV0HDBQzKklP7ymwoORZ6ctGRr49NpB35AmN2RVoAw/0u3OXT8CD jOpRtB2HsHzdFHZMd+NAoSAd8FCKWziS3Jhm4NYQ/b5SfpK/OjNJhrOfddBgvjauP5 yZYLnGRoTBrTXSuN5L1H+CCtCE32W+wR/S8K17V7GkDphZdQiNVilNUDEoXflLf5ml Gz/j1qUIG+mZ56wrF/tIzXMkY2lSAgvrwNUv67wDmS4MmVj8L5YM/nWmmhCooZKDoN zIPcnaDaRZG52Su7pxkvWoIgB8s+m/40RbX34GdAzS+G0vZ2WNWO8h7/UGJ2Uy3H0R ed5xdfzoL7o8A== From: "Ard Biesheuvel" To: devel@edk2.groups.io Cc: Ard Biesheuvel , Ray Ni , Jiewen Yao , Gerd Hoffmann , Taylor Beebe , Oliver Smith-Denny , Dandan Bi , Dun Tan , Liming Gao , "Kinney, Michael D" , Michael Kubacki , Eric Dong , Rahul Kumar , Kun Qin Subject: [PATCH 2/2] UefiCpuPkg/CpuMpPei X64: Reallocate page tables in permanent DRAM Date: Thu, 8 Jun 2023 19:23:23 +0200 Message-Id: <20230608172323.9096-3-ardb@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230608172323.9096-1-ardb@kernel.org> References: <20230608172323.9096-1-ardb@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Currently, we rely on the logic in DXE IPL to create new page tables from scratch when executing in X64 mode, which means that we run with the initial page tables all throughout PEI, and never enable protections such as the CPU stack guard, even though the logic is already in place for IA32. So let's enable the existing logic for X64 as well. This will permit us to apply stricter memory permissions to code and data allocations, as well as the stack, when executing in PEI. It also makes the DxeIpl logic redundant, and should allow us to make the PcdDxeIplBuildPageTables feature PCD limited to IA32 DxeIpl loading the x64 DXE core. When running in long mode, use the same logic that DxeIpl uses to determine the size of the address space, whether or not to use 1 GB leaf entries and whether or not to use 5 level paging. Note that in long mode, PEI is entered with paging enabled, and given that switching between 4 and 5 levels of paging is not currently supported without dropping out of 64-bit mode temporarily, all we can do is carry on without changing the number of levels. Signed-off-by: Ard Biesheuvel --- UefiCpuPkg/CpuMpPei/CpuMpPei.inf | 2 + UefiCpuPkg/CpuMpPei/CpuPaging.c | 163 ++++++++++++++++---- 2 files changed, 139 insertions(+), 26 deletions(-) diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf b/UefiCpuPkg/CpuMpPei/CpuMpPe= i.inf index 865be5627e8551ee..77eecaa0ea035b38 100644 --- a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf +++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf @@ -65,6 +65,8 @@ [Ppis] [Pcd]=0D gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ##= CONSUMES=0D gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ##= CONSUMES=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ##= SOMETIMES_CONSUMES=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable ##= SOMETIMES_CONSUMES=0D gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList ##= SOMETIMES_CONSUMES=0D gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownGoodStackSize ##= SOMETIMES_CONSUMES=0D gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ##= SOMETIMES_CONSUMES=0D diff --git a/UefiCpuPkg/CpuMpPei/CpuPaging.c b/UefiCpuPkg/CpuMpPei/CpuPagin= g.c index 175e47ccd737a0c1..2a901e44253434c2 100644 --- a/UefiCpuPkg/CpuMpPei/CpuPaging.c +++ b/UefiCpuPkg/CpuMpPei/CpuPaging.c @@ -302,7 +302,7 @@ ConvertMemoryPageAttributes ( return RETURN_INVALID_PARAMETER;=0D }=0D =0D - MaximumAddress =3D (EFI_PHYSICAL_ADDRESS)MAX_UINT32;=0D + MaximumAddress =3D (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS;=0D if ((BaseAddress > MaximumAddress) ||=0D (Length > MaximumAddress) ||=0D (BaseAddress > MaximumAddress - (Length - 1)))=0D @@ -350,16 +350,91 @@ ConvertMemoryPageAttributes ( return RETURN_SUCCESS;=0D }=0D =0D +/*=0D + * Get physical address bits supported.=0D + *=0D + * @return The number of supported physical address bits.=0D + */=0D +STATIC=0D +UINT8=0D +GetPhysicalAddressBits (=0D + VOID=0D + )=0D +{=0D + EFI_HOB_CPU *Hob;=0D + UINT32 RegEax;=0D +=0D + Hob =3D GetFirstHob (EFI_HOB_TYPE_CPU);=0D + if (Hob !=3D NULL) {=0D + return Hob->SizeOfMemorySpace;=0D + }=0D +=0D + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);=0D + if (RegEax >=3D 0x80000008) {=0D + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);=0D + return (UINT8)RegEax;=0D + }=0D +=0D + return 36;=0D +}=0D +=0D +/*=0D + * Determine and return the paging mode to be used in long mode, based on = PCD=0D + * configuration and CPU support for 1G leaf descriptors and 5 level pagin= g.=0D + *=0D + * @return The paging mode=0D + */=0D +STATIC=0D +PAGING_MODE=0D +GetPagingMode (=0D + VOID=0D + )=0D +{=0D + BOOLEAN Page5LevelSupport;=0D + BOOLEAN Page1GSupport;=0D + UINT32 RegEax;=0D + UINT32 RegEdx;=0D + IA32_CR4 Cr4;=0D +=0D + Cr4.UintN =3D AsmReadCr4 ();=0D + Page5LevelSupport =3D (Cr4.Bits.LA57 !=3D 0);=0D + ASSERT (PcdGetBool (PcdUse5LevelPageTable) =3D=3D Page5LevelSupport);=0D +=0D + Page1GSupport =3D FALSE;=0D + if (PcdGetBool (PcdUse1GPageTable)) {=0D + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);=0D + if (RegEax >=3D 0x80000001) {=0D + AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);=0D + if ((RegEdx & BIT26) !=3D 0) {=0D + Page1GSupport =3D TRUE;=0D + }=0D + }=0D + }=0D +=0D + if (Page5LevelSupport && Page1GSupport) {=0D + return Paging5Level1GB;=0D + } else if (Page5LevelSupport) {=0D + return Paging5Level;=0D + } else if (Page1GSupport) {=0D + return Paging4Level1GB;=0D + } else {=0D + return Paging4Level;=0D + }=0D +}=0D +=0D /**=0D - Enable PAE Page Table.=0D + Enable Page Table.=0D =0D - @retval EFI_SUCCESS The PAE Page Table was enabled successfu= lly.=0D - @retval EFI_OUT_OF_RESOURCES The PAE Page Table could not be enabled = due to lack of available memory.=0D + @param LongMode Whether the execution mode is 64 bit=0D +=0D + @retval EFI_SUCCESS The Page Table was enabled successfully.= =0D + @retval EFI_OUT_OF_RESOURCES The Page Table could not be enabled due = to lack of available memory.=0D =0D **/=0D +STATIC=0D EFI_STATUS=0D -EnablePaePageTable (=0D - VOID=0D +EnablePageTable (=0D + IN BOOLEAN LongMode=0D )=0D {=0D EFI_STATUS Status;=0D @@ -369,6 +444,8 @@ EnablePaePageTable ( UINTN BufferSize;=0D IA32_MAP_ATTRIBUTE MapAttribute;=0D IA32_MAP_ATTRIBUTE MapMask;=0D + PAGING_MODE PagingMode;=0D + UINT64 Length;=0D =0D PageTable =3D 0;=0D Buffer =3D NULL;=0D @@ -378,10 +455,28 @@ EnablePaePageTable ( MapAttribute.Bits.Present =3D 1;=0D MapAttribute.Bits.ReadWrite =3D 1;=0D =0D - //=0D - // 1:1 map 4GB in 32bit mode=0D - //=0D - Status =3D PageTableMap (&PageTable, PagingPae, 0, &BufferSize, 0, SIZE_= 4GB, &MapAttribute, &MapMask, NULL);=0D + if (!LongMode) {=0D + //=0D + // 1:1 map 4GB in 32bit mode=0D + //=0D + PagingMode =3D PagingPae;=0D + Length =3D SIZE_4GB;=0D + } else {=0D + PagingMode =3D GetPagingMode ();=0D + Length =3D LShiftU64 (1, GetPhysicalAddressBits ());=0D + }=0D +=0D + Status =3D PageTableMap (=0D + &PageTable,=0D + PagingMode,=0D + 0,=0D + &BufferSize,=0D + 0,=0D + Length,=0D + &MapAttribute,=0D + &MapMask,=0D + NULL=0D + );=0D ASSERT (Status =3D=3D EFI_BUFFER_TOO_SMALL);=0D if (Status !=3D EFI_BUFFER_TOO_SMALL) {=0D return Status;=0D @@ -398,12 +493,23 @@ EnablePaePageTable ( =0D DEBUG ((=0D DEBUG_INFO,=0D - "EnablePaePageTable: Created PageTable =3D 0x%x, BufferSize =3D %x\n",= =0D + "%a: Created PageTable =3D 0x%x, BufferSize =3D %x\n",=0D + __func__,=0D PageTable,=0D BufferSize=0D ));=0D =0D - Status =3D PageTableMap (&PageTable, PagingPae, Buffer, &BufferSize, 0, = SIZE_4GB, &MapAttribute, &MapMask, NULL);=0D + Status =3D PageTableMap (=0D + &PageTable,=0D + PagingMode,=0D + Buffer,=0D + &BufferSize,=0D + 0,=0D + Length,=0D + &MapAttribute,=0D + &MapMask,=0D + NULL=0D + );=0D ASSERT_EFI_ERROR (Status);=0D if (EFI_ERROR (Status) || (PageTable =3D=3D 0)) {=0D return EFI_OUT_OF_RESOURCES;=0D @@ -414,15 +520,17 @@ EnablePaePageTable ( //=0D AsmWriteCr3 (PageTable);=0D =0D - //=0D - // Enable CR4.PAE=0D - //=0D - AsmWriteCr4 (AsmReadCr4 () | BIT5);=0D + if (!LongMode) {=0D + //=0D + // Enable CR4.PAE=0D + //=0D + AsmWriteCr4 (AsmReadCr4 () | BIT5);=0D =0D - //=0D - // Enable CR0.PG=0D - //=0D - AsmWriteCr0 (AsmReadCr0 () | BIT31);=0D + //=0D + // Enable CR0.PG=0D + //=0D + AsmWriteCr0 (AsmReadCr0 () | BIT31);=0D + }=0D =0D return Status;=0D }=0D @@ -557,6 +665,9 @@ MemoryDiscoveredPpiNotifyCallback ( EDKII_MIGRATED_FV_INFO *MigratedFvInfo;=0D EFI_PEI_HOB_POINTERS Hob;=0D IA32_CR0 Cr0;=0D + BOOLEAN LongMode;=0D +=0D + LongMode =3D (sizeof (UINTN) =3D=3D sizeof (UINT64));=0D =0D //=0D // Paging must be setup first. Otherwise the exception TSS setup during = MP=0D @@ -565,7 +676,7 @@ MemoryDiscoveredPpiNotifyCallback ( //=0D InitStackGuard =3D FALSE;=0D Hob.Raw =3D NULL;=0D - if (IsIa32PaeSupported ()) {=0D + if (LongMode || IsIa32PaeSupported ()) {=0D Hob.Raw =3D GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);=0D InitStackGuard =3D PcdGetBool (PcdCpuStackGuard);=0D }=0D @@ -575,12 +686,12 @@ MemoryDiscoveredPpiNotifyCallback ( // is to enable paging if it is not enabled (only in 32bit mode).=0D //=0D Cr0.UintN =3D AsmReadCr0 ();=0D - if ((Cr0.Bits.PG =3D=3D 0) && (InitStackGuard || (Hob.Raw !=3D NULL))) {= =0D - ASSERT (sizeof (UINTN) =3D=3D sizeof (UINT32));=0D -=0D - Status =3D EnablePaePageTable ();=0D + if (LongMode ||=0D + ((Cr0.Bits.PG =3D=3D 0) && (InitStackGuard || (Hob.Raw !=3D NULL))))= =0D + {=0D + Status =3D EnablePageTable (LongMode);=0D if (EFI_ERROR (Status)) {=0D - DEBUG ((DEBUG_ERROR, "MemoryDiscoveredPpiNotifyCallback: Failed to e= nable PAE page table: %r.\n", Status));=0D + DEBUG ((DEBUG_ERROR, "%a: Failed to enable page table: %r.\n", __fun= c__, Status));=0D CpuDeadLoop ();=0D }=0D }=0D --=20 2.39.2