]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
OvmfPkg/SmmCpuFeaturesLib: init CPU ejection state
[mirror_edk2.git] / OvmfPkg / Library / SmmCpuFeaturesLib / SmmCpuFeaturesLib.c
index 7ef7ed98342e9382585c0ac43d86f26abae29858..5c025bc717c33f89f05ed420498bdfe4c2ebc928 100644 (file)
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/MemEncryptSevLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
 #include <Library/PcdLib.h>\r
+#include <Library/SafeIntLib.h>\r
 #include <Library/SmmCpuFeaturesLib.h>\r
 #include <Library/SmmServicesTableLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
+#include <Pcd/CpuHotEjectData.h>\r
 #include <PiSmm.h>\r
 #include <Register/Intel/SmramSaveStateMap.h>\r
 #include <Register/QemuSmramSaveStateMap.h>\r
@@ -171,6 +174,77 @@ SmmCpuFeaturesHookReturnFromSmm (
   return OriginalInstructionPointer;\r
 }\r
 \r
+STATIC CPU_HOT_EJECT_DATA *mCpuHotEjectData = NULL;\r
+\r
+/**\r
+  Initialize mCpuHotEjectData if PcdCpuMaxLogicalProcessorNumber > 1.\r
+\r
+  Also setup the corresponding PcdCpuHotEjectDataAddress.\r
+**/\r
+STATIC\r
+VOID\r
+InitCpuHotEjectData (\r
+  VOID\r
+  )\r
+{\r
+  UINTN          Size;\r
+  UINT32         Idx;\r
+  UINT32         MaxNumberOfCpus;\r
+  RETURN_STATUS  PcdStatus;\r
+\r
+  MaxNumberOfCpus = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);\r
+  if (MaxNumberOfCpus == 1) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // We allocate CPU_HOT_EJECT_DATA and CPU_HOT_EJECT_DATA->QemuSelectorMap[]\r
+  // in a single allocation, and explicitly align the QemuSelectorMap[] (which\r
+  // is a UINT64 array) at its natural boundary.\r
+  // Accordingly, allocate:\r
+  //   sizeof(*mCpuHotEjectData) + (MaxNumberOfCpus * sizeof(UINT64))\r
+  // and, add sizeof(UINT64) - 1 to use as padding if needed.\r
+  //\r
+\r
+  if (RETURN_ERROR (SafeUintnMult (MaxNumberOfCpus, sizeof (UINT64), &Size)) ||\r
+      RETURN_ERROR (SafeUintnAdd (Size, sizeof (*mCpuHotEjectData), &Size)) ||\r
+      RETURN_ERROR (SafeUintnAdd (Size, sizeof (UINT64) - 1, &Size))) {\r
+    DEBUG ((DEBUG_ERROR, "%a: invalid CPU_HOT_EJECT_DATA\n", __FUNCTION__));\r
+    goto Fatal;\r
+  }\r
+\r
+  mCpuHotEjectData = AllocatePool (Size);\r
+  if (mCpuHotEjectData == NULL) {\r
+    ASSERT (mCpuHotEjectData != NULL);\r
+    goto Fatal;\r
+  }\r
+\r
+  mCpuHotEjectData->Handler = NULL;\r
+  mCpuHotEjectData->ArrayLength = MaxNumberOfCpus;\r
+\r
+  mCpuHotEjectData->QemuSelectorMap = ALIGN_POINTER (mCpuHotEjectData + 1,\r
+                                        sizeof (UINT64));\r
+  //\r
+  // We use mCpuHotEjectData->QemuSelectorMap to map\r
+  // ProcessorNum -> QemuSelector. Initialize to invalid values.\r
+  //\r
+  for (Idx = 0; Idx < mCpuHotEjectData->ArrayLength; Idx++) {\r
+    mCpuHotEjectData->QemuSelectorMap[Idx] = CPU_EJECT_QEMU_SELECTOR_INVALID;\r
+  }\r
+\r
+  //\r
+  // Expose address of CPU Hot eject Data structure\r
+  //\r
+  PcdStatus = PcdSet64S (PcdCpuHotEjectDataAddress,\r
+                (UINTN)(VOID *)mCpuHotEjectData);\r
+  ASSERT_RETURN_ERROR (PcdStatus);\r
+\r
+  return;\r
+\r
+Fatal:\r
+  CpuDeadLoop ();\r
+}\r
+\r
 /**\r
   Hook point in normal execution mode that allows the one CPU that was elected\r
   as monarch during System Management Mode initialization to perform additional\r
@@ -188,6 +262,9 @@ SmmCpuFeaturesSmmRelocationComplete (
   UINTN      MapPagesBase;\r
   UINTN      MapPagesCount;\r
 \r
+\r
+  InitCpuHotEjectData ();\r
+\r
   if (!MemEncryptSevIsEnabled ()) {\r
     return;\r
   }\r