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 } 1114