From b79015ae63d3c91f06ab78b6f06abba94fd88e12 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Sat, 23 Nov 2024 00:02:25 +0100 Subject: [PATCH] s390/boot: Add prefix filtering to bootdebug messages Enhance boot debugging by allowing the "bootdebug" kernel parameter to accept an optional comma-separated list of prefixes. Only debug messages starting with these prefixes will be printed during boot. For example: bootdebug=startup,vmem Not specifying a filter for the "bootdebug" parameter prints all debug messages. The `boot_fmt` macro can be defined to set a common prefix: #define boot_fmt(fmt) "startup: " fmt Signed-off-by: Vasily Gorbik Acked-by: Heiko Carstens Signed-off-by: Alexander Gordeev --- arch/s390/boot/boot.h | 20 ++++++++++++-------- arch/s390/boot/ipl_parm.c | 5 ++++- arch/s390/boot/printk.c | 6 ++++-- arch/s390/include/asm/boot_data.h | 25 +++++++++++++++++++++++++ arch/s390/kernel/setup.c | 8 +++++--- 5 files changed, 50 insertions(+), 14 deletions(-) diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h index dbfba6822d6f..688fa75f8651 100644 --- a/arch/s390/boot/boot.h +++ b/arch/s390/boot/boot.h @@ -77,14 +77,18 @@ void print_stacktrace(unsigned long sp); void error(char *m); int get_random(unsigned long limit, unsigned long *value); -#define boot_emerg(fmt, ...) boot_printk(KERN_EMERG fmt, ##__VA_ARGS__) -#define boot_alert(fmt, ...) boot_printk(KERN_ALERT fmt, ##__VA_ARGS__) -#define boot_crit(fmt, ...) boot_printk(KERN_CRIT fmt, ##__VA_ARGS__) -#define boot_err(fmt, ...) boot_printk(KERN_ERR fmt, ##__VA_ARGS__) -#define boot_warn(fmt, ...) boot_printk(KERN_WARNING fmt, ##__VA_ARGS__) -#define boot_notice(fmt, ...) boot_printk(KERN_NOTICE fmt, ##__VA_ARGS__) -#define boot_info(fmt, ...) boot_printk(KERN_INFO fmt, ##__VA_ARGS__) -#define boot_debug(fmt, ...) boot_printk(KERN_DEBUG fmt, ##__VA_ARGS__) +#ifndef boot_fmt +#define boot_fmt(fmt) fmt +#endif + +#define boot_emerg(fmt, ...) boot_printk(KERN_EMERG boot_fmt(fmt), ##__VA_ARGS__) +#define boot_alert(fmt, ...) boot_printk(KERN_ALERT boot_fmt(fmt), ##__VA_ARGS__) +#define boot_crit(fmt, ...) boot_printk(KERN_CRIT boot_fmt(fmt), ##__VA_ARGS__) +#define boot_err(fmt, ...) boot_printk(KERN_ERR boot_fmt(fmt), ##__VA_ARGS__) +#define boot_warn(fmt, ...) boot_printk(KERN_WARNING boot_fmt(fmt), ##__VA_ARGS__) +#define boot_notice(fmt, ...) boot_printk(KERN_NOTICE boot_fmt(fmt), ##__VA_ARGS__) +#define boot_info(fmt, ...) boot_printk(KERN_INFO boot_fmt(fmt), ##__VA_ARGS__) +#define boot_debug(fmt, ...) boot_printk(KERN_DEBUG boot_fmt(fmt), ##__VA_ARGS__) extern struct machine_info machine; extern int boot_console_loglevel; diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c index 397046f0c1df..d3731f2983b7 100644 --- a/arch/s390/boot/ipl_parm.c +++ b/arch/s390/boot/ipl_parm.c @@ -317,8 +317,11 @@ void parse_boot_command_line(void) boot_earlyprintk = true; if (!strcmp(param, "debug")) boot_console_loglevel = CONSOLE_LOGLEVEL_DEBUG; - if (!strcmp(param, "bootdebug")) + if (!strcmp(param, "bootdebug")) { bootdebug = true; + if (val) + strncpy(bootdebug_filter, val, sizeof(bootdebug_filter) - 1); + } if (!strcmp(param, "quiet")) boot_console_loglevel = CONSOLE_LOGLEVEL_QUIET; if (!strcmp(param, "ignore_loglevel")) diff --git a/arch/s390/boot/printk.c b/arch/s390/boot/printk.c index 4c60245697ab..092114e46937 100644 --- a/arch/s390/boot/printk.c +++ b/arch/s390/boot/printk.c @@ -17,6 +17,7 @@ bool boot_ignore_loglevel; char __bootdata(boot_rb)[PAGE_SIZE * 2]; bool __bootdata(boot_earlyprintk); size_t __bootdata(boot_rb_off); +char __bootdata(bootdebug_filter)[128]; bool __bootdata(bootdebug); static void boot_rb_add(const char *str, size_t len) @@ -169,11 +170,12 @@ static void boot_console_earlyprintk(const char *buf) /* always print emergency messages */ if (level > LOGLEVEL_EMERG && !boot_earlyprintk) return; + buf = printk_skip_level(buf); /* print debug messages only when bootdebug is enabled */ - if (level == LOGLEVEL_DEBUG && !bootdebug) + if (level == LOGLEVEL_DEBUG && (!bootdebug || !bootdebug_filter_match(buf))) return; if (boot_ignore_loglevel || level < boot_console_loglevel) - sclp_early_printk(printk_skip_level(buf)); + sclp_early_printk(buf); } #define va_arg_len_type(args, lenmod, typemod) \ diff --git a/arch/s390/include/asm/boot_data.h b/arch/s390/include/asm/boot_data.h index da5527c50738..73c441f5e99a 100644 --- a/arch/s390/include/asm/boot_data.h +++ b/arch/s390/include/asm/boot_data.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef _ASM_S390_BOOT_DATA_H +#include #include #include @@ -18,6 +19,7 @@ extern unsigned long early_ipl_comp_list_size; extern char boot_rb[PAGE_SIZE * 2]; extern bool boot_earlyprintk; extern size_t boot_rb_off; +extern char bootdebug_filter[128]; extern bool bootdebug; #define boot_rb_foreach(cb) \ @@ -30,4 +32,27 @@ extern bool bootdebug; cb(boot_rb + off); \ } while (0) +/* + * bootdebug_filter is a comma separated list of strings, + * where each string can be a prefix of the message. + */ +static inline bool bootdebug_filter_match(const char *buf) +{ + char *p = bootdebug_filter, *s; + char *end; + + if (!*p) + return true; + + end = p + strlen(p); + while (p < end) { + p = skip_spaces(p); + s = memscan(p, ',', end - p); + if (!strncmp(p, buf, s - p)) + return true; + p = s + 1; + } + return false; +} + #endif /* _ASM_S390_BOOT_DATA_H */ diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index dd0979182890..74e2ee75b189 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -160,6 +160,7 @@ struct oldmem_data __bootdata_preserved(oldmem_data); char __bootdata(boot_rb)[PAGE_SIZE * 2]; bool __bootdata(boot_earlyprintk); size_t __bootdata(boot_rb_off); +char __bootdata(bootdebug_filter)[128]; bool __bootdata(bootdebug); unsigned long __bootdata_preserved(VMALLOC_START); @@ -886,16 +887,17 @@ static void __init log_component_list(void) * Print avoiding interpretation of % in buf and taking bootdebug option * into consideration. */ -static void __init print_rb_entry(char *buf) +static void __init print_rb_entry(const char *buf) { char fmt[] = KERN_SOH "0boot: %s"; int level = printk_get_level(buf); - if (level == KERN_DEBUG[1] && !bootdebug) + buf = printk_skip_level(buf); + if (level == KERN_DEBUG[1] && (!bootdebug || !bootdebug_filter_match(buf))) return; fmt[1] = level; - printk(fmt, printk_skip_level(buf)); + printk(fmt, buf); } /*