UefiCpuPkg/MpInitLib: honor the platform's boot CPU count in AP detection

- If a platform boots such that the boot CPU count is smaller than
  PcdCpuMaxLogicalProcessorNumber, then the platform cannot use the "fast
  AP detection" logic added in commit 6e1987f19a. (Which has been
  documented as a subset of use case (2) in the previous patch.)

  Said logic depends on the boot CPU count being equal to
  PcdCpuMaxLogicalProcessorNumber. If the equality does not hold, the
  platform either has to wait too long, or risk missing APs due to an
  early timeout.

- The platform may not be able to use the variant added in commit
  0594ec417c either. (Which has been documented as use case (1) in the
  previous patch.)

  See commit 861218740d. When OVMF runs on QEMU/KVM, APs may check in
  with the BSP in arbitrary order, plus the individual AP may take
  arbitrarily long to check-in. If "NumApsExecuting" falls to zero
  mid-enumeration, APs will be missed.

Allow platforms to specify the exact boot CPU count, independently of
PcdCpuMaxLogicalProcessorNumber. In this mode, the BSP waits for all APs
to check-in regardless of timeout. If at least one AP fails to check-in,
then the AP enumeration hangs forever. That is the desired behavior when
the exact boot CPU count is known in advance. (A hung boot is better than
an AP checking-in after timeout, and executing code from released
storage.)

Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
This commit is contained in:
Laszlo Ersek 2019-10-07 14:05:28 +02:00
parent 30459ddde6
commit 778832bcad
5 changed files with 80 additions and 40 deletions

View File

@ -61,6 +61,7 @@
[Pcd] [Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuBootLogicalProcessorNumber ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## SOMETIMES_CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## SOMETIMES_CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES

View File

@ -1044,6 +1044,26 @@ WakeUpAP (
SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart); SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart);
} }
if (CpuMpData->InitFlag == ApInitConfig) { if (CpuMpData->InitFlag == ApInitConfig) {
if (PcdGet32 (PcdCpuBootLogicalProcessorNumber) > 0) {
//
// The AP enumeration algorithm below is suitable only when the
// platform can tell us the *exact* boot CPU count in advance.
//
// The wait below finishes only when the detected AP count reaches
// (PcdCpuBootLogicalProcessorNumber - 1), regardless of how long that
// takes. If at least one AP fails to check in (meaning a platform
// hardware bug), the detection hangs forever, by design. If the actual
// boot CPU count in the system is higher than
// PcdCpuBootLogicalProcessorNumber (meaning a platform
// misconfiguration), then some APs may complete initialization after
// the wait finishes, and cause undefined behavior.
//
TimedWaitForApFinish (
CpuMpData,
PcdGet32 (PcdCpuBootLogicalProcessorNumber) - 1,
MAX_UINT32 // approx. 71 minutes
);
} else {
// //
// The AP enumeration algorithm below is suitable for two use cases. // The AP enumeration algorithm below is suitable for two use cases.
// //
@ -1085,6 +1105,7 @@ WakeUpAP (
while (CpuMpData->MpCpuExchangeInfo->NumApsExecuting != 0) { while (CpuMpData->MpCpuExchangeInfo->NumApsExecuting != 0) {
CpuPause(); CpuPause();
} }
}
} else { } else {
// //
// Wait all APs waken up if this is not the 1st broadcast of SIPI // Wait all APs waken up if this is not the 1st broadcast of SIPI

View File

@ -53,7 +53,8 @@
[Pcd] [Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuBootLogicalProcessorNumber ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## SOMETIMES_CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES

View File

@ -227,6 +227,19 @@
## Specifies timeout value in microseconds for the BSP to detect all APs for the first time. ## Specifies timeout value in microseconds for the BSP to detect all APs for the first time.
# @Prompt Timeout for the BSP to detect all APs for the first time. # @Prompt Timeout for the BSP to detect all APs for the first time.
gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds|50000|UINT32|0x00000004 gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds|50000|UINT32|0x00000004
## Specifies the number of Logical Processors that are available in the
# preboot environment after platform reset, including BSP and APs. Possible
# values:<BR><BR>
# zero (default) - PcdCpuBootLogicalProcessorNumber is ignored, and
# PcdCpuApInitTimeOutInMicroSeconds limits the initial AP
# detection by the BSP.<BR>
# nonzero - PcdCpuApInitTimeOutInMicroSeconds is ignored. The initial
# AP detection finishes only when the detected CPU count
# (BSP plus APs) reaches the value of
# PcdCpuBootLogicalProcessorNumber, regardless of how long
# that takes.<BR>
# @Prompt Number of Logical Processors available after platform reset.
gUefiCpuPkgTokenSpaceGuid.PcdCpuBootLogicalProcessorNumber|0|UINT32|0x00000008
## Specifies the base address of the first microcode Patch in the microcode Region. ## Specifies the base address of the first microcode Patch in the microcode Region.
# @Prompt Microcode Region base address. # @Prompt Microcode Region base address.
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress|0x0|UINT64|0x00000005 gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress|0x0|UINT64|0x00000005

View File

@ -37,6 +37,10 @@
#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuApInitTimeOutInMicroSeconds_HELP #language en-US "Specifies timeout value in microseconds for the BSP to detect all APs for the first time." #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuApInitTimeOutInMicroSeconds_HELP #language en-US "Specifies timeout value in microseconds for the BSP to detect all APs for the first time."
#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuBootLogicalProcessorNumber_PROMPT #language en-US "Number of Logical Processors available after platform reset."
#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuBootLogicalProcessorNumber_HELP #language en-US "Specifies the number of Logical Processors that are available in the preboot environment after platform reset, including BSP and APs."
#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuMicrocodePatchAddress_PROMPT #language en-US "Microcode Region base address." #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuMicrocodePatchAddress_PROMPT #language en-US "Microcode Region base address."
#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuMicrocodePatchAddress_HELP #language en-US "Specifies the base address of the first microcode Patch in the microcode Region." #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuMicrocodePatchAddress_HELP #language en-US "Specifies the base address of the first microcode Patch in the microcode Region."