bootm: Update FPDT boot times before handing off to OS

Update the FPDT boot performance record's ebs_entry and ebs_exit
fields in bootm_final() to record the time when we're about to
hand off to the operating system.

The timing is recorded just before we start the kernel, after all
device cleanup and before interrupts are disabled, which corresponds
to the ExitBootServices phase in UEFI.

If EFI is used to boot, a further update could be made, but that is
left for later.

Avoid including asm/acpi_table.h on platforms without ACPI. Ad a special
case for the QEMU RISC-V ACPI board.

Series-changes: 2
- Depend on ACPIGEN instead of GENERATE_ACPI_TABLE
- Avoid including asm/acpi_table.h on platforms without ACPI

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2025-10-20 12:10:12 +01:00
parent d9b81fa614
commit bfcb0a6dd6
3 changed files with 40 additions and 0 deletions

View File

@@ -9,6 +9,7 @@
#include <bootstage.h>
#include <event.h>
#include <usb.h>
#include <acpi/acpi_table.h>
#include <dm/root.h>
__weak void board_quiesce_devices(void)
@@ -25,6 +26,11 @@ void bootm_final(enum bootm_final_t flags)
bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
/* Update FPDT boot performance record if it exists */
if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE) &&
IS_ENABLED(CONFIG_ACPIGEN))
acpi_final_fpdt();
if (IS_ENABLED(CONFIG_BOOTSTAGE_FDT) && IS_ENABLED(CONFIG_CMD_FDT))
bootstage_fdt_add_report();
if (IS_ENABLED(CONFIG_BOOTSTAGE_REPORT))

View File

@@ -1383,8 +1383,22 @@ struct acpi_fpdt_boot *acpi_get_fpdt_boot(void);
*/
int acpi_fix_fpdt_checksum(void);
/**
* acpi_final_fpdt() - Finalize FPDT boot performance record before OS handoff
*
* Updates the FPDT boot performance record with the final boot timing
* information just before handing control to the operating system. This
* sets the ExitBootServices entry and exit times to the current time.
* If FPDT table exists, the checksum is automatically recalculated.
*
* This function does nothing if the FPDT table is not present.
*/
void acpi_final_fpdt(void);
#endif /* !__ACPI__*/
#ifdef CONFIG_ACPI
#include <asm/acpi_table.h>
#endif
#endif /* __ACPI_TABLE_H__ */

View File

@@ -15,6 +15,7 @@
#include <mapmem.h>
#include <tables_csum.h>
#include <serial.h>
#include <timer.h>
#include <acpi/acpi_table.h>
#include <acpi/acpi_device.h>
#include <asm/global_data.h>
@@ -786,6 +787,24 @@ int acpi_fix_fpdt_checksum(void)
return 0;
}
void acpi_final_fpdt(void)
{
struct acpi_fpdt_boot *fpdt;
if (IS_ENABLED(CONFIG_TARGET_QEMU_VIRT))
return;
fpdt = acpi_get_fpdt_boot();
if (fpdt) {
u64 time;
time = timer_get_boot_us();
fpdt->ebs_entry = time;
fpdt->ebs_exit = time;
acpi_fix_fpdt_checksum();
}
}
/* this board lacks the bootstage timer */
#ifndef CONFIG_TARGET_QEMU_VIRT
@@ -799,4 +818,5 @@ static int acpi_create_fpdt(struct acpi_ctx *ctx,
return acpi_write_fpdt(ctx, uboot_start);
}
ACPI_WRITER(6fpdt, "FPDT", acpi_create_fpdt, 0);
#endif