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