]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/MpInitLib: expand comment on initial AP enumeration
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / MpLib.c
index a1ad665564110cbeebb0d6570bdd4d2d2b926424..594a035d8b927ec031daff272c600d7c81dfd447 100644 (file)
@@ -790,6 +790,7 @@ FillExchangeInfoData (
   volatile MP_CPU_EXCHANGE_INFO    *ExchangeInfo;\r
   UINTN                            Size;\r
   IA32_SEGMENT_DESCRIPTOR          *Selector;\r
+  IA32_CR4                         Cr4;\r
 \r
   ExchangeInfo                  = CpuMpData->MpCpuExchangeInfo;\r
   ExchangeInfo->Lock            = 0;\r
@@ -814,6 +815,18 @@ FillExchangeInfoData (
 \r
   ExchangeInfo->InitializeFloatingPointUnitsAddress = (UINTN)InitializeFloatingPointUnits;\r
 \r
+  //\r
+  // We can check either CPUID(7).ECX[bit16] or check CR4.LA57[bit12]\r
+  //  to determin whether 5-Level Paging is enabled.\r
+  // CPUID(7).ECX[bit16] shows CPU's capability, CR4.LA57[bit12] shows\r
+  // current system setting.\r
+  // Using latter way is simpler because it also eliminates the needs to\r
+  //  check whether platform wants to enable it.\r
+  //\r
+  Cr4.UintN = AsmReadCr4 ();\r
+  ExchangeInfo->Enable5LevelPaging = (BOOLEAN) (Cr4.Bits.LA57 == 1);\r
+  DEBUG ((DEBUG_INFO, "%a: 5-Level Paging = %d\n", gEfiCallerBaseName, ExchangeInfo->Enable5LevelPaging));\r
+\r
   //\r
   // Get the BSP's data of GDT and IDT\r
   //\r
@@ -1032,14 +1045,36 @@ WakeUpAP (
     }\r
     if (CpuMpData->InitFlag == ApInitConfig) {\r
       //\r
-      // Here support two methods to collect AP count through adjust\r
-      // PcdCpuApInitTimeOutInMicroSeconds values.\r
+      // The AP enumeration algorithm below is suitable for two use cases.\r
+      //\r
+      // (1) The check-in time for an individual AP is bounded, and APs run\r
+      //     through their initialization routines strongly concurrently. In\r
+      //     particular, the number of concurrently running APs\r
+      //     ("NumApsExecuting") is never expected to fall to zero\r
+      //     *temporarily* -- it is expected to fall to zero only when all\r
+      //     APs have checked-in.\r
+      //\r
+      //     In this case, the platform is supposed to set\r
+      //     PcdCpuApInitTimeOutInMicroSeconds to a low-ish value (just long\r
+      //     enough for one AP to start initialization). The timeout will be\r
+      //     reached soon, and remaining APs are collected by watching\r
+      //     NumApsExecuting fall to zero. If NumApsExecuting falls to zero\r
+      //     mid-process, while some APs have not completed initialization,\r
+      //     the behavior is undefined.\r
+      //\r
+      // (2) The check-in time for an individual AP is unbounded, and/or APs\r
+      //     may complete their initializations widely spread out. In\r
+      //     particular, some APs may finish initialization before some APs\r
+      //     even start.\r
       //\r
-      // one way is set a value to just let the first AP to start the\r
-      // initialization, then through the later while loop to wait all Aps\r
-      // finsh the initialization.\r
-      // The other way is set a value to let all APs finished the initialzation.\r
-      // In this case, the later while loop is useless.\r
+      //     In this case, the platform is supposed to set\r
+      //     PcdCpuApInitTimeOutInMicroSeconds to a high-ish value. The AP\r
+      //     enumeration will always take that long (except when the boot CPU\r
+      //     count happens to be maximal, that is,\r
+      //     PcdCpuMaxLogicalProcessorNumber). All APs are expected to\r
+      //     check-in before the timeout, and NumApsExecuting is assumed zero\r
+      //     at timeout. APs that miss the time-out may cause undefined\r
+      //     behavior.\r
       //\r
       TimedWaitForApFinish (\r
         CpuMpData,\r