Skip to content

Commit

Permalink
UefiCpuPkg/SecCore: Consume PcdMaxMappingAddressBeforeTempRamExit
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
jiaxinwu authored and mergify[bot] committed Nov 7, 2024
1 parent e1b09df commit 12e1b1f
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 81 deletions.
1 change: 1 addition & 0 deletions UefiCpuPkg/SecCore/SecCore.inf
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@

[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdPeiTemporaryRamStackSize ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdMaxMappingAddressBeforeTempRamExit ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES

[UserExtensions.TianoCore."ExtraFiles"]
Expand Down
1 change: 1 addition & 0 deletions UefiCpuPkg/SecCore/SecCoreNative.inf
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@

[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdPeiTemporaryRamStackSize ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdMaxMappingAddressBeforeTempRamExit ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES

[UserExtensions.TianoCore."ExtraFiles"]
Expand Down
205 changes: 124 additions & 81 deletions UefiCpuPkg/SecCore/SecMain.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -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;
}

//
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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
//
Expand Down

0 comments on commit 12e1b1f

Please sign in to comment.