/** @file\r
Enable SMM profile.\r
\r
-Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2012 - 2017, Intel Corporation. All rights reserved.<BR>\r
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
//\r
UINTN mMsrDsAreaSize = SMM_PROFILE_DTS_SIZE;\r
\r
+//\r
+// The flag indicates if execute-disable is supported by processor.\r
+//\r
+BOOLEAN mXdSupported = TRUE;\r
+\r
//\r
// The flag indicates if execute-disable is enabled on processor.\r
//\r
//\r
{{0x00000000, 0x00000000},TRUE,TRUE},\r
\r
+ //\r
+ // SMRAM ranges not covered by mCpuHotPlugData.SmrrBase/mCpuHotPlugData.SmrrSiz (to be fixed in runtime).\r
+ // It is always present and instruction fetches are allowed.\r
+ // {{0x00000000, 0x00000000},TRUE,FALSE},\r
+ //\r
+\r
//\r
// Future extended range could be added here.\r
//\r
ClearTrapFlag (SystemContext);\r
}\r
\r
+/**\r
+ Check if the input address is in SMM ranges.\r
+\r
+ @param[in] Address The input address.\r
+\r
+ @retval TRUE The input address is in SMM.\r
+ @retval FALSE The input address is not in SMM.\r
+**/\r
+BOOLEAN\r
+IsInSmmRanges (\r
+ IN EFI_PHYSICAL_ADDRESS Address\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ if ((Address >= mCpuHotPlugData.SmrrBase) && (Address < mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) {\r
+ return TRUE;\r
+ }\r
+ for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) {\r
+ if (Address >= mSmmCpuSmramRanges[Index].CpuStart &&\r
+ Address < mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize) {\r
+ return TRUE;\r
+ }\r
+ }\r
+ return FALSE;\r
+}\r
+\r
/**\r
Check if the memory address will be mapped by 4KB-page.\r
\r
{\r
UINTN Index;\r
\r
- *Nx = FALSE;\r
if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {\r
//\r
// Check configuration\r
return FALSE;\r
\r
} else {\r
- if ((Address < mCpuHotPlugData.SmrrBase) ||\r
- (Address >= mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) {\r
- *Nx = TRUE;\r
+ *Nx = TRUE;\r
+ if (IsInSmmRanges (Address)) {\r
+ *Nx = FALSE;\r
}\r
return TRUE;\r
}\r
{\r
UINTN Index;\r
UINTN NumberOfDescriptors;\r
- UINTN NumberOfMmioDescriptors;\r
+ UINTN NumberOfAddedDescriptors;\r
UINTN NumberOfProtectRange;\r
UINTN NumberOfSpliteRange;\r
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
UINT64 Low4KBPageSize;\r
\r
NumberOfDescriptors = 0;\r
- NumberOfMmioDescriptors = 0;\r
+ NumberOfAddedDescriptors = mSmmCpuSmramRangeCount;\r
NumberOfSpliteRange = 0;\r
MemorySpaceMap = NULL;\r
\r
);\r
for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {\r
- NumberOfMmioDescriptors++;\r
+ NumberOfAddedDescriptors++;\r
}\r
}\r
\r
- if (NumberOfMmioDescriptors != 0) {\r
- TotalSize = NumberOfMmioDescriptors * sizeof (MEMORY_PROTECTION_RANGE) + sizeof (mProtectionMemRangeTemplate);\r
+ if (NumberOfAddedDescriptors != 0) {\r
+ TotalSize = NumberOfAddedDescriptors * sizeof (MEMORY_PROTECTION_RANGE) + sizeof (mProtectionMemRangeTemplate);\r
mProtectionMemRange = (MEMORY_PROTECTION_RANGE *) AllocateZeroPool (TotalSize);\r
ASSERT (mProtectionMemRange != NULL);\r
mProtectionMemRangeCount = TotalSize / sizeof (MEMORY_PROTECTION_RANGE);\r
mSplitMemRange = (MEMORY_RANGE *) AllocateZeroPool (TotalSize);\r
ASSERT (mSplitMemRange != NULL);\r
\r
+ //\r
+ // Create SMM ranges which are set to present and execution-enable.\r
+ //\r
+ NumberOfProtectRange = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE);\r
+ for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) {\r
+ if (mSmmCpuSmramRanges[Index].CpuStart >= mProtectionMemRange[0].Range.Base &&\r
+ mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize < mProtectionMemRange[0].Range.Top) {\r
+ //\r
+ // If the address have been already covered by mCpuHotPlugData.SmrrBase/mCpuHotPlugData.SmrrSiz\r
+ //\r
+ break;\r
+ }\r
+ mProtectionMemRange[NumberOfProtectRange].Range.Base = mSmmCpuSmramRanges[Index].CpuStart;\r
+ mProtectionMemRange[NumberOfProtectRange].Range.Top = mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize;\r
+ mProtectionMemRange[NumberOfProtectRange].Present = TRUE;\r
+ mProtectionMemRange[NumberOfProtectRange].Nx = FALSE;\r
+ NumberOfProtectRange++;\r
+ }\r
+\r
//\r
// Create MMIO ranges which are set to present and execution-disable.\r
//\r
- NumberOfProtectRange = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE);\r
for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
if (MemorySpaceMap[Index].GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) {\r
continue;\r
mProtectionMemRange[NumberOfProtectRange].Nx = TRUE;\r
NumberOfProtectRange++;\r
}\r
+\r
+ //\r
+ // Check and updated actual protected memory ranges count\r
+ //\r
+ ASSERT (NumberOfProtectRange <= mProtectionMemRangeCount);\r
+ mProtectionMemRangeCount = NumberOfProtectRange;\r
}\r
\r
//\r
// Extended CPUID functions are not supported on this processor.\r
//\r
mXdSupported = FALSE;\r
+ PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);\r
}\r
\r
AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);\r
// Execute Disable Bit feature is not supported on this processor.\r
//\r
mXdSupported = FALSE;\r
+ PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);\r
}\r
}\r
\r
{\r
UINT64 *PageTable;\r
UINT64 PFAddress;\r
+ UINT64 RestoreAddress;\r
+ UINTN RestorePageNumber;\r
UINTN CpuIndex;\r
UINTN Index;\r
UINT64 InstructionAddress;\r
PFAddress = AsmReadCr2 ();\r
CpuIndex = GetCpuIndex ();\r
\r
- if (PFAddress <= 0xFFFFFFFF) {\r
- RestorePageTableBelow4G (PageTable, PFAddress, CpuIndex, ErrorCode);\r
- } else {\r
- RestorePageTableAbove4G (PageTable, PFAddress, CpuIndex, ErrorCode, &IsValidPFAddress);\r
+ //\r
+ // Memory operation cross pages, like "rep mov" instruction, will cause\r
+ // infinite loop between this and Debug Trap handler. We have to make sure\r
+ // that current page and the page followed are both in PRESENT state.\r
+ //\r
+ RestorePageNumber = 2;\r
+ RestoreAddress = PFAddress;\r
+ while (RestorePageNumber > 0) {\r
+ if (RestoreAddress <= 0xFFFFFFFF) {\r
+ RestorePageTableBelow4G (PageTable, RestoreAddress, CpuIndex, ErrorCode);\r
+ } else {\r
+ RestorePageTableAbove4G (PageTable, RestoreAddress, CpuIndex, ErrorCode, &IsValidPFAddress);\r
+ }\r
+ RestoreAddress += EFI_PAGE_SIZE;\r
+ RestorePageNumber--;\r
}\r
\r
if (!IsValidPFAddress) {\r