X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=UefiCpuPkg%2FCpuMpPei%2FCpuPaging.c;h=1354222253400c80d4678a0a065697c8c923f9cf;hb=HEAD;hp=3bf0574b34c6cbe342573d633977a7d39403f265;hpb=60b12e69fb1c8c7180fdda92f008248b9ec83db1;p=mirror_edk2.git diff --git a/UefiCpuPkg/CpuMpPei/CpuPaging.c b/UefiCpuPkg/CpuMpPei/CpuPaging.c index 3bf0574b34..1354222253 100644 --- a/UefiCpuPkg/CpuMpPei/CpuPaging.c +++ b/UefiCpuPkg/CpuMpPei/CpuPaging.c @@ -12,26 +12,27 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include "CpuMpPei.h" -#define IA32_PG_P BIT0 -#define IA32_PG_RW BIT1 -#define IA32_PG_U BIT2 -#define IA32_PG_A BIT5 -#define IA32_PG_D BIT6 -#define IA32_PG_PS BIT7 -#define IA32_PG_NX BIT63 +#define IA32_PG_P BIT0 +#define IA32_PG_RW BIT1 +#define IA32_PG_U BIT2 +#define IA32_PG_A BIT5 +#define IA32_PG_D BIT6 +#define IA32_PG_PS BIT7 +#define IA32_PG_NX BIT63 -#define PAGE_ATTRIBUTE_BITS (IA32_PG_RW | IA32_PG_P) -#define PAGE_PROGATE_BITS (IA32_PG_D | IA32_PG_A | IA32_PG_NX | IA32_PG_U |\ +#define PAGE_ATTRIBUTE_BITS (IA32_PG_RW | IA32_PG_P) +#define PAGE_PROGATE_BITS (IA32_PG_D | IA32_PG_A | IA32_PG_NX | IA32_PG_U | \ PAGE_ATTRIBUTE_BITS) -#define PAGING_PAE_INDEX_MASK 0x1FF -#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull -#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull -#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull -#define PAGING_512G_ADDRESS_MASK_64 0x000FFF8000000000ull +#define PAGING_PAE_INDEX_MASK 0x1FF +#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull +#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull +#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull +#define PAGING_512G_ADDRESS_MASK_64 0x000FFF8000000000ull typedef enum { PageNone = 0, @@ -44,19 +45,19 @@ typedef enum { } PAGE_ATTRIBUTE; typedef struct { - PAGE_ATTRIBUTE Attribute; - UINT64 Length; - UINT64 AddressMask; - UINTN AddressBitOffset; - UINTN AddressBitLength; + PAGE_ATTRIBUTE Attribute; + UINT64 Length; + UINT64 AddressMask; + UINTN AddressBitOffset; + UINTN AddressBitLength; } PAGE_ATTRIBUTE_TABLE; -PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = { - {PageNone, 0, 0, 0, 0}, - {Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64, 12, 9}, - {Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64, 21, 9}, - {Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64, 30, 9}, - {Page512G, SIZE_512GB, PAGING_512G_ADDRESS_MASK_64, 39, 9}, +PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = { + { PageNone, 0, 0, 0, 0 }, + { Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64, 12, 9 }, + { Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64, 21, 9 }, + { Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64, 30, 9 }, + { Page512G, SIZE_512GB, PAGING_512G_ADDRESS_MASK_64, 39, 9 }, }; EFI_PEI_NOTIFY_DESCRIPTOR mPostMemNotifyList[] = { @@ -79,8 +80,8 @@ IsIa32PaeSupported ( VOID ) { - UINT32 RegEax; - CPUID_VERSION_INFO_EDX RegEdx; + UINT32 RegEax; + CPUID_VERSION_INFO_EDX RegEdx; AsmCpuid (CPUID_SIGNATURE, &RegEax, NULL, NULL, NULL); if (RegEax >= CPUID_VERSION_INFO) { @@ -103,14 +104,14 @@ IsIa32PaeSupported ( **/ VOID * AllocatePageTableMemory ( - IN UINTN Pages + IN UINTN Pages ) { - VOID *Address; + VOID *Address; - Address = AllocatePages(Pages); + Address = AllocatePages (Pages); if (Address != NULL) { - ZeroMem(Address, EFI_PAGES_TO_SIZE (Pages)); + ZeroMem (Address, EFI_PAGES_TO_SIZE (Pages)); } return Address; @@ -128,13 +129,13 @@ GetPhysicalAddressWidth ( VOID ) { - UINT32 RegEax; + UINT32 RegEax; - if (sizeof(UINTN) == 4) { + if (sizeof (UINTN) == 4) { return 32; } - AsmCpuid(CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); + AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); if (RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) { AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &RegEax, NULL, NULL, NULL); RegEax &= 0xFF; @@ -152,7 +153,7 @@ GetPhysicalAddressWidth ( Get the type of top level page table. @retval Page512G PML4 paging. - @retval Page1G PAE paing. + @retval Page1G PAE paging. **/ PAGE_ATTRIBUTE @@ -160,7 +161,7 @@ GetPageTableTopLevelType ( VOID ) { - MSR_IA32_EFER_REGISTER MsrEfer; + MSR_IA32_EFER_REGISTER MsrEfer; MsrEfer.Uint64 = AsmReadMsr64 (MSR_CORE_IA32_EFER); @@ -177,19 +178,19 @@ GetPageTableTopLevelType ( **/ VOID * GetPageTableEntry ( - IN PHYSICAL_ADDRESS Address, - OUT PAGE_ATTRIBUTE *PageAttribute + IN PHYSICAL_ADDRESS Address, + OUT PAGE_ATTRIBUTE *PageAttribute ) { - INTN Level; - UINTN Index; - UINT64 *PageTable; - UINT64 AddressEncMask; + INTN Level; + UINTN Index; + UINT64 *PageTable; + UINT64 AddressEncMask; AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask); - PageTable = (UINT64 *)(UINTN)(AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64); + PageTable = (UINT64 *)(UINTN)(AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64); for (Level = (INTN)GetPageTableTopLevelType (); Level > 0; --Level) { - Index = (UINTN)RShiftU64 (Address, mPageAttributeTable[Level].AddressBitOffset); + Index = (UINTN)RShiftU64 (Address, mPageAttributeTable[Level].AddressBitOffset); Index &= PAGING_PAE_INDEX_MASK; // @@ -203,7 +204,7 @@ GetPageTableEntry ( // // Page memory? // - if ((PageTable[Index] & IA32_PG_PS) != 0 || Level == PageMin) { + if (((PageTable[Index] & IA32_PG_PS) != 0) || (Level == PageMin)) { *PageAttribute = (PAGE_ATTRIBUTE)Level; return &PageTable[Index]; } @@ -234,19 +235,19 @@ GetPageTableEntry ( **/ RETURN_STATUS SplitPage ( - IN UINT64 *PageEntry, - IN PAGE_ATTRIBUTE PageAttribute, - IN PAGE_ATTRIBUTE SplitAttribute, - IN BOOLEAN Recursively + IN UINT64 *PageEntry, + IN PAGE_ATTRIBUTE PageAttribute, + IN PAGE_ATTRIBUTE SplitAttribute, + IN BOOLEAN Recursively ) { - UINT64 BaseAddress; - UINT64 *NewPageEntry; - UINTN Index; - UINT64 AddressEncMask; - PAGE_ATTRIBUTE SplitTo; + UINT64 BaseAddress; + UINT64 *NewPageEntry; + UINTN Index; + UINT64 AddressEncMask; + PAGE_ATTRIBUTE SplitTo; - if (SplitAttribute == PageNone || SplitAttribute >= PageAttribute) { + if ((SplitAttribute == PageNone) || (SplitAttribute >= PageAttribute)) { ASSERT (SplitAttribute != PageNone); ASSERT (SplitAttribute < PageAttribute); return RETURN_INVALID_PARAMETER; @@ -261,13 +262,13 @@ SplitPage ( // // One level down each step to achieve more compact page table. // - SplitTo = PageAttribute - 1; + SplitTo = PageAttribute - 1; AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & mPageAttributeTable[SplitTo].AddressMask; - BaseAddress = *PageEntry & - ~PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & - mPageAttributeTable[PageAttribute].AddressMask; - for (Index = 0; Index < SIZE_4KB / sizeof(UINT64); Index++) { + BaseAddress = *PageEntry & + ~PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & + mPageAttributeTable[PageAttribute].AddressMask; + for (Index = 0; Index < SIZE_4KB / sizeof (UINT64); Index++) { NewPageEntry[Index] = BaseAddress | AddressEncMask | ((*PageEntry) & PAGE_PROGATE_BITS); @@ -275,7 +276,7 @@ SplitPage ( NewPageEntry[Index] |= IA32_PG_PS; } - if (Recursively && SplitTo > SplitAttribute) { + if (Recursively && (SplitTo > SplitAttribute)) { SplitPage (&NewPageEntry[Index], SplitTo, SplitAttribute, Recursively); } @@ -312,20 +313,20 @@ SplitPage ( RETURN_STATUS EFIAPI ConvertMemoryPageAttributes ( - IN PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes + IN PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes ) { - UINT64 *PageEntry; - PAGE_ATTRIBUTE PageAttribute; - RETURN_STATUS Status; - EFI_PHYSICAL_ADDRESS MaximumAddress; - - if (Length == 0 || - (BaseAddress & (SIZE_4KB - 1)) != 0 || - (Length & (SIZE_4KB - 1)) != 0) { - + UINT64 *PageEntry; + PAGE_ATTRIBUTE PageAttribute; + RETURN_STATUS Status; + EFI_PHYSICAL_ADDRESS MaximumAddress; + + if ((Length == 0) || + ((BaseAddress & (SIZE_4KB - 1)) != 0) || + ((Length & (SIZE_4KB - 1)) != 0)) + { ASSERT (Length > 0); ASSERT ((BaseAddress & (SIZE_4KB - 1)) == 0); ASSERT ((Length & (SIZE_4KB - 1)) == 0); @@ -334,9 +335,10 @@ ConvertMemoryPageAttributes ( } MaximumAddress = (EFI_PHYSICAL_ADDRESS)MAX_UINT32; - if (BaseAddress > MaximumAddress || - Length > MaximumAddress || - (BaseAddress > MaximumAddress - (Length - 1))) { + if ((BaseAddress > MaximumAddress) || + (Length > MaximumAddress) || + (BaseAddress > MaximumAddress - (Length - 1))) + { return RETURN_UNSUPPORTED; } @@ -354,6 +356,7 @@ ConvertMemoryPageAttributes ( if (RETURN_ERROR (Status)) { return Status; } + // // Do it again until the page is 4K. // @@ -373,7 +376,7 @@ ConvertMemoryPageAttributes ( // Convert success, move to next // BaseAddress += SIZE_4KB; - Length -= SIZE_4KB; + Length -= SIZE_4KB; } return RETURN_SUCCESS; @@ -393,8 +396,8 @@ GetMaxMemoryPage ( IN PAGE_ATTRIBUTE TopLevelType ) { - UINT32 RegEax; - UINT32 RegEdx; + UINT32 RegEax; + UINT32 RegEdx; if (TopLevelType == Page512G) { AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); @@ -420,31 +423,31 @@ CreatePageTable ( VOID ) { - RETURN_STATUS Status; - UINTN PhysicalAddressBits; - UINTN NumberOfEntries; - PAGE_ATTRIBUTE TopLevelPageAttr; - UINTN PageTable; - PAGE_ATTRIBUTE MaxMemoryPage; - UINTN Index; - UINT64 AddressEncMask; - UINT64 *PageEntry; - EFI_PHYSICAL_ADDRESS PhysicalAddress; - - TopLevelPageAttr = (PAGE_ATTRIBUTE)GetPageTableTopLevelType (); + RETURN_STATUS Status; + UINTN PhysicalAddressBits; + UINTN NumberOfEntries; + PAGE_ATTRIBUTE TopLevelPageAttr; + UINTN PageTable; + PAGE_ATTRIBUTE MaxMemoryPage; + UINTN Index; + UINT64 AddressEncMask; + UINT64 *PageEntry; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + + TopLevelPageAttr = (PAGE_ATTRIBUTE)GetPageTableTopLevelType (); PhysicalAddressBits = GetPhysicalAddressWidth (); - NumberOfEntries = (UINTN)1 << (PhysicalAddressBits - - mPageAttributeTable[TopLevelPageAttr].AddressBitOffset); + NumberOfEntries = (UINTN)1 << (PhysicalAddressBits - + mPageAttributeTable[TopLevelPageAttr].AddressBitOffset); - PageTable = (UINTN) AllocatePageTableMemory (1); + PageTable = (UINTN)AllocatePageTableMemory (1); if (PageTable == 0) { return 0; } - AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask); + AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask); AddressEncMask &= mPageAttributeTable[TopLevelPageAttr].AddressMask; - MaxMemoryPage = GetMaxMemoryPage (TopLevelPageAttr); - PageEntry = (UINT64 *)PageTable; + MaxMemoryPage = GetMaxMemoryPage (TopLevelPageAttr); + PageEntry = (UINT64 *)PageTable; PhysicalAddress = 0; for (Index = 0; Index < NumberOfEntries; ++Index) { @@ -454,7 +457,7 @@ CreatePageTable ( // Split the top page table down to the maximum page size supported // if (MaxMemoryPage < TopLevelPageAttr) { - Status = SplitPage(PageEntry, TopLevelPageAttr, MaxMemoryPage, TRUE); + Status = SplitPage (PageEntry, TopLevelPageAttr, MaxMemoryPage, TRUE); ASSERT_EFI_ERROR (Status); } @@ -465,11 +468,10 @@ CreatePageTable ( *PageEntry &= ~(UINT64)(IA32_PG_RW | IA32_PG_U); } - PageEntry += 1; + PageEntry += 1; PhysicalAddress += mPageAttributeTable[TopLevelPageAttr].Length; } - return PageTable; } @@ -482,12 +484,12 @@ EnablePaging ( VOID ) { - UINTN PageTable; + UINTN PageTable; PageTable = CreatePageTable (); ASSERT (PageTable != 0); if (PageTable != 0) { - AsmWriteCr3(PageTable); + AsmWriteCr3 (PageTable); AsmWriteCr4 (AsmReadCr4 () | BIT5); // CR4.PAE AsmWriteCr0 (AsmReadCr0 () | BIT31); // CR0.PG } @@ -508,15 +510,15 @@ EnablePaging ( VOID EFIAPI GetStackBase ( - IN OUT VOID *Buffer + IN OUT VOID *Buffer ) { - EFI_PHYSICAL_ADDRESS StackBase; + EFI_PHYSICAL_ADDRESS StackBase; - StackBase = (EFI_PHYSICAL_ADDRESS)(UINTN)&StackBase; + StackBase = (EFI_PHYSICAL_ADDRESS)(UINTN)&StackBase; StackBase += BASE_4KB; StackBase &= ~((EFI_PHYSICAL_ADDRESS)BASE_4KB - 1); - StackBase -= PcdGet32(PcdCpuApStackSize); + StackBase -= PcdGet32 (PcdCpuApStackSize); *(EFI_PHYSICAL_ADDRESS *)Buffer = StackBase; } @@ -531,21 +533,21 @@ SetupStackGuardPage ( VOID ) { - EFI_PEI_HOB_POINTERS Hob; - EFI_PHYSICAL_ADDRESS StackBase; - UINTN NumberOfProcessors; - UINTN Bsp; - UINTN Index; + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS StackBase; + UINTN NumberOfProcessors; + UINTN Bsp; + UINTN Index; // // One extra page at the bottom of the stack is needed for Guard page. // - if (PcdGet32(PcdCpuApStackSize) <= EFI_PAGE_SIZE) { + if (PcdGet32 (PcdCpuApStackSize) <= EFI_PAGE_SIZE) { DEBUG ((DEBUG_ERROR, "PcdCpuApStackSize is not big enough for Stack Guard!\n")); ASSERT (FALSE); } - MpInitLibGetNumberOfProcessors(&NumberOfProcessors, NULL); + MpInitLibGetNumberOfProcessors (&NumberOfProcessors, NULL); MpInitLibWhoAmI (&Bsp); for (Index = 0; Index < NumberOfProcessors; ++Index) { StackBase = 0; @@ -553,26 +555,35 @@ SetupStackGuardPage ( if (Index == Bsp) { Hob.Raw = GetHobList (); while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) { - if (CompareGuid (&gEfiHobMemoryAllocStackGuid, - &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) { + if (CompareGuid ( + &gEfiHobMemoryAllocStackGuid, + &(Hob.MemoryAllocationStack->AllocDescriptor.Name) + )) + { StackBase = Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress; break; } + Hob.Raw = GET_NEXT_HOB (Hob); } } else { // // Ask AP to return is stack base address. // - MpInitLibStartupThisAP(GetStackBase, Index, NULL, 0, (VOID *)&StackBase, NULL); + MpInitLibStartupThisAP (GetStackBase, Index, NULL, 0, (VOID *)&StackBase, NULL); } + ASSERT (StackBase != 0); // // Set Guard page at stack base address. // - ConvertMemoryPageAttributes(StackBase, EFI_PAGE_SIZE, 0); - DEBUG ((DEBUG_INFO, "Stack Guard set at %lx [cpu%lu]!\n", - (UINT64)StackBase, (UINT64)Index)); + ConvertMemoryPageAttributes (StackBase, EFI_PAGE_SIZE, 0); + DEBUG (( + DEBUG_INFO, + "Stack Guard set at %lx [cpu%lu]!\n", + (UINT64)StackBase, + (UINT64)Index + )); } // @@ -582,7 +593,7 @@ SetupStackGuardPage ( } /** - Enabl/setup stack guard for each processor if PcdCpuStackGuard is set to TRUE. + Enable/setup stack guard for each processor if PcdCpuStackGuard is set to TRUE. Doing this in the memory-discovered callback is to make sure the Stack Guard feature to cover as most PEI code as possible. @@ -602,16 +613,10 @@ MemoryDiscoveredPpiNotifyCallback ( IN VOID *Ppi ) { - EFI_STATUS Status; - BOOLEAN InitStackGuard; - BOOLEAN InterruptState; - - if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) { - InterruptState = SaveAndDisableInterrupts (); - Status = MigrateGdt (); - ASSERT_EFI_ERROR (Status); - SetInterruptState (InterruptState); - } + EFI_STATUS Status; + BOOLEAN InitStackGuard; + EDKII_MIGRATED_FV_INFO *MigratedFvInfo; + EFI_PEI_HOB_POINTERS Hob; // // Paging must be setup first. Otherwise the exception TSS setup during MP @@ -619,9 +624,14 @@ MemoryDiscoveredPpiNotifyCallback ( // the task switch (for the sake of stack switch). // InitStackGuard = FALSE; - if (IsIa32PaeSupported () && PcdGetBool (PcdCpuStackGuard)) { + Hob.Raw = NULL; + if (IsIa32PaeSupported ()) { + Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid); + InitStackGuard = PcdGetBool (PcdCpuStackGuard); + } + + if (InitStackGuard || (Hob.Raw != NULL)) { EnablePaging (); - InitStackGuard = TRUE; } Status = InitializeCpuMpWorker ((CONST EFI_PEI_SERVICES **)PeiServices); @@ -631,6 +641,20 @@ MemoryDiscoveredPpiNotifyCallback ( SetupStackGuardPage (); } + while (Hob.Raw != NULL) { + MigratedFvInfo = GET_GUID_HOB_DATA (Hob); + + // + // Enable #PF exception, so if the code access SPI after disable NEM, it will generate + // the exception to avoid potential vulnerability. + // + ConvertMemoryPageAttributes (MigratedFvInfo->FvOrgBase, MigratedFvInfo->FvLength, 0); + + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw); + } + + CpuFlushTlb (); + return Status; } -