}\r
}\r
\r
+/**\r
+ Check for various QEMU bugs concerning CPU numbers.\r
+\r
+ Compensate for those bugs if various conditions are satisfied, by updating a\r
+ suitable subset of the input-output parameters. The function may not return\r
+ (it may hang deliberately), even in RELEASE builds, if the QEMU bug is\r
+ impossible to cover up.\r
+\r
+ @param[in,out] BootCpuCount On input, the boot CPU count reported by QEMU via\r
+ fw_cfg (QemuFwCfgItemSmpCpuCount). The caller is\r
+ responsible for ensuring (BootCpuCount > 0); that\r
+ is, if QEMU does not provide the boot CPU count\r
+ via fw_cfg *at all*, then this function must not\r
+ be called.\r
+\r
+ @param[in,out] Present On input, the number of present-at-boot CPUs, as\r
+ reported by QEMU through the modern CPU hotplug\r
+ register block.\r
+\r
+ @param[in,out] Possible On input, the number of possible CPUs, as\r
+ reported by QEMU through the modern CPU hotplug\r
+ register block.\r
+**/\r
+STATIC\r
+VOID\r
+PlatformCpuCountBugCheck (\r
+ IN OUT UINT16 *BootCpuCount,\r
+ IN OUT UINT32 *Present,\r
+ IN OUT UINT32 *Possible\r
+ )\r
+{\r
+ ASSERT (*BootCpuCount > 0);\r
+\r
+ //\r
+ // Sanity check: fw_cfg and the modern CPU hotplug interface should expose the\r
+ // same boot CPU count.\r
+ //\r
+ if (*BootCpuCount != *Present) {\r
+ DEBUG ((\r
+ DEBUG_WARN,\r
+ "%a: QEMU v2.7 reset bug: BootCpuCount=%d Present=%u\n",\r
+ __FUNCTION__,\r
+ *BootCpuCount,\r
+ *Present\r
+ ));\r
+ //\r
+ // The handling of QemuFwCfgItemSmpCpuCount, across CPU hotplug plus\r
+ // platform reset (including S3), was corrected in QEMU commit e3cadac073a9\r
+ // ("pc: fix FW_CFG_NB_CPUS to account for -device added CPUs", 2016-11-16),\r
+ // part of release v2.8.0.\r
+ //\r
+ *BootCpuCount = (UINT16)*Present;\r
+ }\r
+}\r
+\r
/**\r
Fetch the boot CPU count and the possible CPU count from QEMU, and expose\r
them to UefiCpuPkg modules.\r
UINT8 CpuStatus;\r
\r
//\r
- // Read the status of the currently selected CPU. This will help with a\r
- // sanity check against "BootCpuCount".\r
+ // Read the status of the currently selected CPU. This will help with\r
+ // various CPU count sanity checks.\r
//\r
CpuStatus = IoRead8 (CpuHpBase + QEMU_CPUHP_R_CPU_STAT);\r
if ((CpuStatus & QEMU_CPUHP_STAT_ENABLED) != 0) {\r
ASSERT (Selected == Possible || Selected == 0);\r
} while (Selected > 0);\r
\r
- //\r
- // Sanity check: fw_cfg and the modern CPU hotplug interface should\r
- // return the same boot CPU count.\r
- //\r
- if (BootCpuCount != Present) {\r
- DEBUG ((\r
- DEBUG_WARN,\r
- "%a: QEMU v2.7 reset bug: BootCpuCount=%d "\r
- "Present=%u\n",\r
- __FUNCTION__,\r
- BootCpuCount,\r
- Present\r
- ));\r
- //\r
- // The handling of QemuFwCfgItemSmpCpuCount, across CPU hotplug plus\r
- // platform reset (including S3), was corrected in QEMU commit\r
- // e3cadac073a9 ("pc: fix FW_CFG_NB_CPUS to account for -device added\r
- // CPUs", 2016-11-16), part of release v2.8.0.\r
- //\r
- BootCpuCount = (UINT16)Present;\r
- }\r
+ PlatformCpuCountBugCheck (&BootCpuCount, &Present, &Possible);\r
\r
MaxCpuCount = Possible;\r
}\r