X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=UefiCpuPkg%2FPiSmmCpuDxeSmm%2FSmmProfile.c;h=b4fe0bc23b6cb6f9d0b0a53050d5255700366456;hp=f53819ee24c235afe1e45d662974031c46826021;hb=3c5ce64f23c437e671259385d0ea2fdcf3a44aef;hpb=bb767506b265b1cdbf0dbec58c9a3f4c6be6ab2b diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c index f53819ee24..b4fe0bc23b 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c @@ -1,7 +1,9 @@ /** @file Enable SMM profile. -Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2012 - 2017, Intel Corporation. All rights reserved.
+Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -29,6 +31,11 @@ UINTN mSmmProfileSize; // UINTN mMsrDsAreaSize = SMM_PROFILE_DTS_SIZE; +// +// The flag indicates if execute-disable is supported by processor. +// +BOOLEAN mXdSupported = TRUE; + // // The flag indicates if execute-disable is enabled on processor. // @@ -80,6 +87,12 @@ MEMORY_PROTECTION_RANGE mProtectionMemRangeTemplate[] = { // {{0x00000000, 0x00000000},TRUE,TRUE}, + // + // SMRAM ranges not covered by mCpuHotPlugData.SmrrBase/mCpuHotPlugData.SmrrSiz (to be fixed in runtime). + // It is always present and instruction fetches are allowed. + // {{0x00000000, 0x00000000},TRUE,FALSE}, + // + // // Future extended range could be added here. // @@ -244,6 +257,33 @@ DebugExceptionHandler ( ClearTrapFlag (SystemContext); } +/** + Check if the input address is in SMM ranges. + + @param[in] Address The input address. + + @retval TRUE The input address is in SMM. + @retval FALSE The input address is not in SMM. +**/ +BOOLEAN +IsInSmmRanges ( + IN EFI_PHYSICAL_ADDRESS Address + ) +{ + UINTN Index; + + if ((Address >= mCpuHotPlugData.SmrrBase) && (Address < mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) { + return TRUE; + } + for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) { + if (Address >= mSmmCpuSmramRanges[Index].CpuStart && + Address < mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize) { + return TRUE; + } + } + return FALSE; +} + /** Check if the memory address will be mapped by 4KB-page. @@ -259,7 +299,6 @@ IsAddressValid ( { UINTN Index; - *Nx = FALSE; if (FeaturePcdGet (PcdCpuSmmProfileEnable)) { // // Check configuration @@ -274,9 +313,9 @@ IsAddressValid ( return FALSE; } else { - if ((Address < mCpuHotPlugData.SmrrBase) || - (Address >= mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) { - *Nx = TRUE; + *Nx = TRUE; + if (IsInSmmRanges (Address)) { + *Nx = FALSE; } return TRUE; } @@ -332,7 +371,7 @@ InitProtectedMemRange ( { UINTN Index; UINTN NumberOfDescriptors; - UINTN NumberOfMmioDescriptors; + UINTN NumberOfAddedDescriptors; UINTN NumberOfProtectRange; UINTN NumberOfSpliteRange; EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; @@ -345,7 +384,7 @@ InitProtectedMemRange ( UINT64 Low4KBPageSize; NumberOfDescriptors = 0; - NumberOfMmioDescriptors = 0; + NumberOfAddedDescriptors = mSmmCpuSmramRangeCount; NumberOfSpliteRange = 0; MemorySpaceMap = NULL; @@ -358,12 +397,12 @@ InitProtectedMemRange ( ); for (Index = 0; Index < NumberOfDescriptors; Index++) { if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) { - NumberOfMmioDescriptors++; + NumberOfAddedDescriptors++; } } - if (NumberOfMmioDescriptors != 0) { - TotalSize = NumberOfMmioDescriptors * sizeof (MEMORY_PROTECTION_RANGE) + sizeof (mProtectionMemRangeTemplate); + if (NumberOfAddedDescriptors != 0) { + TotalSize = NumberOfAddedDescriptors * sizeof (MEMORY_PROTECTION_RANGE) + sizeof (mProtectionMemRangeTemplate); mProtectionMemRange = (MEMORY_PROTECTION_RANGE *) AllocateZeroPool (TotalSize); ASSERT (mProtectionMemRange != NULL); mProtectionMemRangeCount = TotalSize / sizeof (MEMORY_PROTECTION_RANGE); @@ -380,10 +419,28 @@ InitProtectedMemRange ( mSplitMemRange = (MEMORY_RANGE *) AllocateZeroPool (TotalSize); ASSERT (mSplitMemRange != NULL); + // + // Create SMM ranges which are set to present and execution-enable. + // + NumberOfProtectRange = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE); + for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) { + if (mSmmCpuSmramRanges[Index].CpuStart >= mProtectionMemRange[0].Range.Base && + mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize < mProtectionMemRange[0].Range.Top) { + // + // If the address have been already covered by mCpuHotPlugData.SmrrBase/mCpuHotPlugData.SmrrSiz + // + break; + } + mProtectionMemRange[NumberOfProtectRange].Range.Base = mSmmCpuSmramRanges[Index].CpuStart; + mProtectionMemRange[NumberOfProtectRange].Range.Top = mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize; + mProtectionMemRange[NumberOfProtectRange].Present = TRUE; + mProtectionMemRange[NumberOfProtectRange].Nx = FALSE; + NumberOfProtectRange++; + } + // // Create MMIO ranges which are set to present and execution-disable. // - NumberOfProtectRange = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE); for (Index = 0; Index < NumberOfDescriptors; Index++) { if (MemorySpaceMap[Index].GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) { continue; @@ -394,6 +451,12 @@ InitProtectedMemRange ( mProtectionMemRange[NumberOfProtectRange].Nx = TRUE; NumberOfProtectRange++; } + + // + // Check and updated actual protected memory ranges count + // + ASSERT (NumberOfProtectRange <= mProtectionMemRangeCount); + mProtectionMemRangeCount = NumberOfProtectRange; } // @@ -513,7 +576,7 @@ InitPaging ( // continue; } - Pde = (UINT64 *)(UINTN)(Pml4[Level1] & PHYSICAL_ADDRESS_MASK); + Pde = (UINT64 *)(UINTN)(Pml4[Level1] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); } else { Pde = (UINT64*)(UINTN)mSmmProfileCr3; } @@ -530,7 +593,7 @@ InitPaging ( // continue; } - Pte = (UINT64 *)(UINTN)(*Pde & PHYSICAL_ADDRESS_MASK); + Pte = (UINT64 *)(UINTN)(*Pde & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); if (Pte == 0) { continue; } @@ -557,9 +620,9 @@ InitPaging ( // Split it for (Level4 = 0; Level4 < SIZE_4KB / sizeof(*Pt); Level4++) { - Pt[Level4] = Address + ((Level4 << 12) | PAGE_ATTRIBUTE_BITS); + Pt[Level4] = Address + ((Level4 << 12) | mAddressEncMask | PAGE_ATTRIBUTE_BITS); } // end for PT - *Pte = (UINTN)Pt | PAGE_ATTRIBUTE_BITS; + *Pte = (UINT64)(UINTN)Pt | mAddressEncMask | PAGE_ATTRIBUTE_BITS; } // end if IsAddressSplit } // end for PTE } // end for PDE @@ -577,7 +640,7 @@ InitPaging ( // continue; } - Pde = (UINT64 *)(UINTN)(Pml4[Level1] & PHYSICAL_ADDRESS_MASK); + Pde = (UINT64 *)(UINTN)(Pml4[Level1] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); } else { Pde = (UINT64*)(UINTN)mSmmProfileCr3; } @@ -597,7 +660,7 @@ InitPaging ( } continue; } - Pte = (UINT64 *)(UINTN)(*Pde & PHYSICAL_ADDRESS_MASK); + Pte = (UINT64 *)(UINTN)(*Pde & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); if (Pte == 0) { continue; } @@ -624,7 +687,7 @@ InitPaging ( } } else { // 4KB page - Pt = (UINT64 *)(UINTN)(*Pte & PHYSICAL_ADDRESS_MASK); + Pt = (UINT64 *)(UINTN)(*Pte & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); if (Pt == 0) { continue; } @@ -952,6 +1015,7 @@ CheckFeatureSupported ( // Extended CPUID functions are not supported on this processor. // mXdSupported = FALSE; + PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1); } AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx); @@ -960,6 +1024,7 @@ CheckFeatureSupported ( // Execute Disable Bit feature is not supported on this processor. // mXdSupported = FALSE; + PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1); } } @@ -1244,6 +1309,8 @@ SmmProfilePFHandler ( { UINT64 *PageTable; UINT64 PFAddress; + UINT64 RestoreAddress; + UINTN RestorePageNumber; UINTN CpuIndex; UINTN Index; UINT64 InstructionAddress; @@ -1273,10 +1340,21 @@ SmmProfilePFHandler ( PFAddress = AsmReadCr2 (); CpuIndex = GetCpuIndex (); - if (PFAddress <= 0xFFFFFFFF) { - RestorePageTableBelow4G (PageTable, PFAddress, CpuIndex, ErrorCode); - } else { - RestorePageTableAbove4G (PageTable, PFAddress, CpuIndex, ErrorCode, &IsValidPFAddress); + // + // Memory operation cross pages, like "rep mov" instruction, will cause + // infinite loop between this and Debug Trap handler. We have to make sure + // that current page and the page followed are both in PRESENT state. + // + RestorePageNumber = 2; + RestoreAddress = PFAddress; + while (RestorePageNumber > 0) { + if (RestoreAddress <= 0xFFFFFFFF) { + RestorePageTableBelow4G (PageTable, RestoreAddress, CpuIndex, ErrorCode); + } else { + RestorePageTableAbove4G (PageTable, RestoreAddress, CpuIndex, ErrorCode, &IsValidPFAddress); + } + RestoreAddress += EFI_PAGE_SIZE; + RestorePageNumber--; } if (!IsValidPFAddress) {