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