SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart);\r
}\r
if (CpuMpData->InitFlag == ApInitConfig) {\r
- //\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
- // 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
- PcdGet32 (PcdCpuMaxLogicalProcessorNumber) - 1,\r
- PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds)\r
- );\r
+ if (PcdGet32 (PcdCpuBootLogicalProcessorNumber) > 0) {\r
+ //\r
+ // The AP enumeration algorithm below is suitable only when the\r
+ // platform can tell us the *exact* boot CPU count in advance.\r
+ //\r
+ // The wait below finishes only when the detected AP count reaches\r
+ // (PcdCpuBootLogicalProcessorNumber - 1), regardless of how long that\r
+ // takes. If at least one AP fails to check in (meaning a platform\r
+ // hardware bug), the detection hangs forever, by design. If the actual\r
+ // boot CPU count in the system is higher than\r
+ // PcdCpuBootLogicalProcessorNumber (meaning a platform\r
+ // misconfiguration), then some APs may complete initialization after\r
+ // the wait finishes, and cause undefined behavior.\r
+ //\r
+ TimedWaitForApFinish (\r
+ CpuMpData,\r
+ PcdGet32 (PcdCpuBootLogicalProcessorNumber) - 1,\r
+ MAX_UINT32 // approx. 71 minutes\r
+ );\r
+ } else {\r
+ //\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
+ // 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
+ PcdGet32 (PcdCpuMaxLogicalProcessorNumber) - 1,\r
+ PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds)\r
+ );\r
\r
- while (CpuMpData->MpCpuExchangeInfo->NumApsExecuting != 0) {\r
- CpuPause();\r
+ while (CpuMpData->MpCpuExchangeInfo->NumApsExecuting != 0) {\r
+ CpuPause();\r
+ }\r
}\r
} else {\r
//\r
## Specifies timeout value in microseconds for the BSP to detect all APs for the first time.\r
# @Prompt Timeout for the BSP to detect all APs for the first time.\r
gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds|50000|UINT32|0x00000004\r
+ ## Specifies the number of Logical Processors that are available in the\r
+ # preboot environment after platform reset, including BSP and APs. Possible\r
+ # values:<BR><BR>\r
+ # zero (default) - PcdCpuBootLogicalProcessorNumber is ignored, and\r
+ # PcdCpuApInitTimeOutInMicroSeconds limits the initial AP\r
+ # detection by the BSP.<BR>\r
+ # nonzero - PcdCpuApInitTimeOutInMicroSeconds is ignored. The initial\r
+ # AP detection finishes only when the detected CPU count\r
+ # (BSP plus APs) reaches the value of\r
+ # PcdCpuBootLogicalProcessorNumber, regardless of how long\r
+ # that takes.<BR>\r
+ # @Prompt Number of Logical Processors available after platform reset.\r
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuBootLogicalProcessorNumber|0|UINT32|0x00000008\r
## Specifies the base address of the first microcode Patch in the microcode Region.\r
# @Prompt Microcode Region base address.\r
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress|0x0|UINT64|0x00000005\r