From: Simon Glass <sjg@chromium.org> Add 'bootstage save' and 'bootstage restore' subcommands behind a new BOOTSTAGE_SAVE Kconfig (default y when UNIT_TEST is enabled). These store and retrieve the record count via $bootstage_count. Some commands (e.g. bootm) add bootstage records with unique IDs. In a pytest session with many tests, these accumulate and fill the bootstage table. The new commands allow the test framework to save the count before a test and restore it afterwards. Also add inline stubs for bootstage_get_rec_count() and bootstage_set_rec_count() when BOOTSTAGE is disabled, along with a test and command documentation. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/Kconfig | 11 +++++ cmd/bootstage.c | 28 ++++++++++++ doc/usage/cmd/bootstage.rst | 86 +++++++++++++++++++++++++++++++++++++ doc/usage/index.rst | 1 + include/bootstage.h | 9 ++++ test/cmd/bootstage.c | 24 +++++++++++ 6 files changed, 159 insertions(+) create mode 100644 doc/usage/cmd/bootstage.rst diff --git a/boot/Kconfig b/boot/Kconfig index cd66060f4db..d9d5214ca0f 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -1479,6 +1479,17 @@ config BOOTSTAGE_FDT Code in the Linux kernel can find this in /proc/devicetree. +config BOOTSTAGE_SAVE + bool "Allow saving and restoring the bootstage record count" + depends on BOOTSTAGE + default y if UNIT_TEST + help + Provide 'bootstage save' and 'bootstage restore' subcommands + which store and retrieve the record count via the bootstage_count + environment variable. These are used by Python tests to prevent + records from accumulating across tests and filling the bootstage + table. + config BOOTSTAGE_STASH bool "Stash the boot timing information in memory before booting OS" depends on BOOTSTAGE diff --git a/cmd/bootstage.c b/cmd/bootstage.c index 5c6d5a3ab45..ce69097b96c 100644 --- a/cmd/bootstage.c +++ b/cmd/bootstage.c @@ -5,6 +5,7 @@ #include <bootstage.h> #include <command.h> +#include <env.h> #include <vsprintf.h> #include <linux/string.h> @@ -62,8 +63,31 @@ static int do_bootstage_stash(struct cmd_tbl *cmdtp, int flag, int argc, } #endif +static int __maybe_unused do_bootstage_save(struct cmd_tbl *cmdtp, int flag, + int argc, char *const argv[]) +{ + env_set_hex("bootstage_count", bootstage_get_rec_count()); + + return 0; +} + +static int __maybe_unused do_bootstage_restore(struct cmd_tbl *cmdtp, int flag, + int argc, char *const argv[]) +{ + ulong count = env_get_hex("bootstage_count", 0); + + if (count) + bootstage_set_rec_count(count); + + return 0; +} + static struct cmd_tbl cmd_bootstage_sub[] = { U_BOOT_CMD_MKENT(report, 2, 1, do_bootstage_report, "", ""), +#if IS_ENABLED(CONFIG_BOOTSTAGE_SAVE) + U_BOOT_CMD_MKENT(save, 1, 0, do_bootstage_save, "", ""), + U_BOOT_CMD_MKENT(restore, 1, 0, do_bootstage_restore, "", ""), +#endif #if IS_ENABLED(CONFIG_BOOTSTAGE_STASH) U_BOOT_CMD_MKENT(stash, 4, 0, do_bootstage_stash, "", ""), U_BOOT_CMD_MKENT(unstash, 4, 0, do_bootstage_stash, "", ""), @@ -95,6 +119,10 @@ U_BOOT_CMD(bootstage, 4, 1, do_boostage, "Boot stage command", " - check boot progress and timing\n" "report - Print a report\n" +#if IS_ENABLED(CONFIG_BOOTSTAGE_SAVE) + "save - Save record count to $bootstage_count\n" + "restore - Restore record count from $bootstage_count\n" +#endif #if IS_ENABLED(CONFIG_BOOTSTAGE_STASH) "stash [<start> [<size>]] - Stash data into memory\n" "unstash [<start> [<size>]] - Unstash data from memory\n" diff --git a/doc/usage/cmd/bootstage.rst b/doc/usage/cmd/bootstage.rst new file mode 100644 index 00000000000..44069e6fedd --- /dev/null +++ b/doc/usage/cmd/bootstage.rst @@ -0,0 +1,86 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +.. index:: + single: bootstage (command) + +bootstage command +================= + +Synopsis +-------- + +:: + + bootstage report + bootstage save + bootstage restore + bootstage stash [<start> [<size>]] + bootstage unstash [<start> [<size>]] + +Description +----------- + +The *bootstage* command provides access to U-Boot's boot-timing records. + +bootstage report + Print a report of all bootstage records, showing the timestamp and elapsed + time for each stage. + +bootstage save + Save the current record count to the *bootstage_count* environment + variable. This can be used to snapshot the bootstage state before an + operation that adds records. + +bootstage restore + Restore the record count from *bootstage_count*, discarding any records + added since the last save. This is used by the Python test framework to + prevent records from accumulating across tests. + +bootstage stash + Stash bootstage data into memory at the given address and size. + Only available when ``CONFIG_BOOTSTAGE_STASH`` is enabled. + +bootstage unstash + Read back previously stashed bootstage data from memory. + Only available when ``CONFIG_BOOTSTAGE_STASH`` is enabled. + +Configuration +------------- + +The *bootstage* command is available when ``CONFIG_BOOTSTAGE`` is enabled. + +CONFIG_BOOTSTAGE_REPORT + Enable output of a boot-time report before booting the OS. + +CONFIG_BOOTSTAGE_RECORD_COUNT + Number of bootstage records to store (default 50). + +CONFIG_BOOTSTAGE_SAVE + Enable the *save* and *restore* subcommands. Default y when + ``CONFIG_UNIT_TEST`` is set. + +CONFIG_BOOTSTAGE_STASH + Enable the *stash* and *unstash* subcommands for passing bootstage + data to the OS via memory. + +Example +------- + +:: + + => bootstage report + Timer summary in microseconds (8 records): + Mark Elapsed Stage + 0 0 reset + 0 0 board_init_f + 29,743 29,743 board_init_r + 52,918 23,175 eth_common_init + 53,007 89 eth_initialize + + Accumulated time: + 1,235 dm_f + 670 of_live + 5,621 dm_r + + => bootstage save + => bootstage restore diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 05e1828bf01..ecf0ba16700 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -49,6 +49,7 @@ Shell commands cmd/bootm cmd/bootmenu cmd/bootmeth + cmd/bootstage cmd/bootstd cmd/bootz cmd/button diff --git a/include/bootstage.h b/include/bootstage.h index da57f9b81c5..30858cbfb3f 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -519,6 +519,15 @@ static inline int bootstage_init(bool first) return 0; } +static inline uint bootstage_get_rec_count(void) +{ + return 0; +} + +static inline void bootstage_set_rec_count(uint count) +{ +} + #endif /* ENABLE_BOOTSTAGE */ /* helpers for SPL */ diff --git a/test/cmd/bootstage.c b/test/cmd/bootstage.c index dee4a0671fa..29df4725d1f 100644 --- a/test/cmd/bootstage.c +++ b/test/cmd/bootstage.c @@ -30,3 +30,27 @@ static int cmd_bootstage_report(struct unit_test_state *uts) return 0; } CMD_TEST(cmd_bootstage_report, UTF_CONSOLE); + +static int cmd_bootstage_save_restore(struct unit_test_state *uts) +{ + uint count; + + count = bootstage_get_rec_count(); + ut_assert(count > 0); + + /* Save the current count */ + ut_assertok(run_command("bootstage save", 0)); + ut_assert_console_end(); + + /* Add a new record and check the count grows by one */ + bootstage_mark_name(BOOTSTAGE_ID_USER + 60, "test_save_restore"); + ut_asserteq(count + 1, bootstage_get_rec_count()); + + /* Restore should bring the count back */ + ut_assertok(run_command("bootstage restore", 0)); + ut_assert_console_end(); + ut_asserteq(count, bootstage_get_rec_count()); + + return 0; +} +CMD_TEST(cmd_bootstage_save_restore, UTF_CONSOLE); -- 2.43.0