]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
s390/boot: Add prefix filtering to bootdebug messages
authorVasily Gorbik <gor@linux.ibm.com>
Fri, 22 Nov 2024 23:02:25 +0000 (00:02 +0100)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Sun, 26 Jan 2025 16:24:01 +0000 (17:24 +0100)
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 <gor@linux.ibm.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
arch/s390/boot/boot.h
arch/s390/boot/ipl_parm.c
arch/s390/boot/printk.c
arch/s390/include/asm/boot_data.h
arch/s390/kernel/setup.c

index dbfba6822d6fdcf9b2457e3f5841ff53fef5fdd6..688fa75f865168e34b27295474d24cd67ec8a2ac 100644 (file)
@@ -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;
index 397046f0c1dfeaec75cead45765b491d7c5e9d23..d3731f2983b77c6eb8f0158a6be04b983eda5fa8 100644 (file)
@@ -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"))
index 4c60245697ab00b9c9d55a267cc205e7bd2ad089..092114e469376d47c7a74df08ccb0ee264a8471d 100644 (file)
@@ -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)                         \
index da5527c50738e8a911ab4c85ccaa846ea3272c4b..73c441f5e99aefaf0648bd21b79da8c7748aba56 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 #ifndef _ASM_S390_BOOT_DATA_H
 
+#include <linux/string.h>
 #include <asm/setup.h>
 #include <asm/ipl.h>
 
@@ -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 */
index dd0979182890e131d46c290f926b2111a8aad205..74e2ee75b18965437143f30829952debe893d436 100644 (file)
@@ -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);
 }
 
 /*