soc/intel/xeon_sp/finalize.c: Set BIOS_DONE MSR as applicable

If BIOS_DONE MSR is supported, set it after ReadyToBoot, because FSP
programs certain registers via Notify phase ReadyToBoot and it cannot
be modified by FSP after coreboot has set BIOS_DONE MSR, therefore we
try to set BIOS_DONE MSR as late as possible to avoid this.

Signed-off-by: Tim Chu <Tim.Chu@quantatw.com>
Signed-off-by: Johnny Lin <johnny_lin@wiwynn.com>
Signed-off-by: Jonathan Zhang <jonzhang@meta.com>
Change-Id: I4f19a7c54818231ebbccd2b6f8b23f47b117eb1f
Reviewed-on: https://review.coreboot.org/c/coreboot/+/71964
Reviewed-by: Jonathan Zhang <jonzhang@fb.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: David Hendricks <david.hendricks@gmail.com>
diff --git a/src/soc/intel/xeon_sp/finalize.c b/src/soc/intel/xeon_sp/finalize.c
index 33a4d43..6b8395c 100644
--- a/src/soc/intel/xeon_sp/finalize.c
+++ b/src/soc/intel/xeon_sp/finalize.c
@@ -11,6 +11,7 @@
 #include <soc/pci_devs.h>
 #include <soc/pm.h>
 #include <soc/util.h>
+#include <soc/soc_util.h>
 #include <smp/spinlock.h>
 
 #include "chip.h"
@@ -83,4 +84,19 @@
 	post_code(POST_OS_BOOT);
 }
 
+static void bios_done_finalize(void *unused)
+{
+	if (!CONFIG(SOC_INTEL_HAS_BIOS_DONE_MSR))
+		return;
+
+	printk(BIOS_DEBUG, "Setting BIOS_DONE\n");
+	/* bios_done_msr() only defined for some Xeon-SP, such as SPR-SP */
+	if (mp_run_on_all_cpus(&bios_done_msr, NULL) != CB_SUCCESS)
+		printk(BIOS_ERR, "Fail to set BIOS_DONE MSR\n");
+
+}
+
 BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_ENTRY, soc_finalize, NULL);
+/* FSP programs certain registers via Notify phase ReadyToBoot that can only be programmed
+   before BIOS_DONE MSR is set, so coreboot sets BIOS_DONE as late as possible. */
+BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, bios_done_finalize, NULL);