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