[PATCH] log: fixup log_head after relocating global data

When `gd` is relocated during `spl_relocate_stack_gd()` the doubly-linked circular list in the `log_head` member is broken.
The last element of the list should point back to the initial `list_head`, but as the initial `list_head` is moved the pointer becomes stale. As a result the loop in `log_dispatch` would never finish.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de --- This patch is a simpler alternative to https://lore.kernel.org/u-boot/20240212-spl-logging-v1-1-051cde837559@linutr...
This patch should also remove the special handling introduced in commit e7595aa350ae ("x86: Allow logging to be used in SPL reliably"). --- common/log.c | 4 ++++ common/spl/spl.c | 3 +++ include/log.h | 12 ++++++++++++ 3 files changed, 19 insertions(+)
diff --git a/common/log.c b/common/log.c index b2de57fcb3b8..0ca2d1b4c8bc 100644 --- a/common/log.c +++ b/common/log.c @@ -428,6 +428,10 @@ int log_device_set_enable(struct log_driver *drv, bool enable) return 0; }
+void log_fixup_for_gd_move(struct global_data *new_gd) { + new_gd->log_head.prev->next = &new_gd->log_head; +} + int log_init(void) { struct log_driver *drv = ll_entry_start(struct log_driver, log_driver); diff --git a/common/spl/spl.c b/common/spl/spl.c index b65c439e7aa9..e06bc75d36b2 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -909,6 +909,9 @@ ulong spl_relocate_stack_gd(void) #if CONFIG_IS_ENABLED(DM) dm_fixup_for_gd_move(new_gd); #endif +#if CONFIG_IS_ENABLED(LOG) + log_fixup_for_gd_move(new_gd); +#endif #if !defined(CONFIG_ARM) && !defined(CONFIG_RISCV) gd = new_gd; #endif diff --git a/include/log.h b/include/log.h index 6e84f080ef3d..fc0d59844728 100644 --- a/include/log.h +++ b/include/log.h @@ -688,4 +688,16 @@ static inline int log_get_default_format(void) (IS_ENABLED(CONFIG_LOGF_FUNC) ? BIT(LOGF_FUNC) : 0); }
+struct global_data; +/** + * log_fixup_for_gd_move() - Handle global_data moving to a new place + * + * @new_gd: Pointer to the new global data + * + * The log_head list is part of global_data. Due to the way lists work, moving + * the list will cause it to become invalid. This function fixes that up so + * that the log_head list will work correctly. + */ +void log_fixup_for_gd_move(struct global_data *new_gd); + #endif
--- base-commit: 73b5b47dd5b546d0b9106bcca54c72815380e6d3 change-id: 20240213-spl-logging-2-43a81ae0f147
Best regards,

On Tue, Feb 13, 2024 at 06:13:28PM +0100, Thomas Weißschuh wrote:
When `gd` is relocated during `spl_relocate_stack_gd()` the doubly-linked circular list in the `log_head` member is broken.
The last element of the list should point back to the initial `list_head`, but as the initial `list_head` is moved the pointer becomes stale. As a result the loop in `log_dispatch` would never finish.
Signed-off-by: Thomas Weißschuh thomas.weissschuh@linutronix.de
Applied to u-boot/next, thanks!
participants (2)
-
Thomas Weißschuh
-
Tom Rini