1// SPDX-License-Identifier: GPL-2.0
2#include <linux/kernel.h>
3#include <linux/string.h>
4#include <asm/lowcore.h>
5#include <asm/setup.h>
6#include <asm/sclp.h>
7#include "boot.h"
8
9const char hex_asc[] = "0123456789abcdef";
10
11#define add_val_as_hex(dst, val)					       \
12	__add_val_as_hex(dst, (const unsigned char *)&val, sizeof(val))
13
14static char *__add_val_as_hex(char *dst, const unsigned char *src, size_t count)
15{
16	while (count--)
17		dst = hex_byte_pack(dst, *src++);
18	return dst;
19}
20
21static char *add_str(char *dst, char *src)
22{
23	strcpy(dst, src);
24	return dst + strlen(dst);
25}
26
27void print_pgm_check_info(void)
28{
29	struct psw_bits *psw = &psw_bits(S390_lowcore.psw_save_area);
30	unsigned short ilc = S390_lowcore.pgm_ilc >> 1;
31	char buf[256];
32	int row, col;
33	char *p;
34
35	add_str(buf, "Linux version ");
36	strlcat(buf, kernel_version, sizeof(buf) - 1);
37	strlcat(buf, "\n", sizeof(buf));
38	sclp_early_printk(buf);
39
40	p = add_str(buf, "Kernel fault: interruption code ");
41	p = add_val_as_hex(buf + strlen(buf), S390_lowcore.pgm_code);
42	p = add_str(p, " ilc:");
43	*p++ = hex_asc_lo(ilc);
44	add_str(p, "\n");
45	sclp_early_printk(buf);
46
47	if (kaslr_enabled) {
48		p = add_str(buf, "Kernel random base: ");
49		p = add_val_as_hex(p, __kaslr_offset);
50		add_str(p, "\n");
51		sclp_early_printk(buf);
52	}
53
54	p = add_str(buf, "PSW : ");
55	p = add_val_as_hex(p, S390_lowcore.psw_save_area.mask);
56	p = add_str(p, " ");
57	p = add_val_as_hex(p, S390_lowcore.psw_save_area.addr);
58	add_str(p, "\n");
59	sclp_early_printk(buf);
60
61	p = add_str(buf, "      R:");
62	*p++ = hex_asc_lo(psw->per);
63	p = add_str(p, " T:");
64	*p++ = hex_asc_lo(psw->dat);
65	p = add_str(p, " IO:");
66	*p++ = hex_asc_lo(psw->io);
67	p = add_str(p, " EX:");
68	*p++ = hex_asc_lo(psw->ext);
69	p = add_str(p, " Key:");
70	*p++ = hex_asc_lo(psw->key);
71	p = add_str(p, " M:");
72	*p++ = hex_asc_lo(psw->mcheck);
73	p = add_str(p, " W:");
74	*p++ = hex_asc_lo(psw->wait);
75	p = add_str(p, " P:");
76	*p++ = hex_asc_lo(psw->pstate);
77	p = add_str(p, " AS:");
78	*p++ = hex_asc_lo(psw->as);
79	p = add_str(p, " CC:");
80	*p++ = hex_asc_lo(psw->cc);
81	p = add_str(p, " PM:");
82	*p++ = hex_asc_lo(psw->pm);
83	p = add_str(p, " RI:");
84	*p++ = hex_asc_lo(psw->ri);
85	p = add_str(p, " EA:");
86	*p++ = hex_asc_lo(psw->eaba);
87	add_str(p, "\n");
88	sclp_early_printk(buf);
89
90	for (row = 0; row < 4; row++) {
91		p = add_str(buf, row == 0 ? "GPRS:" : "     ");
92		for (col = 0; col < 4; col++) {
93			p = add_str(p, " ");
94			p = add_val_as_hex(p, S390_lowcore.gpregs_save_area[row * 4 + col]);
95		}
96		add_str(p, "\n");
97		sclp_early_printk(buf);
98	}
99}
100