Commit b5e80459 authored by Vasily Gorbik's avatar Vasily Gorbik Committed by Martin Schwidefsky
Browse files

s390: allow overriding facilities via command line



Add "facilities=" command line option which allows to override
facility bits returned by stfle. The main purpose of that is debugging
aids which allows to test specific kernel behaviour depending on
specific facilities presence. It also affects CPU alternatives.

"facilities=" command line option format is comma separated list of
integer values to be additionally set or cleared (if value is starting
with "!"). Values ranges are also supported. e.g.:

facilities=!130-160,159,167-169

Reviewed-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent d8901f2b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ void startup_kernel(void);
void detect_memory(void);
void store_ipl_parmblock(void);
void setup_boot_command_line(void);
void parse_boot_command_line(void);
void setup_memory_end(void);

#endif /* BOOT_BOOT_H */
+48 −2
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include <asm/sclp.h>
#include <asm/sections.h>
#include <asm/boot_data.h>
#include <asm/facility.h>
#include "boot.h"

char __bootdata(early_command_line)[COMMAND_LINE_SIZE];
@@ -143,8 +144,51 @@ void setup_boot_command_line(void)
		append_ipl_block_parm();
}

static void modify_facility(unsigned long nr, bool clear)
{
	if (clear)
		__clear_facility(nr, S390_lowcore.stfle_fac_list);
	else
		__set_facility(nr, S390_lowcore.stfle_fac_list);
}

static void modify_fac_list(char *str)
{
	unsigned long val, endval;
	char *endp;
	bool clear;

	while (*str) {
		clear = false;
		if (*str == '!') {
			clear = true;
			str++;
		}
		val = simple_strtoull(str, &endp, 0);
		if (str == endp)
			break;
		str = endp;
		if (*str == '-') {
			str++;
			endval = simple_strtoull(str, &endp, 0);
			if (str == endp)
				break;
			str = endp;
			while (val <= endval) {
				modify_facility(val, clear);
				val++;
			}
		} else {
			modify_facility(val, clear);
		}
		if (*str != ',')
			break;
		str++;
	}
}

static char command_line_buf[COMMAND_LINE_SIZE] __section(.data);
static void parse_mem_opt(void)
void parse_boot_command_line(void)
{
	char *param, *val;
	bool enabled;
@@ -165,12 +209,14 @@ static void parse_mem_opt(void)
			if (!rc && !enabled)
				noexec_disabled = 1;
		}

		if (!strcmp(param, "facilities"))
			modify_fac_list(val);
	}
}

void setup_memory_end(void)
{
	parse_mem_opt();
#ifdef CONFIG_CRASH_DUMP
	if (!OLDMEM_BASE && early_ipl_block_valid &&
	    early_ipl_block.hdr.pbt == DIAG308_IPL_TYPE_FCP &&
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ void startup_kernel(void)
	sclp_early_read_info();
	store_ipl_parmblock();
	setup_boot_command_line();
	parse_boot_command_line();
	setup_memory_end();
	detect_memory();
	if (!IS_ENABLED(CONFIG_KERNEL_UNCOMPRESSED)) {