From 12e1b1f8ef6ec14ff518518c9f5794e127308aa2 Mon Sep 17 00:00:00 2001 From: Jiaxin Wu Date: Tue, 22 Oct 2024 11:53:01 +0800 Subject: [PATCH] UefiCpuPkg/SecCore: Consume PcdMaxMappingAddressBeforeTempRamExit Consume PcdMaxMappingAddressBeforeTempRamExit for page table creation in permanent memory before Temp Ram Exit. This patch will create the full page table in two steps: Step 1: Create the max address in page table before the Temporary RAM exit. Step 2: Create the full range page table after the Temporary RAM exit. Signed-off-by: Jiaxin Wu --- UefiCpuPkg/SecCore/SecCore.inf | 1 + UefiCpuPkg/SecCore/SecCoreNative.inf | 1 + UefiCpuPkg/SecCore/SecMain.c | 205 ++++++++++++++++----------- 3 files changed, 126 insertions(+), 81 deletions(-) diff --git a/UefiCpuPkg/SecCore/SecCore.inf b/UefiCpuPkg/SecCore/SecCore.inf index 4f732cccb7..20a2ccef0b 100644 --- a/UefiCpuPkg/SecCore/SecCore.inf +++ b/UefiCpuPkg/SecCore/SecCore.inf @@ -78,6 +78,7 @@ [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdPeiTemporaryRamStackSize ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdMaxMappingAddressBeforeTempRamExit ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES [UserExtensions.TianoCore."ExtraFiles"] diff --git a/UefiCpuPkg/SecCore/SecCoreNative.inf b/UefiCpuPkg/SecCore/SecCoreNative.inf index 454a3629e5..6d6d306294 100644 --- a/UefiCpuPkg/SecCore/SecCoreNative.inf +++ b/UefiCpuPkg/SecCore/SecCoreNative.inf @@ -75,6 +75,7 @@ [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdPeiTemporaryRamStackSize ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdMaxMappingAddressBeforeTempRamExit ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES [UserExtensions.TianoCore."ExtraFiles"] diff --git a/UefiCpuPkg/SecCore/SecMain.c b/UefiCpuPkg/SecCore/SecMain.c index b0ab6cdae4..23a75d3076 100644 --- a/UefiCpuPkg/SecCore/SecMain.c +++ b/UefiCpuPkg/SecCore/SecMain.c @@ -73,40 +73,21 @@ MigrateGdt ( } /** - Migrate page table to permanent memory mapping entire physical address space. - - @retval EFI_SUCCESS The PageTable was migrated successfully. - @retval EFI_UNSUPPORTED Unsupport to migrate page table to permanent memory if IA-32e Mode not actived. - @retval EFI_OUT_OF_RESOURCES The PageTable could not be migrated due to lack of available memory. + Get Paging Mode + @retval Paging Mode. **/ -EFI_STATUS -MigratePageTable ( +PAGING_MODE +GetPagingMode ( VOID ) { - EFI_STATUS Status; - IA32_CR4 Cr4; - BOOLEAN Page5LevelSupport; - UINT32 RegEax; - CPUID_EXTENDED_CPU_SIG_EDX RegEdx; - BOOLEAN Page1GSupport; - PAGING_MODE PagingMode; - CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize; - UINT32 MaxExtendedFunctionId; - UINTN PageTable; - EFI_PHYSICAL_ADDRESS Buffer; - UINTN BufferSize; - IA32_MAP_ATTRIBUTE MapAttribute; - IA32_MAP_ATTRIBUTE MapMask; - - VirPhyAddressSize.Uint32 = 0; - PageTable = 0; - BufferSize = 0; - MapAttribute.Uint64 = 0; - MapMask.Uint64 = MAX_UINT64; - MapAttribute.Bits.Present = 1; - MapAttribute.Bits.ReadWrite = 1; + IA32_CR4 Cr4; + BOOLEAN Page5LevelSupport; + UINT32 RegEax; + CPUID_EXTENDED_CPU_SIG_EDX RegEdx; + BOOLEAN Page1GSupport; + PAGING_MODE PagingMode; // // Check Page5Level Support or not. @@ -135,6 +116,27 @@ MigratePageTable ( PagingMode = Page1GSupport ? Paging4Level1GB : Paging4Level; } + return PagingMode; +} + +/** + Get max physical address supported by specific page mode + + @param[in] PagingMode The paging mode. + + @retval Max Address. +**/ +UINT32 +GetMaxAddress ( + IN PAGING_MODE PagingMode + ) +{ + CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize; + UINT32 MaxExtendedFunctionId; + UINT32 MaxAddressBits; + + VirPhyAddressSize.Uint32 = 0; + // // Get Maximum Physical Address Bits // Get the number of address lines; Maximum Physical Address is 2^PhysicalAddressBits - 1. @@ -143,62 +145,19 @@ MigratePageTable ( AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedFunctionId, NULL, NULL, NULL); if (MaxExtendedFunctionId >= CPUID_VIR_PHY_ADDRESS_SIZE) { AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &VirPhyAddressSize.Uint32, NULL, NULL, NULL); + MaxAddressBits = VirPhyAddressSize.Bits.PhysicalAddressBits; } else { - VirPhyAddressSize.Bits.PhysicalAddressBits = 36; + MaxAddressBits = 36; } if ((PagingMode == Paging4Level1GB) || (PagingMode == Paging4Level)) { // - // The max lineaddress bits is 48 for 4 level page table. + // The max liner address bits is 48 for 4 level page table. // - VirPhyAddressSize.Bits.PhysicalAddressBits = MIN (VirPhyAddressSize.Bits.PhysicalAddressBits, 48); - } - - // - // Get required buffer size for the pagetable that will be created. - // - Status = PageTableMap (&PageTable, PagingMode, 0, &BufferSize, 0, LShiftU64 (1, VirPhyAddressSize.Bits.PhysicalAddressBits), &MapAttribute, &MapMask, NULL); - ASSERT (Status == EFI_BUFFER_TOO_SMALL); - if (Status != EFI_BUFFER_TOO_SMALL) { - return Status; + MaxAddressBits = MIN (VirPhyAddressSize.Bits.PhysicalAddressBits, 48); } - // - // Allocate required Buffer. - // - Status = PeiServicesAllocatePages ( - EfiBootServicesData, - EFI_SIZE_TO_PAGES (BufferSize), - &Buffer - ); - if (EFI_ERROR (Status)) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Create PageTable in permanent memory. - // - Status = PageTableMap (&PageTable, PagingMode, (VOID *)(UINTN)Buffer, &BufferSize, 0, LShiftU64 (1, VirPhyAddressSize.Bits.PhysicalAddressBits), &MapAttribute, &MapMask, NULL); - ASSERT_EFI_ERROR (Status); - if (EFI_ERROR (Status) || (PageTable == 0)) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Write the Pagetable to CR3. - // - AsmWriteCr3 (PageTable); - - DEBUG (( - DEBUG_INFO, - "MigratePageTable: Created PageTable = 0x%lx, BufferSize = %x, PagingMode = 0x%lx, Support Max Physical Address Bits = %d\n", - PageTable, - BufferSize, - (UINTN)PagingMode, - VirPhyAddressSize.Bits.PhysicalAddressBits - )); - - return Status; + return MaxAddressBits; } // @@ -583,6 +542,22 @@ SecTemporaryRamDone ( EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor; REPUBLISH_SEC_PPI_PPI *RepublishSecPpiPpi; IA32_CR0 Cr0; + PAGING_MODE PagingMode; + UINT32 MaxAddressBits; + UINTN PageTable; + EFI_PHYSICAL_ADDRESS Buffer; + UINTN BufferSize; + UINT64 Length; + UINT64 Address; + IA32_MAP_ATTRIBUTE MapAttribute; + IA32_MAP_ATTRIBUTE MapMask; + + PageTable = 0; + BufferSize = 0; + MapAttribute.Uint64 = 0; + MapAttribute.Bits.Present = 1; + MapAttribute.Bits.ReadWrite = 1; + MapMask.Uint64 = MAX_UINT64; // // Republish Sec Platform Information(2) PPI @@ -634,10 +609,43 @@ SecTemporaryRamDone ( // ASSERT (sizeof (UINTN) == sizeof (UINT64)); - Status = MigratePageTable (); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "SecTemporaryRamDone: Failed to migrate page table to permanent memory: %r.\n", Status)); - CpuDeadLoop (); + // + // Get PagingMode & MaxAddressBits. + // + PagingMode = GetPagingMode (); + MaxAddressBits = GetMaxAddress (PagingMode); + DEBUG ((DEBUG_INFO, "SecTemporaryRamDone: PagingMode = 0x%lx, MaxAddressBits = %d\n", PagingMode, MaxAddressBits)); + + // + // Create page table to cover the max mapping address in physical memory before Temp + // Ram Exit. The max mapping address is defined by PcdMaxMappingAddressBeforeTempRamExit. + // + Length = FixedPcdGet64 (PcdMaxMappingAddressBeforeTempRamExit); + Length = MIN (LShiftU64 (1, MaxAddressBits), Length); + if (Length != 0) { + Status = PageTableMap (&PageTable, PagingMode, 0, &BufferSize, 0, Length, &MapAttribute, &MapMask, NULL); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + if (Status != EFI_BUFFER_TOO_SMALL) { + return Status; + } + + Status = PeiServicesAllocatePages ( + EfiBootServicesData, + EFI_SIZE_TO_PAGES (BufferSize), + &Buffer + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + Status = PageTableMap (&PageTable, PagingMode, (VOID *)(UINTN)Buffer, &BufferSize, 0, Length, &MapAttribute, &MapMask, NULL); + ASSERT (BufferSize == 0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SecTemporaryRamDone: Failed to create page table in physical memory before Temp Ram Exit: %r.\n", Status)); + CpuDeadLoop (); + } + + AsmWriteCr3 (PageTable); } } @@ -646,6 +654,41 @@ SecTemporaryRamDone ( // SecPlatformDisableTemporaryMemory (); + // + // Expanding the page table to cover the entire memory space since the physical memory is WB after TempRamExit. + // + if ((Cr0.Bits.PG != 0) && (Length < LShiftU64 (1, MaxAddressBits))) { + Address = Length; + Length = LShiftU64 (1, MaxAddressBits) - Length; + + MapAttribute.Uint64 = Address; + MapAttribute.Bits.Present = 1; + MapAttribute.Bits.ReadWrite = 1; + + Status = PageTableMap (&PageTable, PagingMode, 0, &BufferSize, Address, Length, &MapAttribute, &MapMask, NULL); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + if (Status != EFI_BUFFER_TOO_SMALL) { + return Status; + } + + Status = PeiServicesAllocatePages ( + EfiBootServicesData, + EFI_SIZE_TO_PAGES (BufferSize), + &Buffer + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + Status = PageTableMap (&PageTable, PagingMode, (VOID *)(UINTN)Buffer, &BufferSize, Address, Length, &MapAttribute, &MapMask, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SecTemporaryRamDone: Failed to create full range page table in physical memory after Temp Ram Exit: %r.\n", Status)); + CpuDeadLoop (); + } + + AsmWriteCr3 (PageTable); + } + // // Restore original interrupt state //