EFI_STATUS Status;\r
BOOLEAN InterruptState;\r
IA32_DESCRIPTOR DxeIdtr;\r
+\r
+ //\r
+ // There are 32 (not 255) entries in it since only processor\r
+ // generated exceptions will be handled.\r
+ //\r
+ gcSmiIdtr.Limit = (sizeof(IA32_IDT_GATE_DESCRIPTOR) * 32) - 1;\r
+ //\r
+ // Allocate page aligned IDT, because it might be set as read only.\r
+ //\r
+ gcSmiIdtr.Base = (UINTN)AllocateCodePages (EFI_SIZE_TO_PAGES(gcSmiIdtr.Limit + 1));\r
+ ASSERT (gcSmiIdtr.Base != 0);\r
+ ZeroMem ((VOID *)gcSmiIdtr.Base, gcSmiIdtr.Limit + 1);\r
+\r
//\r
// Disable Interrupt and save DXE IDT table\r
//\r
AsmWriteIdtr (&gcSmiIdtr);\r
ApicId = GetApicId ();\r
\r
- ASSERT (mNumberOfCpus <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber));\r
+ ASSERT (mNumberOfCpus <= mMaxNumberOfCpus);\r
\r
for (Index = 0; Index < mNumberOfCpus; Index++) {\r
if (ApicId == (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) {\r
{\r
GetAcpiCpuData ();\r
\r
+ //\r
+ // Cache a copy of UEFI memory map before we start profiling feature.\r
+ //\r
+ GetUefiMemoryMap ();\r
+\r
//\r
// Set SMM ready to lock flag and return\r
//\r
\r
//\r
// Compute tile size of buffer required to hold the CPU SMRAM Save State Map, extra CPU\r
- // specific context in a PROCESSOR_SMM_DESCRIPTOR, and the SMI entry point. This size\r
- // is rounded up to nearest power of 2.\r
+ // specific context start starts at SMBASE + SMM_PSD_OFFSET, and the SMI entry point.\r
+ // This size is rounded up to nearest power of 2.\r
//\r
TileCodeSize = GetSmiHandlerSize ();\r
TileCodeSize = ALIGN_VALUE(TileCodeSize, SIZE_4KB);\r
- TileDataSize = sizeof (SMRAM_SAVE_STATE_MAP) + sizeof (PROCESSOR_SMM_DESCRIPTOR);\r
+ TileDataSize = (SMRAM_SAVE_STATE_MAP_OFFSET - SMM_PSD_OFFSET) + sizeof (SMRAM_SAVE_STATE_MAP);\r
TileDataSize = ALIGN_VALUE(TileDataSize, SIZE_4KB);\r
TileSize = TileDataSize + TileCodeSize - 1;\r
TileSize = 2 * GetPowerOfTwo32 ((UINT32)TileSize);\r
DEBUG ((EFI_D_INFO, "SMRAM TileSize = 0x%08x (0x%08x, 0x%08x)\n", TileSize, TileCodeSize, TileDataSize));\r
\r
//\r
- // If the TileSize is larger than space available for the SMI Handler of CPU[i],\r
- // the PROCESSOR_SMM_DESCRIPTOR of CPU[i+1] and the SMRAM Save State Map of CPU[i+1],\r
- // the ASSERT(). If this ASSERT() is triggered, then the SMI Handler size must be\r
- // reduced.\r
+ // If the TileSize is larger than space available for the SMI Handler of\r
+ // CPU[i], the extra CPU specific context of CPU[i+1], and the SMRAM Save\r
+ // State Map of CPU[i+1], then ASSERT(). If this ASSERT() is triggered, then\r
+ // the SMI Handler size must be reduced or the size of the extra CPU specific\r
+ // context must be reduced.\r
//\r
ASSERT (TileSize <= (SMRAM_SAVE_STATE_MAP_OFFSET + sizeof (SMRAM_SAVE_STATE_MAP) - SMM_HANDLER_OFFSET));\r
\r
//\r
BufferPages = EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1));\r
if ((FamilyId == 4) || (FamilyId == 5)) {\r
- Buffer = AllocateAlignedPages (BufferPages, SIZE_32KB);\r
+ Buffer = AllocateAlignedCodePages (BufferPages, SIZE_32KB);\r
} else {\r
- Buffer = AllocateAlignedPages (BufferPages, SIZE_4KB);\r
+ Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB);\r
}\r
ASSERT (Buffer != NULL);\r
DEBUG ((EFI_D_INFO, "SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE(BufferPages)));\r
//\r
SmmCpuFeaturesSmmRelocationComplete ();\r
\r
+ DEBUG ((DEBUG_INFO, "mXdSupported - 0x%x\n", mXdSupported));\r
+\r
//\r
// SMM Time initialization\r
//\r
}\r
} while (Found);\r
\r
+ FreePool (SmramRanges);\r
DEBUG ((EFI_D_INFO, "SMRR Base: 0x%x, SMRR Size: 0x%x\n", *SmrrBase, *SmrrSize));\r
}\r
\r
return AllocatePages (Pages);\r
}\r
\r
+/**\r
+ Allocate pages for code.\r
+\r
+ @param[in] Pages Number of pages to be allocated.\r
+\r
+ @return Allocated memory.\r
+**/\r
+VOID *\r
+AllocateCodePages (\r
+ IN UINTN Pages\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS Memory;\r
+\r
+ if (Pages == 0) {\r
+ return NULL;\r
+ }\r
+\r
+ Status = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, Pages, &Memory);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+ return (VOID *) (UINTN) Memory;\r
+}\r
+\r
+/**\r
+ Allocate aligned pages for code.\r
+\r
+ @param[in] Pages Number of pages to be allocated.\r
+ @param[in] Alignment The requested alignment of the allocation.\r
+ Must be a power of two.\r
+ If Alignment is zero, then byte alignment is used.\r
+\r
+ @return Allocated memory.\r
+**/\r
+VOID *\r
+AllocateAlignedCodePages (\r
+ IN UINTN Pages,\r
+ IN UINTN Alignment\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS Memory;\r
+ UINTN AlignedMemory;\r
+ UINTN AlignmentMask;\r
+ UINTN UnalignedPages;\r
+ UINTN RealPages;\r
+\r
+ //\r
+ // Alignment must be a power of two or zero.\r
+ //\r
+ ASSERT ((Alignment & (Alignment - 1)) == 0);\r
+\r
+ if (Pages == 0) {\r
+ return NULL;\r
+ }\r
+ if (Alignment > EFI_PAGE_SIZE) {\r
+ //\r
+ // Calculate the total number of pages since alignment is larger than page size.\r
+ //\r
+ AlignmentMask = Alignment - 1;\r
+ RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);\r
+ //\r
+ // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
+ //\r
+ ASSERT (RealPages > Pages);\r
+\r
+ Status = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, RealPages, &Memory);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+ AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;\r
+ UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);\r
+ if (UnalignedPages > 0) {\r
+ //\r
+ // Free first unaligned page(s).\r
+ //\r
+ Status = gSmst->SmmFreePages (Memory, UnalignedPages);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));\r
+ UnalignedPages = RealPages - Pages - UnalignedPages;\r
+ if (UnalignedPages > 0) {\r
+ //\r
+ // Free last unaligned page(s).\r
+ //\r
+ Status = gSmst->SmmFreePages (Memory, UnalignedPages);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ } else {\r
+ //\r
+ // Do not over-allocate pages in this case.\r
+ //\r
+ Status = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, Pages, &Memory);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+ AlignedMemory = (UINTN) Memory;\r
+ }\r
+ return (VOID *) AlignedMemory;\r
+}\r
+\r
/**\r
Perform the remaining tasks.\r
\r
// Create a mix of 2MB and 4KB page table. Update some memory ranges absent and execute-disable.\r
//\r
InitPaging ();\r
+\r
+ //\r
+ // Mark critical region to be read-only in page table\r
+ //\r
+ SetMemMapAttributes ();\r
+\r
+ //\r
+ // For outside SMRAM, we only map SMM communication buffer or MMIO.\r
+ //\r
+ SetUefiMemMapAttributes ();\r
+\r
+ //\r
+ // Set page table itself to be read-only\r
+ //\r
+ SetPageTableAttributes ();\r
+\r
//\r
// Configure SMM Code Access Check feature if available.\r
//\r