xref: /linux/arch/s390/boot/alternative.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0
2 #define boot_fmt(fmt)	"alt: " fmt
3 #include "boot.h"
4 
5 #define a_debug		boot_debug
6 
7 #include "../kernel/alternative.c"
8 
9 static void alt_debug_all(int type)
10 {
11 	int i;
12 
13 	switch (type) {
14 	case ALT_TYPE_FACILITY:
15 		for (i = 0; i < ARRAY_SIZE(alt_debug.facilities); i++)
16 			alt_debug.facilities[i] = -1UL;
17 		break;
18 	case ALT_TYPE_FEATURE:
19 		for (i = 0; i < ARRAY_SIZE(alt_debug.mfeatures); i++)
20 			alt_debug.mfeatures[i] = -1UL;
21 		break;
22 	case ALT_TYPE_SPEC:
23 		alt_debug.spec = 1;
24 		break;
25 	}
26 }
27 
28 static void alt_debug_modify(int type, unsigned int nr, bool clear)
29 {
30 	switch (type) {
31 	case ALT_TYPE_FACILITY:
32 		if (clear)
33 			__clear_facility(nr, alt_debug.facilities);
34 		else
35 			__set_facility(nr, alt_debug.facilities);
36 		break;
37 	case ALT_TYPE_FEATURE:
38 		if (clear)
39 			__clear_machine_feature(nr, alt_debug.mfeatures);
40 		else
41 			__set_machine_feature(nr, alt_debug.mfeatures);
42 		break;
43 	}
44 }
45 
46 static char *alt_debug_parse(int type, char *str)
47 {
48 	unsigned long val, endval, limit;
49 	char *endp;
50 	bool clear;
51 	int i;
52 
53 	limit = type == ALT_TYPE_FACILITY ? MAX_FACILITY_BIT : MAX_MFEATURE_BIT;
54 	if (*str == ':') {
55 		str++;
56 	} else {
57 		alt_debug_all(type);
58 		return str;
59 	}
60 	clear = false;
61 	if (*str == '!') {
62 		alt_debug_all(type);
63 		clear = true;
64 		str++;
65 	}
66 	while (*str) {
67 		val = simple_strtoull(str, &endp, 0);
68 		if (str == endp)
69 			break;
70 		str = endp;
71 		if (*str == '-') {
72 			str++;
73 			endval = simple_strtoull(str, &endp, 0);
74 			if (str == endp)
75 				break;
76 			str = endp;
77 			while (val <= endval && val < limit) {
78 				alt_debug_modify(type, val, clear);
79 				val++;
80 			}
81 		} else {
82 			alt_debug_modify(type, val, clear);
83 		}
84 		if (*str != ',')
85 			break;
86 		str++;
87 	}
88 	return str;
89 }
90 
91 /*
92  * Use debug-alternative command line parameter for debugging:
93  * "debug-alternative"
94  *  -> print debug message for every single alternative
95  *
96  * "debug-alternative=0;2"
97  * -> print debug message for all alternatives with type 0 and 2
98  *
99  * "debug-alternative=0:0-7"
100  * -> print debug message for all alternatives with type 0 and with
101  *    facility numbers within the range of 0-7
102  *    (if type 0 is ALT_TYPE_FACILITY)
103  *
104  * "debug-alternative=0:!8;1"
105  * -> print debug message for all alternatives with type 0, for all
106  *    facility number, except facility 8, and in addition print all
107  *    alternatives with type 1
108  */
109 void alt_debug_setup(char *str)
110 {
111 	unsigned long type;
112 	char *endp;
113 	int i;
114 
115 	if (!str) {
116 		alt_debug_all(ALT_TYPE_FACILITY);
117 		alt_debug_all(ALT_TYPE_FEATURE);
118 		alt_debug_all(ALT_TYPE_SPEC);
119 		return;
120 	}
121 	while (*str) {
122 		type = simple_strtoull(str, &endp, 0);
123 		if (str == endp)
124 			break;
125 		str = endp;
126 		switch (type) {
127 		case ALT_TYPE_FACILITY:
128 		case ALT_TYPE_FEATURE:
129 			str = alt_debug_parse(type, str);
130 			break;
131 		case ALT_TYPE_SPEC:
132 			alt_debug_all(ALT_TYPE_SPEC);
133 			break;
134 		}
135 		if (*str != ';')
136 			break;
137 		str++;
138 	}
139 }
140