xref: /linux/arch/s390/kernel/ipl.c (revision eb2bce7f5e7ac1ca6da434461217fadf3c688d2c)
1 /*
2  *  arch/s390/kernel/ipl.c
3  *    ipl/reipl/dump support for Linux on s390.
4  *
5  *    Copyright (C) IBM Corp. 2005,2006
6  *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
7  *		 Heiko Carstens <heiko.carstens@de.ibm.com>
8  *		 Volker Sameske <sameske@de.ibm.com>
9  */
10 
11 #include <linux/types.h>
12 #include <linux/module.h>
13 #include <linux/device.h>
14 #include <linux/delay.h>
15 #include <linux/reboot.h>
16 #include <linux/ctype.h>
17 #include <asm/ipl.h>
18 #include <asm/smp.h>
19 #include <asm/setup.h>
20 #include <asm/cpcmd.h>
21 #include <asm/cio.h>
22 #include <asm/ebcdic.h>
23 #include <asm/reset.h>
24 #include <asm/sclp.h>
25 
26 #define IPL_PARM_BLOCK_VERSION 0
27 
28 #define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
29 #define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
30 #define SCCB_FLAG (s390_readinfo_sccb.flags)
31 
32 #define IPL_UNKNOWN_STR		"unknown"
33 #define IPL_CCW_STR		"ccw"
34 #define IPL_FCP_STR		"fcp"
35 #define IPL_FCP_DUMP_STR	"fcp_dump"
36 #define IPL_NSS_STR		"nss"
37 
38 static char *ipl_type_str(enum ipl_type type)
39 {
40 	switch (type) {
41 	case IPL_TYPE_CCW:
42 		return IPL_CCW_STR;
43 	case IPL_TYPE_FCP:
44 		return IPL_FCP_STR;
45 	case IPL_TYPE_FCP_DUMP:
46 		return IPL_FCP_DUMP_STR;
47 	case IPL_TYPE_NSS:
48 		return IPL_NSS_STR;
49 	case IPL_TYPE_UNKNOWN:
50 	default:
51 		return IPL_UNKNOWN_STR;
52 	}
53 }
54 
55 enum dump_type {
56 	DUMP_TYPE_NONE	= 1,
57 	DUMP_TYPE_CCW	= 2,
58 	DUMP_TYPE_FCP	= 4,
59 };
60 
61 #define DUMP_NONE_STR	 "none"
62 #define DUMP_CCW_STR	 "ccw"
63 #define DUMP_FCP_STR	 "fcp"
64 
65 static char *dump_type_str(enum dump_type type)
66 {
67 	switch (type) {
68 	case DUMP_TYPE_NONE:
69 		return DUMP_NONE_STR;
70 	case DUMP_TYPE_CCW:
71 		return DUMP_CCW_STR;
72 	case DUMP_TYPE_FCP:
73 		return DUMP_FCP_STR;
74 	default:
75 		return NULL;
76 	}
77 }
78 
79 /*
80  * Must be in data section since the bss section
81  * is not cleared when these are accessed.
82  */
83 static u16 ipl_devno __attribute__((__section__(".data"))) = 0;
84 u32 ipl_flags __attribute__((__section__(".data"))) = 0;
85 
86 enum ipl_method {
87 	REIPL_METHOD_CCW_CIO,
88 	REIPL_METHOD_CCW_DIAG,
89 	REIPL_METHOD_CCW_VM,
90 	REIPL_METHOD_FCP_RO_DIAG,
91 	REIPL_METHOD_FCP_RW_DIAG,
92 	REIPL_METHOD_FCP_RO_VM,
93 	REIPL_METHOD_FCP_DUMP,
94 	REIPL_METHOD_NSS,
95 	REIPL_METHOD_DEFAULT,
96 };
97 
98 enum dump_method {
99 	DUMP_METHOD_NONE,
100 	DUMP_METHOD_CCW_CIO,
101 	DUMP_METHOD_CCW_DIAG,
102 	DUMP_METHOD_CCW_VM,
103 	DUMP_METHOD_FCP_DIAG,
104 };
105 
106 enum shutdown_action {
107 	SHUTDOWN_REIPL,
108 	SHUTDOWN_DUMP,
109 	SHUTDOWN_STOP,
110 };
111 
112 #define SHUTDOWN_REIPL_STR "reipl"
113 #define SHUTDOWN_DUMP_STR  "dump"
114 #define SHUTDOWN_STOP_STR  "stop"
115 
116 static char *shutdown_action_str(enum shutdown_action action)
117 {
118 	switch (action) {
119 	case SHUTDOWN_REIPL:
120 		return SHUTDOWN_REIPL_STR;
121 	case SHUTDOWN_DUMP:
122 		return SHUTDOWN_DUMP_STR;
123 	case SHUTDOWN_STOP:
124 		return SHUTDOWN_STOP_STR;
125 	default:
126 		return NULL;
127 	}
128 }
129 
130 static int diag308_set_works = 0;
131 
132 static int reipl_capabilities = IPL_TYPE_UNKNOWN;
133 
134 static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
135 static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
136 static struct ipl_parameter_block *reipl_block_fcp;
137 static struct ipl_parameter_block *reipl_block_ccw;
138 
139 static char reipl_nss_name[NSS_NAME_SIZE + 1];
140 
141 static int dump_capabilities = DUMP_TYPE_NONE;
142 static enum dump_type dump_type = DUMP_TYPE_NONE;
143 static enum dump_method dump_method = DUMP_METHOD_NONE;
144 static struct ipl_parameter_block *dump_block_fcp;
145 static struct ipl_parameter_block *dump_block_ccw;
146 
147 static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
148 
149 int diag308(unsigned long subcode, void *addr)
150 {
151 	register unsigned long _addr asm("0") = (unsigned long) addr;
152 	register unsigned long _rc asm("1") = 0;
153 
154 	asm volatile(
155 		"	diag	%0,%2,0x308\n"
156 		"0:\n"
157 		EX_TABLE(0b,0b)
158 		: "+d" (_addr), "+d" (_rc)
159 		: "d" (subcode) : "cc", "memory");
160 	return _rc;
161 }
162 EXPORT_SYMBOL_GPL(diag308);
163 
164 /* SYSFS */
165 
166 #define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value)		\
167 static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset,	\
168 		char *page)						\
169 {									\
170 	return sprintf(page, _format, _value);				\
171 }									\
172 static struct subsys_attribute sys_##_prefix##_##_name##_attr =		\
173 	__ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL);
174 
175 #define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)	\
176 static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset,	\
177 		char *page)						\
178 {									\
179 	return sprintf(page, _fmt_out,					\
180 			(unsigned long long) _value);			\
181 }									\
182 static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset,	\
183 		const char *buf, size_t len)				\
184 {									\
185 	unsigned long long value;					\
186 	if (sscanf(buf, _fmt_in, &value) != 1)				\
187 		return -EINVAL;						\
188 	_value = value;							\
189 	return len;							\
190 }									\
191 static struct subsys_attribute sys_##_prefix##_##_name##_attr =		\
192 	__ATTR(_name,(S_IRUGO | S_IWUSR),				\
193 			sys_##_prefix##_##_name##_show,			\
194 			sys_##_prefix##_##_name##_store);
195 
196 #define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
197 static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset,	\
198 		char *page)						\
199 {									\
200 	return sprintf(page, _fmt_out, _value);				\
201 }									\
202 static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset,	\
203 		const char *buf, size_t len)				\
204 {									\
205 	if (sscanf(buf, _fmt_in, _value) != 1)				\
206 		return -EINVAL;						\
207 	return len;							\
208 }									\
209 static struct subsys_attribute sys_##_prefix##_##_name##_attr =		\
210 	__ATTR(_name,(S_IRUGO | S_IWUSR),				\
211 			sys_##_prefix##_##_name##_show,			\
212 			sys_##_prefix##_##_name##_store);
213 
214 static void make_attrs_ro(struct attribute **attrs)
215 {
216 	while (*attrs) {
217 		(*attrs)->mode = S_IRUGO;
218 		attrs++;
219 	}
220 }
221 
222 /*
223  * ipl section
224  */
225 
226 static __init enum ipl_type get_ipl_type(void)
227 {
228 	struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
229 
230 	if (ipl_flags & IPL_NSS_VALID)
231 		return IPL_TYPE_NSS;
232 	if (!(ipl_flags & IPL_DEVNO_VALID))
233 		return IPL_TYPE_UNKNOWN;
234 	if (!(ipl_flags & IPL_PARMBLOCK_VALID))
235 		return IPL_TYPE_CCW;
236 	if (ipl->hdr.version > IPL_MAX_SUPPORTED_VERSION)
237 		return IPL_TYPE_UNKNOWN;
238 	if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP)
239 		return IPL_TYPE_UNKNOWN;
240 	if (ipl->ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP)
241 		return IPL_TYPE_FCP_DUMP;
242 	return IPL_TYPE_FCP;
243 }
244 
245 void __init setup_ipl_info(void)
246 {
247 	ipl_info.type = get_ipl_type();
248 	switch (ipl_info.type) {
249 	case IPL_TYPE_CCW:
250 		ipl_info.data.ccw.dev_id.devno = ipl_devno;
251 		ipl_info.data.ccw.dev_id.ssid = 0;
252 		break;
253 	case IPL_TYPE_FCP:
254 	case IPL_TYPE_FCP_DUMP:
255 		ipl_info.data.fcp.dev_id.devno =
256 			IPL_PARMBLOCK_START->ipl_info.fcp.devno;
257 		ipl_info.data.fcp.dev_id.ssid = 0;
258 		ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn;
259 		ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun;
260 		break;
261 	case IPL_TYPE_NSS:
262 		strncpy(ipl_info.data.nss.name, kernel_nss_name,
263 			sizeof(ipl_info.data.nss.name));
264 		break;
265 	case IPL_TYPE_UNKNOWN:
266 	default:
267 		/* We have no info to copy */
268 		break;
269 	}
270 }
271 
272 struct ipl_info ipl_info;
273 EXPORT_SYMBOL_GPL(ipl_info);
274 
275 static ssize_t ipl_type_show(struct kset *kset, char *page)
276 {
277 	return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
278 }
279 
280 static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
281 
282 static ssize_t sys_ipl_device_show(struct kset *kset, char *page)
283 {
284 	struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
285 
286 	switch (ipl_info.type) {
287 	case IPL_TYPE_CCW:
288 		return sprintf(page, "0.0.%04x\n", ipl_devno);
289 	case IPL_TYPE_FCP:
290 	case IPL_TYPE_FCP_DUMP:
291 		return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno);
292 	default:
293 		return 0;
294 	}
295 }
296 
297 static struct subsys_attribute sys_ipl_device_attr =
298 	__ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
299 
300 static ssize_t ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off,
301 				  size_t count)
302 {
303 	unsigned int size = IPL_PARMBLOCK_SIZE;
304 
305 	if (off > size)
306 		return 0;
307 	if (off + count > size)
308 		count = size - off;
309 	memcpy(buf, (void *)IPL_PARMBLOCK_START + off, count);
310 	return count;
311 }
312 
313 static struct bin_attribute ipl_parameter_attr = {
314 	.attr = {
315 		.name = "binary_parameter",
316 		.mode = S_IRUGO,
317 		.owner = THIS_MODULE,
318 	},
319 	.size = PAGE_SIZE,
320 	.read = &ipl_parameter_read,
321 };
322 
323 static ssize_t ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off,
324 	size_t count)
325 {
326 	unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
327 	void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
328 
329 	if (off > size)
330 		return 0;
331 	if (off + count > size)
332 		count = size - off;
333 	memcpy(buf, scp_data + off, count);
334 	return count;
335 }
336 
337 static struct bin_attribute ipl_scp_data_attr = {
338 	.attr = {
339 		.name = "scp_data",
340 		.mode = S_IRUGO,
341 		.owner = THIS_MODULE,
342 	},
343 	.size = PAGE_SIZE,
344 	.read = &ipl_scp_data_read,
345 };
346 
347 /* FCP ipl device attributes */
348 
349 DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n", (unsigned long long)
350 		   IPL_PARMBLOCK_START->ipl_info.fcp.wwpn);
351 DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n", (unsigned long long)
352 		   IPL_PARMBLOCK_START->ipl_info.fcp.lun);
353 DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long)
354 		   IPL_PARMBLOCK_START->ipl_info.fcp.bootprog);
355 DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
356 		   IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
357 
358 static struct attribute *ipl_fcp_attrs[] = {
359 	&sys_ipl_type_attr.attr,
360 	&sys_ipl_device_attr.attr,
361 	&sys_ipl_fcp_wwpn_attr.attr,
362 	&sys_ipl_fcp_lun_attr.attr,
363 	&sys_ipl_fcp_bootprog_attr.attr,
364 	&sys_ipl_fcp_br_lba_attr.attr,
365 	NULL,
366 };
367 
368 static struct attribute_group ipl_fcp_attr_group = {
369 	.attrs = ipl_fcp_attrs,
370 };
371 
372 /* CCW ipl device attributes */
373 
374 static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page)
375 {
376 	char loadparm[LOADPARM_LEN + 1] = {};
377 
378 	if (!SCCB_VALID)
379 		return sprintf(page, "#unknown#\n");
380 	memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN);
381 	EBCASC(loadparm, LOADPARM_LEN);
382 	strstrip(loadparm);
383 	return sprintf(page, "%s\n", loadparm);
384 }
385 
386 static struct subsys_attribute sys_ipl_ccw_loadparm_attr =
387 	__ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
388 
389 static struct attribute *ipl_ccw_attrs[] = {
390 	&sys_ipl_type_attr.attr,
391 	&sys_ipl_device_attr.attr,
392 	&sys_ipl_ccw_loadparm_attr.attr,
393 	NULL,
394 };
395 
396 static struct attribute_group ipl_ccw_attr_group = {
397 	.attrs = ipl_ccw_attrs,
398 };
399 
400 /* NSS ipl device attributes */
401 
402 DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name);
403 
404 static struct attribute *ipl_nss_attrs[] = {
405 	&sys_ipl_type_attr.attr,
406 	&sys_ipl_nss_name_attr.attr,
407 	NULL,
408 };
409 
410 static struct attribute_group ipl_nss_attr_group = {
411 	.attrs = ipl_nss_attrs,
412 };
413 
414 /* UNKNOWN ipl device attributes */
415 
416 static struct attribute *ipl_unknown_attrs[] = {
417 	&sys_ipl_type_attr.attr,
418 	NULL,
419 };
420 
421 static struct attribute_group ipl_unknown_attr_group = {
422 	.attrs = ipl_unknown_attrs,
423 };
424 
425 static decl_subsys(ipl, NULL, NULL);
426 
427 /*
428  * reipl section
429  */
430 
431 /* FCP reipl device attributes */
432 
433 DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n",
434 		   reipl_block_fcp->ipl_info.fcp.wwpn);
435 DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%016llx\n",
436 		   reipl_block_fcp->ipl_info.fcp.lun);
437 DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
438 		   reipl_block_fcp->ipl_info.fcp.bootprog);
439 DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
440 		   reipl_block_fcp->ipl_info.fcp.br_lba);
441 DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
442 		   reipl_block_fcp->ipl_info.fcp.devno);
443 
444 static struct attribute *reipl_fcp_attrs[] = {
445 	&sys_reipl_fcp_device_attr.attr,
446 	&sys_reipl_fcp_wwpn_attr.attr,
447 	&sys_reipl_fcp_lun_attr.attr,
448 	&sys_reipl_fcp_bootprog_attr.attr,
449 	&sys_reipl_fcp_br_lba_attr.attr,
450 	NULL,
451 };
452 
453 static struct attribute_group reipl_fcp_attr_group = {
454 	.name  = IPL_FCP_STR,
455 	.attrs = reipl_fcp_attrs,
456 };
457 
458 /* CCW reipl device attributes */
459 
460 DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
461 	reipl_block_ccw->ipl_info.ccw.devno);
462 
463 static void reipl_get_ascii_loadparm(char *loadparm)
464 {
465 	memcpy(loadparm, &reipl_block_ccw->ipl_info.ccw.load_param,
466 	       LOADPARM_LEN);
467 	EBCASC(loadparm, LOADPARM_LEN);
468 	loadparm[LOADPARM_LEN] = 0;
469 	strstrip(loadparm);
470 }
471 
472 static ssize_t reipl_ccw_loadparm_show(struct kset *kset, char *page)
473 {
474 	char buf[LOADPARM_LEN + 1];
475 
476 	reipl_get_ascii_loadparm(buf);
477 	return sprintf(page, "%s\n", buf);
478 }
479 
480 static ssize_t reipl_ccw_loadparm_store(struct kset *kset,
481 					const char *buf, size_t len)
482 {
483 	int i, lp_len;
484 
485 	/* ignore trailing newline */
486 	lp_len = len;
487 	if ((len > 0) && (buf[len - 1] == '\n'))
488 		lp_len--;
489 	/* loadparm can have max 8 characters and must not start with a blank */
490 	if ((lp_len > LOADPARM_LEN) || ((lp_len > 0) && (buf[0] == ' ')))
491 		return -EINVAL;
492 	/* loadparm can only contain "a-z,A-Z,0-9,SP,." */
493 	for (i = 0; i < lp_len; i++) {
494 		if (isalpha(buf[i]) || isdigit(buf[i]) || (buf[i] == ' ') ||
495 		    (buf[i] == '.'))
496 			continue;
497 		return -EINVAL;
498 	}
499 	/* initialize loadparm with blanks */
500 	memset(&reipl_block_ccw->ipl_info.ccw.load_param, ' ', LOADPARM_LEN);
501 	/* copy and convert to ebcdic */
502 	memcpy(&reipl_block_ccw->ipl_info.ccw.load_param, buf, lp_len);
503 	ASCEBC(reipl_block_ccw->ipl_info.ccw.load_param, LOADPARM_LEN);
504 	return len;
505 }
506 
507 static struct subsys_attribute sys_reipl_ccw_loadparm_attr =
508 	__ATTR(loadparm, 0644, reipl_ccw_loadparm_show,
509 	       reipl_ccw_loadparm_store);
510 
511 static struct attribute *reipl_ccw_attrs[] = {
512 	&sys_reipl_ccw_device_attr.attr,
513 	&sys_reipl_ccw_loadparm_attr.attr,
514 	NULL,
515 };
516 
517 static struct attribute_group reipl_ccw_attr_group = {
518 	.name  = IPL_CCW_STR,
519 	.attrs = reipl_ccw_attrs,
520 };
521 
522 
523 /* NSS reipl device attributes */
524 
525 DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name);
526 
527 static struct attribute *reipl_nss_attrs[] = {
528 	&sys_reipl_nss_name_attr.attr,
529 	NULL,
530 };
531 
532 static struct attribute_group reipl_nss_attr_group = {
533 	.name  = IPL_NSS_STR,
534 	.attrs = reipl_nss_attrs,
535 };
536 
537 /* reipl type */
538 
539 static int reipl_set_type(enum ipl_type type)
540 {
541 	if (!(reipl_capabilities & type))
542 		return -EINVAL;
543 
544 	switch(type) {
545 	case IPL_TYPE_CCW:
546 		if (MACHINE_IS_VM)
547 			reipl_method = REIPL_METHOD_CCW_VM;
548 		else
549 			reipl_method = REIPL_METHOD_CCW_CIO;
550 		break;
551 	case IPL_TYPE_FCP:
552 		if (diag308_set_works)
553 			reipl_method = REIPL_METHOD_FCP_RW_DIAG;
554 		else if (MACHINE_IS_VM)
555 			reipl_method = REIPL_METHOD_FCP_RO_VM;
556 		else
557 			reipl_method = REIPL_METHOD_FCP_RO_DIAG;
558 		break;
559 	case IPL_TYPE_FCP_DUMP:
560 		reipl_method = REIPL_METHOD_FCP_DUMP;
561 		break;
562 	case IPL_TYPE_NSS:
563 		reipl_method = REIPL_METHOD_NSS;
564 		break;
565 	case IPL_TYPE_UNKNOWN:
566 		reipl_method = REIPL_METHOD_DEFAULT;
567 		break;
568 	default:
569 		BUG();
570 	}
571 	reipl_type = type;
572 	return 0;
573 }
574 
575 static ssize_t reipl_type_show(struct kset *kset, char *page)
576 {
577 	return sprintf(page, "%s\n", ipl_type_str(reipl_type));
578 }
579 
580 static ssize_t reipl_type_store(struct kset *kset, const char *buf,
581 				size_t len)
582 {
583 	int rc = -EINVAL;
584 
585 	if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
586 		rc = reipl_set_type(IPL_TYPE_CCW);
587 	else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
588 		rc = reipl_set_type(IPL_TYPE_FCP);
589 	else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
590 		rc = reipl_set_type(IPL_TYPE_NSS);
591 	return (rc != 0) ? rc : len;
592 }
593 
594 static struct subsys_attribute reipl_type_attr =
595 		__ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
596 
597 static decl_subsys(reipl, NULL, NULL);
598 
599 /*
600  * dump section
601  */
602 
603 /* FCP dump device attributes */
604 
605 DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n",
606 		   dump_block_fcp->ipl_info.fcp.wwpn);
607 DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n",
608 		   dump_block_fcp->ipl_info.fcp.lun);
609 DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
610 		   dump_block_fcp->ipl_info.fcp.bootprog);
611 DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
612 		   dump_block_fcp->ipl_info.fcp.br_lba);
613 DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
614 		   dump_block_fcp->ipl_info.fcp.devno);
615 
616 static struct attribute *dump_fcp_attrs[] = {
617 	&sys_dump_fcp_device_attr.attr,
618 	&sys_dump_fcp_wwpn_attr.attr,
619 	&sys_dump_fcp_lun_attr.attr,
620 	&sys_dump_fcp_bootprog_attr.attr,
621 	&sys_dump_fcp_br_lba_attr.attr,
622 	NULL,
623 };
624 
625 static struct attribute_group dump_fcp_attr_group = {
626 	.name  = IPL_FCP_STR,
627 	.attrs = dump_fcp_attrs,
628 };
629 
630 /* CCW dump device attributes */
631 
632 DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
633 		   dump_block_ccw->ipl_info.ccw.devno);
634 
635 static struct attribute *dump_ccw_attrs[] = {
636 	&sys_dump_ccw_device_attr.attr,
637 	NULL,
638 };
639 
640 static struct attribute_group dump_ccw_attr_group = {
641 	.name  = IPL_CCW_STR,
642 	.attrs = dump_ccw_attrs,
643 };
644 
645 /* dump type */
646 
647 static int dump_set_type(enum dump_type type)
648 {
649 	if (!(dump_capabilities & type))
650 		return -EINVAL;
651 	switch(type) {
652 	case DUMP_TYPE_CCW:
653 		if (MACHINE_IS_VM)
654 			dump_method = DUMP_METHOD_CCW_VM;
655 		else
656 			dump_method = DUMP_METHOD_CCW_CIO;
657 		break;
658 	case DUMP_TYPE_FCP:
659 		dump_method = DUMP_METHOD_FCP_DIAG;
660 		break;
661 	default:
662 		dump_method = DUMP_METHOD_NONE;
663 	}
664 	dump_type = type;
665 	return 0;
666 }
667 
668 static ssize_t dump_type_show(struct kset *kset, char *page)
669 {
670 	return sprintf(page, "%s\n", dump_type_str(dump_type));
671 }
672 
673 static ssize_t dump_type_store(struct kset *kset, const char *buf,
674 			       size_t len)
675 {
676 	int rc = -EINVAL;
677 
678 	if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
679 		rc = dump_set_type(DUMP_TYPE_NONE);
680 	else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
681 		rc = dump_set_type(DUMP_TYPE_CCW);
682 	else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
683 		rc = dump_set_type(DUMP_TYPE_FCP);
684 	return (rc != 0) ? rc : len;
685 }
686 
687 static struct subsys_attribute dump_type_attr =
688 		__ATTR(dump_type, 0644, dump_type_show, dump_type_store);
689 
690 static decl_subsys(dump, NULL, NULL);
691 
692 /*
693  * Shutdown actions section
694  */
695 
696 static decl_subsys(shutdown_actions, NULL, NULL);
697 
698 /* on panic */
699 
700 static ssize_t on_panic_show(struct kset *kset, char *page)
701 {
702 	return sprintf(page, "%s\n", shutdown_action_str(on_panic_action));
703 }
704 
705 static ssize_t on_panic_store(struct kset *kset, const char *buf,
706 			      size_t len)
707 {
708 	if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0)
709 		on_panic_action = SHUTDOWN_REIPL;
710 	else if (strncmp(buf, SHUTDOWN_DUMP_STR,
711 			 strlen(SHUTDOWN_DUMP_STR)) == 0)
712 		on_panic_action = SHUTDOWN_DUMP;
713 	else if (strncmp(buf, SHUTDOWN_STOP_STR,
714 			 strlen(SHUTDOWN_STOP_STR)) == 0)
715 		on_panic_action = SHUTDOWN_STOP;
716 	else
717 		return -EINVAL;
718 
719 	return len;
720 }
721 
722 static struct subsys_attribute on_panic_attr =
723 		__ATTR(on_panic, 0644, on_panic_show, on_panic_store);
724 
725 void do_reipl(void)
726 {
727 	struct ccw_dev_id devid;
728 	static char buf[100];
729 	char loadparm[LOADPARM_LEN + 1];
730 
731 	switch (reipl_method) {
732 	case REIPL_METHOD_CCW_CIO:
733 		devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
734 		if (ipl_info.type == IPL_TYPE_CCW && devid.devno == ipl_devno)
735 			diag308(DIAG308_IPL, NULL);
736 		devid.ssid  = 0;
737 		reipl_ccw_dev(&devid);
738 		break;
739 	case REIPL_METHOD_CCW_VM:
740 		reipl_get_ascii_loadparm(loadparm);
741 		if (strlen(loadparm) == 0)
742 			sprintf(buf, "IPL %X",
743 				reipl_block_ccw->ipl_info.ccw.devno);
744 		else
745 			sprintf(buf, "IPL %X LOADPARM '%s'",
746 				reipl_block_ccw->ipl_info.ccw.devno, loadparm);
747 		__cpcmd(buf, NULL, 0, NULL);
748 		break;
749 	case REIPL_METHOD_CCW_DIAG:
750 		diag308(DIAG308_SET, reipl_block_ccw);
751 		diag308(DIAG308_IPL, NULL);
752 		break;
753 	case REIPL_METHOD_FCP_RW_DIAG:
754 		diag308(DIAG308_SET, reipl_block_fcp);
755 		diag308(DIAG308_IPL, NULL);
756 		break;
757 	case REIPL_METHOD_FCP_RO_DIAG:
758 		diag308(DIAG308_IPL, NULL);
759 		break;
760 	case REIPL_METHOD_FCP_RO_VM:
761 		__cpcmd("IPL", NULL, 0, NULL);
762 		break;
763 	case REIPL_METHOD_NSS:
764 		sprintf(buf, "IPL %s", reipl_nss_name);
765 		__cpcmd(buf, NULL, 0, NULL);
766 		break;
767 	case REIPL_METHOD_DEFAULT:
768 		if (MACHINE_IS_VM)
769 			__cpcmd("IPL", NULL, 0, NULL);
770 		diag308(DIAG308_IPL, NULL);
771 		break;
772 	case REIPL_METHOD_FCP_DUMP:
773 	default:
774 		break;
775 	}
776 	signal_processor(smp_processor_id(), sigp_stop_and_store_status);
777 }
778 
779 static void do_dump(void)
780 {
781 	struct ccw_dev_id devid;
782 	static char buf[100];
783 
784 	switch (dump_method) {
785 	case DUMP_METHOD_CCW_CIO:
786 		smp_send_stop();
787 		devid.devno = dump_block_ccw->ipl_info.ccw.devno;
788 		devid.ssid  = 0;
789 		reipl_ccw_dev(&devid);
790 		break;
791 	case DUMP_METHOD_CCW_VM:
792 		smp_send_stop();
793 		sprintf(buf, "STORE STATUS");
794 		__cpcmd(buf, NULL, 0, NULL);
795 		sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
796 		__cpcmd(buf, NULL, 0, NULL);
797 		break;
798 	case DUMP_METHOD_CCW_DIAG:
799 		diag308(DIAG308_SET, dump_block_ccw);
800 		diag308(DIAG308_DUMP, NULL);
801 		break;
802 	case DUMP_METHOD_FCP_DIAG:
803 		diag308(DIAG308_SET, dump_block_fcp);
804 		diag308(DIAG308_DUMP, NULL);
805 		break;
806 	case DUMP_METHOD_NONE:
807 	default:
808 		return;
809 	}
810 	printk(KERN_EMERG "Dump failed!\n");
811 }
812 
813 /* init functions */
814 
815 static int __init ipl_register_fcp_files(void)
816 {
817 	int rc;
818 
819 	rc = sysfs_create_group(&ipl_subsys.kset.kobj,
820 				&ipl_fcp_attr_group);
821 	if (rc)
822 		goto out;
823 	rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
824 				   &ipl_parameter_attr);
825 	if (rc)
826 		goto out_ipl_parm;
827 	rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
828 				   &ipl_scp_data_attr);
829 	if (!rc)
830 		goto out;
831 
832 	sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr);
833 
834 out_ipl_parm:
835 	sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
836 out:
837 	return rc;
838 }
839 
840 static int __init ipl_init(void)
841 {
842 	int rc;
843 
844 	rc = firmware_register(&ipl_subsys);
845 	if (rc)
846 		return rc;
847 	switch (ipl_info.type) {
848 	case IPL_TYPE_CCW:
849 		rc = sysfs_create_group(&ipl_subsys.kset.kobj,
850 					&ipl_ccw_attr_group);
851 		break;
852 	case IPL_TYPE_FCP:
853 	case IPL_TYPE_FCP_DUMP:
854 		rc = ipl_register_fcp_files();
855 		break;
856 	case IPL_TYPE_NSS:
857 		rc = sysfs_create_group(&ipl_subsys.kset.kobj,
858 					&ipl_nss_attr_group);
859 		break;
860 	default:
861 		rc = sysfs_create_group(&ipl_subsys.kset.kobj,
862 					&ipl_unknown_attr_group);
863 		break;
864 	}
865 	if (rc)
866 		firmware_unregister(&ipl_subsys);
867 	return rc;
868 }
869 
870 static void __init reipl_probe(void)
871 {
872 	void *buffer;
873 
874 	buffer = (void *) get_zeroed_page(GFP_KERNEL);
875 	if (!buffer)
876 		return;
877 	if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK)
878 		diag308_set_works = 1;
879 	free_page((unsigned long)buffer);
880 }
881 
882 static int __init reipl_nss_init(void)
883 {
884 	int rc;
885 
886 	if (!MACHINE_IS_VM)
887 		return 0;
888 	rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_nss_attr_group);
889 	if (rc)
890 		return rc;
891 	strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
892 	reipl_capabilities |= IPL_TYPE_NSS;
893 	return 0;
894 }
895 
896 static int __init reipl_ccw_init(void)
897 {
898 	int rc;
899 
900 	reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
901 	if (!reipl_block_ccw)
902 		return -ENOMEM;
903 	rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_ccw_attr_group);
904 	if (rc) {
905 		free_page((unsigned long)reipl_block_ccw);
906 		return rc;
907 	}
908 	reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
909 	reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
910 	reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
911 	reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
912 	/* check if read scp info worked and set loadparm */
913 	if (SCCB_VALID)
914 		memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
915 		       SCCB_LOADPARM, LOADPARM_LEN);
916 	else
917 		/* read scp info failed: set empty loadparm (EBCDIC blanks) */
918 		memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
919 		       LOADPARM_LEN);
920 	/* FIXME: check for diag308_set_works when enabling diag ccw reipl */
921 	if (!MACHINE_IS_VM)
922 		sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
923 	if (ipl_info.type == IPL_TYPE_CCW)
924 		reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
925 	reipl_capabilities |= IPL_TYPE_CCW;
926 	return 0;
927 }
928 
929 static int __init reipl_fcp_init(void)
930 {
931 	int rc;
932 
933 	if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP))
934 		return 0;
935 	if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP))
936 		make_attrs_ro(reipl_fcp_attrs);
937 
938 	reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
939 	if (!reipl_block_fcp)
940 		return -ENOMEM;
941 	rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_fcp_attr_group);
942 	if (rc) {
943 		free_page((unsigned long)reipl_block_fcp);
944 		return rc;
945 	}
946 	if (ipl_info.type == IPL_TYPE_FCP) {
947 		memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
948 	} else {
949 		reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
950 		reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
951 		reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
952 		reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
953 		reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL;
954 	}
955 	reipl_capabilities |= IPL_TYPE_FCP;
956 	return 0;
957 }
958 
959 static int __init reipl_init(void)
960 {
961 	int rc;
962 
963 	rc = firmware_register(&reipl_subsys);
964 	if (rc)
965 		return rc;
966 	rc = subsys_create_file(&reipl_subsys, &reipl_type_attr);
967 	if (rc) {
968 		firmware_unregister(&reipl_subsys);
969 		return rc;
970 	}
971 	rc = reipl_ccw_init();
972 	if (rc)
973 		return rc;
974 	rc = reipl_fcp_init();
975 	if (rc)
976 		return rc;
977 	rc = reipl_nss_init();
978 	if (rc)
979 		return rc;
980 	rc = reipl_set_type(ipl_info.type);
981 	if (rc)
982 		return rc;
983 	return 0;
984 }
985 
986 static int __init dump_ccw_init(void)
987 {
988 	int rc;
989 
990 	dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
991 	if (!dump_block_ccw)
992 		return -ENOMEM;
993 	rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_ccw_attr_group);
994 	if (rc) {
995 		free_page((unsigned long)dump_block_ccw);
996 		return rc;
997 	}
998 	dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
999 	dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
1000 	dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
1001 	dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
1002 	dump_capabilities |= DUMP_TYPE_CCW;
1003 	return 0;
1004 }
1005 
1006 static int __init dump_fcp_init(void)
1007 {
1008 	int rc;
1009 
1010 	if(!(SCCB_FLAG & 0x2) || !SCCB_VALID)
1011 		return 0; /* LDIPL DUMP is not installed */
1012 	if (!diag308_set_works)
1013 		return 0;
1014 	dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
1015 	if (!dump_block_fcp)
1016 		return -ENOMEM;
1017 	rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_fcp_attr_group);
1018 	if (rc) {
1019 		free_page((unsigned long)dump_block_fcp);
1020 		return rc;
1021 	}
1022 	dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
1023 	dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
1024 	dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
1025 	dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
1026 	dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
1027 	dump_capabilities |= DUMP_TYPE_FCP;
1028 	return 0;
1029 }
1030 
1031 #define SHUTDOWN_ON_PANIC_PRIO 0
1032 
1033 static int shutdown_on_panic_notify(struct notifier_block *self,
1034 				    unsigned long event, void *data)
1035 {
1036 	if (on_panic_action == SHUTDOWN_DUMP)
1037 		do_dump();
1038 	else if (on_panic_action == SHUTDOWN_REIPL)
1039 		do_reipl();
1040 	return NOTIFY_OK;
1041 }
1042 
1043 static struct notifier_block shutdown_on_panic_nb = {
1044 	.notifier_call = shutdown_on_panic_notify,
1045 	.priority = SHUTDOWN_ON_PANIC_PRIO
1046 };
1047 
1048 static int __init dump_init(void)
1049 {
1050 	int rc;
1051 
1052 	rc = firmware_register(&dump_subsys);
1053 	if (rc)
1054 		return rc;
1055 	rc = subsys_create_file(&dump_subsys, &dump_type_attr);
1056 	if (rc) {
1057 		firmware_unregister(&dump_subsys);
1058 		return rc;
1059 	}
1060 	rc = dump_ccw_init();
1061 	if (rc)
1062 		return rc;
1063 	rc = dump_fcp_init();
1064 	if (rc)
1065 		return rc;
1066 	dump_set_type(DUMP_TYPE_NONE);
1067 	return 0;
1068 }
1069 
1070 static int __init shutdown_actions_init(void)
1071 {
1072 	int rc;
1073 
1074 	rc = firmware_register(&shutdown_actions_subsys);
1075 	if (rc)
1076 		return rc;
1077 	rc = subsys_create_file(&shutdown_actions_subsys, &on_panic_attr);
1078 	if (rc) {
1079 		firmware_unregister(&shutdown_actions_subsys);
1080 		return rc;
1081 	}
1082 	atomic_notifier_chain_register(&panic_notifier_list,
1083 				       &shutdown_on_panic_nb);
1084 	return 0;
1085 }
1086 
1087 static int __init s390_ipl_init(void)
1088 {
1089 	int rc;
1090 
1091 	reipl_probe();
1092 	rc = ipl_init();
1093 	if (rc)
1094 		return rc;
1095 	rc = reipl_init();
1096 	if (rc)
1097 		return rc;
1098 	rc = dump_init();
1099 	if (rc)
1100 		return rc;
1101 	rc = shutdown_actions_init();
1102 	if (rc)
1103 		return rc;
1104 	return 0;
1105 }
1106 
1107 __initcall(s390_ipl_init);
1108 
1109 void __init ipl_save_parameters(void)
1110 {
1111 	struct cio_iplinfo iplinfo;
1112 	unsigned int *ipl_ptr;
1113 	void *src, *dst;
1114 
1115 	if (cio_get_iplinfo(&iplinfo))
1116 		return;
1117 
1118 	ipl_devno = iplinfo.devno;
1119 	ipl_flags |= IPL_DEVNO_VALID;
1120 	if (!iplinfo.is_qdio)
1121 		return;
1122 	ipl_flags |= IPL_PARMBLOCK_VALID;
1123 	ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR;
1124 	src = (void *)(unsigned long)*ipl_ptr;
1125 	dst = (void *)IPL_PARMBLOCK_ORIGIN;
1126 	memmove(dst, src, PAGE_SIZE);
1127 	*ipl_ptr = IPL_PARMBLOCK_ORIGIN;
1128 }
1129 
1130 static LIST_HEAD(rcall);
1131 static DEFINE_MUTEX(rcall_mutex);
1132 
1133 void register_reset_call(struct reset_call *reset)
1134 {
1135 	mutex_lock(&rcall_mutex);
1136 	list_add(&reset->list, &rcall);
1137 	mutex_unlock(&rcall_mutex);
1138 }
1139 EXPORT_SYMBOL_GPL(register_reset_call);
1140 
1141 void unregister_reset_call(struct reset_call *reset)
1142 {
1143 	mutex_lock(&rcall_mutex);
1144 	list_del(&reset->list);
1145 	mutex_unlock(&rcall_mutex);
1146 }
1147 EXPORT_SYMBOL_GPL(unregister_reset_call);
1148 
1149 static void do_reset_calls(void)
1150 {
1151 	struct reset_call *reset;
1152 
1153 	list_for_each_entry(reset, &rcall, list)
1154 		reset->fn();
1155 }
1156 
1157 u32 dump_prefix_page;
1158 
1159 void s390_reset_system(void)
1160 {
1161 	struct _lowcore *lc;
1162 
1163 	lc = (struct _lowcore *)(unsigned long) store_prefix();
1164 
1165 	/* Stack for interrupt/machine check handler */
1166 	lc->panic_stack = S390_lowcore.panic_stack;
1167 
1168 	/* Save prefix page address for dump case */
1169 	dump_prefix_page = (u32)(unsigned long) lc;
1170 
1171 	/* Disable prefixing */
1172 	set_prefix(0);
1173 
1174 	/* Disable lowcore protection */
1175 	__ctl_clear_bit(0,28);
1176 
1177 	/* Set new machine check handler */
1178 	S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
1179 	S390_lowcore.mcck_new_psw.addr =
1180 		PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
1181 
1182 	/* Set new program check handler */
1183 	S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
1184 	S390_lowcore.program_new_psw.addr =
1185 		PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
1186 
1187 	do_reset_calls();
1188 }
1189