diff options
Diffstat (limited to 'arch/s390/boot/pgm_check_info.c')
| -rw-r--r-- | arch/s390/boot/pgm_check_info.c | 90 | 
1 files changed, 90 insertions, 0 deletions
diff --git a/arch/s390/boot/pgm_check_info.c b/arch/s390/boot/pgm_check_info.c new file mode 100644 index 000000000000..83b5b7915c32 --- /dev/null +++ b/arch/s390/boot/pgm_check_info.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/kernel.h> +#include <linux/string.h> +#include <asm/lowcore.h> +#include <asm/sclp.h> +#include "boot.h" + +const char hex_asc[] = "0123456789abcdef"; + +#define add_val_as_hex(dst, val)					       \ +	__add_val_as_hex(dst, (const unsigned char *)&val, sizeof(val)) + +static char *__add_val_as_hex(char *dst, const unsigned char *src, size_t count) +{ +	while (count--) +		dst = hex_byte_pack(dst, *src++); +	return dst; +} + +static char *add_str(char *dst, char *src) +{ +	strcpy(dst, src); +	return dst + strlen(dst); +} + +void print_pgm_check_info(void) +{ +	struct psw_bits *psw = &psw_bits(S390_lowcore.psw_save_area); +	unsigned short ilc = S390_lowcore.pgm_ilc >> 1; +	char buf[256]; +	int row, col; +	char *p; + +	add_str(buf, "Linux version "); +	strlcat(buf, kernel_version, sizeof(buf)); +	sclp_early_printk(buf); + +	p = add_str(buf, "Kernel fault: interruption code "); +	p = add_val_as_hex(buf + strlen(buf), S390_lowcore.pgm_code); +	p = add_str(p, " ilc:"); +	*p++ = hex_asc_lo(ilc); +	add_str(p, "\n"); +	sclp_early_printk(buf); + +	p = add_str(buf, "PSW : "); +	p = add_val_as_hex(p, S390_lowcore.psw_save_area.mask); +	p = add_str(p, " "); +	p = add_val_as_hex(p, S390_lowcore.psw_save_area.addr); +	add_str(p, "\n"); +	sclp_early_printk(buf); + +	p = add_str(buf, "      R:"); +	*p++ = hex_asc_lo(psw->per); +	p = add_str(p, " T:"); +	*p++ = hex_asc_lo(psw->dat); +	p = add_str(p, " IO:"); +	*p++ = hex_asc_lo(psw->io); +	p = add_str(p, " EX:"); +	*p++ = hex_asc_lo(psw->ext); +	p = add_str(p, " Key:"); +	*p++ = hex_asc_lo(psw->key); +	p = add_str(p, " M:"); +	*p++ = hex_asc_lo(psw->mcheck); +	p = add_str(p, " W:"); +	*p++ = hex_asc_lo(psw->wait); +	p = add_str(p, " P:"); +	*p++ = hex_asc_lo(psw->pstate); +	p = add_str(p, " AS:"); +	*p++ = hex_asc_lo(psw->as); +	p = add_str(p, " CC:"); +	*p++ = hex_asc_lo(psw->cc); +	p = add_str(p, " PM:"); +	*p++ = hex_asc_lo(psw->pm); +	p = add_str(p, " RI:"); +	*p++ = hex_asc_lo(psw->ri); +	p = add_str(p, " EA:"); +	*p++ = hex_asc_lo(psw->eaba); +	add_str(p, "\n"); +	sclp_early_printk(buf); + +	for (row = 0; row < 4; row++) { +		p = add_str(buf, row == 0 ? "GPRS:" : "     "); +		for (col = 0; col < 4; col++) { +			p = add_str(p, " "); +			p = add_val_as_hex(p, S390_lowcore.gpregs_save_area[row * 4 + col]); +		} +		add_str(p, "\n"); +		sclp_early_printk(buf); +	} +}  |