- //\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