18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/kernel.h>
38c2ecf20Sopenharmony_ci#include <linux/string.h>
48c2ecf20Sopenharmony_ci#include <asm/lowcore.h>
58c2ecf20Sopenharmony_ci#include <asm/setup.h>
68c2ecf20Sopenharmony_ci#include <asm/sclp.h>
78c2ecf20Sopenharmony_ci#include "boot.h"
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ciconst char hex_asc[] = "0123456789abcdef";
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#define add_val_as_hex(dst, val)					       \
128c2ecf20Sopenharmony_ci	__add_val_as_hex(dst, (const unsigned char *)&val, sizeof(val))
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic char *__add_val_as_hex(char *dst, const unsigned char *src, size_t count)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	while (count--)
178c2ecf20Sopenharmony_ci		dst = hex_byte_pack(dst, *src++);
188c2ecf20Sopenharmony_ci	return dst;
198c2ecf20Sopenharmony_ci}
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistatic char *add_str(char *dst, char *src)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	strcpy(dst, src);
248c2ecf20Sopenharmony_ci	return dst + strlen(dst);
258c2ecf20Sopenharmony_ci}
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_civoid print_pgm_check_info(void)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	struct psw_bits *psw = &psw_bits(S390_lowcore.psw_save_area);
308c2ecf20Sopenharmony_ci	unsigned short ilc = S390_lowcore.pgm_ilc >> 1;
318c2ecf20Sopenharmony_ci	char buf[256];
328c2ecf20Sopenharmony_ci	int row, col;
338c2ecf20Sopenharmony_ci	char *p;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	add_str(buf, "Linux version ");
368c2ecf20Sopenharmony_ci	strlcat(buf, kernel_version, sizeof(buf) - 1);
378c2ecf20Sopenharmony_ci	strlcat(buf, "\n", sizeof(buf));
388c2ecf20Sopenharmony_ci	sclp_early_printk(buf);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	p = add_str(buf, "Kernel fault: interruption code ");
418c2ecf20Sopenharmony_ci	p = add_val_as_hex(buf + strlen(buf), S390_lowcore.pgm_code);
428c2ecf20Sopenharmony_ci	p = add_str(p, " ilc:");
438c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(ilc);
448c2ecf20Sopenharmony_ci	add_str(p, "\n");
458c2ecf20Sopenharmony_ci	sclp_early_printk(buf);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	if (kaslr_enabled) {
488c2ecf20Sopenharmony_ci		p = add_str(buf, "Kernel random base: ");
498c2ecf20Sopenharmony_ci		p = add_val_as_hex(p, __kaslr_offset);
508c2ecf20Sopenharmony_ci		add_str(p, "\n");
518c2ecf20Sopenharmony_ci		sclp_early_printk(buf);
528c2ecf20Sopenharmony_ci	}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	p = add_str(buf, "PSW : ");
558c2ecf20Sopenharmony_ci	p = add_val_as_hex(p, S390_lowcore.psw_save_area.mask);
568c2ecf20Sopenharmony_ci	p = add_str(p, " ");
578c2ecf20Sopenharmony_ci	p = add_val_as_hex(p, S390_lowcore.psw_save_area.addr);
588c2ecf20Sopenharmony_ci	add_str(p, "\n");
598c2ecf20Sopenharmony_ci	sclp_early_printk(buf);
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	p = add_str(buf, "      R:");
628c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->per);
638c2ecf20Sopenharmony_ci	p = add_str(p, " T:");
648c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->dat);
658c2ecf20Sopenharmony_ci	p = add_str(p, " IO:");
668c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->io);
678c2ecf20Sopenharmony_ci	p = add_str(p, " EX:");
688c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->ext);
698c2ecf20Sopenharmony_ci	p = add_str(p, " Key:");
708c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->key);
718c2ecf20Sopenharmony_ci	p = add_str(p, " M:");
728c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->mcheck);
738c2ecf20Sopenharmony_ci	p = add_str(p, " W:");
748c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->wait);
758c2ecf20Sopenharmony_ci	p = add_str(p, " P:");
768c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->pstate);
778c2ecf20Sopenharmony_ci	p = add_str(p, " AS:");
788c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->as);
798c2ecf20Sopenharmony_ci	p = add_str(p, " CC:");
808c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->cc);
818c2ecf20Sopenharmony_ci	p = add_str(p, " PM:");
828c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->pm);
838c2ecf20Sopenharmony_ci	p = add_str(p, " RI:");
848c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->ri);
858c2ecf20Sopenharmony_ci	p = add_str(p, " EA:");
868c2ecf20Sopenharmony_ci	*p++ = hex_asc_lo(psw->eaba);
878c2ecf20Sopenharmony_ci	add_str(p, "\n");
888c2ecf20Sopenharmony_ci	sclp_early_printk(buf);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	for (row = 0; row < 4; row++) {
918c2ecf20Sopenharmony_ci		p = add_str(buf, row == 0 ? "GPRS:" : "     ");
928c2ecf20Sopenharmony_ci		for (col = 0; col < 4; col++) {
938c2ecf20Sopenharmony_ci			p = add_str(p, " ");
948c2ecf20Sopenharmony_ci			p = add_val_as_hex(p, S390_lowcore.gpregs_save_area[row * 4 + col]);
958c2ecf20Sopenharmony_ci		}
968c2ecf20Sopenharmony_ci		add_str(p, "\n");
978c2ecf20Sopenharmony_ci		sclp_early_printk(buf);
988c2ecf20Sopenharmony_ci	}
998c2ecf20Sopenharmony_ci}
100