Commit b79015ae authored by Vasily Gorbik's avatar Vasily Gorbik Committed by Alexander Gordeev
Browse files

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: default avatarVasily Gorbik <gor@linux.ibm.com>
Acked-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
parent d20d8e51
Loading
Loading
Loading
Loading
+12 −8
Original line number Diff line number Diff line
@@ -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;
+4 −1
Original line number Diff line number Diff line
@@ -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"))
+4 −2
Original line number Diff line number Diff line
@@ -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)				\
+25 −0
Original line number Diff line number Diff line
/* 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 */
+5 −3
Original line number Diff line number Diff line
@@ -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);
}

/*