linux/arch/s390/kernel/ipl.c
<<
>>
Prefs
   1/*
   2 *  arch/s390/kernel/ipl.c
   3 *    ipl/reipl/dump support for Linux on s390.
   4 *
   5 *    Copyright IBM Corp. 2005,2007
   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#define DUMP_CCW_STR            "ccw"
  35#define DUMP_FCP_STR            "fcp"
  36#define DUMP_NONE_STR           "none"
  37
  38/*
  39 * Four shutdown trigger types are supported:
  40 * - panic
  41 * - halt
  42 * - power off
  43 * - reipl
  44 */
  45#define ON_PANIC_STR            "on_panic"
  46#define ON_HALT_STR             "on_halt"
  47#define ON_POFF_STR             "on_poff"
  48#define ON_REIPL_STR            "on_reboot"
  49
  50struct shutdown_action;
  51struct shutdown_trigger {
  52        char *name;
  53        struct shutdown_action *action;
  54};
  55
  56/*
  57 * Five shutdown action types are supported:
  58 */
  59#define SHUTDOWN_ACTION_IPL_STR         "ipl"
  60#define SHUTDOWN_ACTION_REIPL_STR       "reipl"
  61#define SHUTDOWN_ACTION_DUMP_STR        "dump"
  62#define SHUTDOWN_ACTION_VMCMD_STR       "vmcmd"
  63#define SHUTDOWN_ACTION_STOP_STR        "stop"
  64
  65struct shutdown_action {
  66        char *name;
  67        void (*fn) (struct shutdown_trigger *trigger);
  68        int (*init) (void);
  69};
  70
  71static char *ipl_type_str(enum ipl_type type)
  72{
  73        switch (type) {
  74        case IPL_TYPE_CCW:
  75                return IPL_CCW_STR;
  76        case IPL_TYPE_FCP:
  77                return IPL_FCP_STR;
  78        case IPL_TYPE_FCP_DUMP:
  79                return IPL_FCP_DUMP_STR;
  80        case IPL_TYPE_NSS:
  81                return IPL_NSS_STR;
  82        case IPL_TYPE_UNKNOWN:
  83        default:
  84                return IPL_UNKNOWN_STR;
  85        }
  86}
  87
  88enum dump_type {
  89        DUMP_TYPE_NONE  = 1,
  90        DUMP_TYPE_CCW   = 2,
  91        DUMP_TYPE_FCP   = 4,
  92};
  93
  94static char *dump_type_str(enum dump_type type)
  95{
  96        switch (type) {
  97        case DUMP_TYPE_NONE:
  98                return DUMP_NONE_STR;
  99        case DUMP_TYPE_CCW:
 100                return DUMP_CCW_STR;
 101        case DUMP_TYPE_FCP:
 102                return DUMP_FCP_STR;
 103        default:
 104                return NULL;
 105        }
 106}
 107
 108/*
 109 * Must be in data section since the bss section
 110 * is not cleared when these are accessed.
 111 */
 112static u16 ipl_devno __attribute__((__section__(".data"))) = 0;
 113u32 ipl_flags __attribute__((__section__(".data"))) = 0;
 114
 115enum ipl_method {
 116        REIPL_METHOD_CCW_CIO,
 117        REIPL_METHOD_CCW_DIAG,
 118        REIPL_METHOD_CCW_VM,
 119        REIPL_METHOD_FCP_RO_DIAG,
 120        REIPL_METHOD_FCP_RW_DIAG,
 121        REIPL_METHOD_FCP_RO_VM,
 122        REIPL_METHOD_FCP_DUMP,
 123        REIPL_METHOD_NSS,
 124        REIPL_METHOD_DEFAULT,
 125};
 126
 127enum dump_method {
 128        DUMP_METHOD_NONE,
 129        DUMP_METHOD_CCW_CIO,
 130        DUMP_METHOD_CCW_DIAG,
 131        DUMP_METHOD_CCW_VM,
 132        DUMP_METHOD_FCP_DIAG,
 133};
 134
 135static int diag308_set_works = 0;
 136
 137static int reipl_capabilities = IPL_TYPE_UNKNOWN;
 138
 139static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
 140static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
 141static struct ipl_parameter_block *reipl_block_fcp;
 142static struct ipl_parameter_block *reipl_block_ccw;
 143
 144static char reipl_nss_name[NSS_NAME_SIZE + 1];
 145
 146static int dump_capabilities = DUMP_TYPE_NONE;
 147static enum dump_type dump_type = DUMP_TYPE_NONE;
 148static enum dump_method dump_method = DUMP_METHOD_NONE;
 149static struct ipl_parameter_block *dump_block_fcp;
 150static struct ipl_parameter_block *dump_block_ccw;
 151
 152static struct sclp_ipl_info sclp_ipl_info;
 153
 154int diag308(unsigned long subcode, void *addr)
 155{
 156        register unsigned long _addr asm("0") = (unsigned long) addr;
 157        register unsigned long _rc asm("1") = 0;
 158
 159        asm volatile(
 160                "       diag    %0,%2,0x308\n"
 161                "0:\n"
 162                EX_TABLE(0b,0b)
 163                : "+d" (_addr), "+d" (_rc)
 164                : "d" (subcode) : "cc", "memory");
 165        return _rc;
 166}
 167EXPORT_SYMBOL_GPL(diag308);
 168
 169/* SYSFS */
 170
 171#define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value)             \
 172static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj,     \
 173                struct kobj_attribute *attr,                            \
 174                char *page)                                             \
 175{                                                                       \
 176        return sprintf(page, _format, _value);                          \
 177}                                                                       \
 178static struct kobj_attribute sys_##_prefix##_##_name##_attr =           \
 179        __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL);
 180
 181#define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)   \
 182static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj,     \
 183                struct kobj_attribute *attr,                            \
 184                char *page)                                             \
 185{                                                                       \
 186        return sprintf(page, _fmt_out,                                  \
 187                        (unsigned long long) _value);                   \
 188}                                                                       \
 189static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj,    \
 190                struct kobj_attribute *attr,                            \
 191                const char *buf, size_t len)                            \
 192{                                                                       \
 193        unsigned long long value;                                       \
 194        if (sscanf(buf, _fmt_in, &value) != 1)                          \
 195                return -EINVAL;                                         \
 196        _value = value;                                                 \
 197        return len;                                                     \
 198}                                                                       \
 199static struct kobj_attribute sys_##_prefix##_##_name##_attr =           \
 200        __ATTR(_name,(S_IRUGO | S_IWUSR),                               \
 201                        sys_##_prefix##_##_name##_show,                 \
 202                        sys_##_prefix##_##_name##_store);
 203
 204#define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
 205static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj,     \
 206                struct kobj_attribute *attr,                            \
 207                char *page)                                             \
 208{                                                                       \
 209        return sprintf(page, _fmt_out, _value);                         \
 210}                                                                       \
 211static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj,    \
 212                struct kobj_attribute *attr,                            \
 213                const char *buf, size_t len)                            \
 214{                                                                       \
 215        strncpy(_value, buf, sizeof(_value) - 1);                       \
 216        strstrip(_value);                                               \
 217        return len;                                                     \
 218}                                                                       \
 219static struct kobj_attribute sys_##_prefix##_##_name##_attr =           \
 220        __ATTR(_name,(S_IRUGO | S_IWUSR),                               \
 221                        sys_##_prefix##_##_name##_show,                 \
 222                        sys_##_prefix##_##_name##_store);
 223
 224static void make_attrs_ro(struct attribute **attrs)
 225{
 226        while (*attrs) {
 227                (*attrs)->mode = S_IRUGO;
 228                attrs++;
 229        }
 230}
 231
 232/*
 233 * ipl section
 234 */
 235
 236static __init enum ipl_type get_ipl_type(void)
 237{
 238        struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
 239
 240        if (ipl_flags & IPL_NSS_VALID)
 241                return IPL_TYPE_NSS;
 242        if (!(ipl_flags & IPL_DEVNO_VALID))
 243                return IPL_TYPE_UNKNOWN;
 244        if (!(ipl_flags & IPL_PARMBLOCK_VALID))
 245                return IPL_TYPE_CCW;
 246        if (ipl->hdr.version > IPL_MAX_SUPPORTED_VERSION)
 247                return IPL_TYPE_UNKNOWN;
 248        if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP)
 249                return IPL_TYPE_UNKNOWN;
 250        if (ipl->ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP)
 251                return IPL_TYPE_FCP_DUMP;
 252        return IPL_TYPE_FCP;
 253}
 254
 255struct ipl_info ipl_info;
 256EXPORT_SYMBOL_GPL(ipl_info);
 257
 258static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
 259                             char *page)
 260{
 261        return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
 262}
 263
 264static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
 265
 266static ssize_t sys_ipl_device_show(struct kobject *kobj,
 267                                   struct kobj_attribute *attr, char *page)
 268{
 269        struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
 270
 271        switch (ipl_info.type) {
 272        case IPL_TYPE_CCW:
 273                return sprintf(page, "0.0.%04x\n", ipl_devno);
 274        case IPL_TYPE_FCP:
 275        case IPL_TYPE_FCP_DUMP:
 276                return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno);
 277        default:
 278                return 0;
 279        }
 280}
 281
 282static struct kobj_attribute sys_ipl_device_attr =
 283        __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
 284
 285static ssize_t ipl_parameter_read(struct kobject *kobj, struct bin_attribute *attr,
 286                                  char *buf, loff_t off, size_t count)
 287{
 288        unsigned int size = IPL_PARMBLOCK_SIZE;
 289
 290        if (off > size)
 291                return 0;
 292        if (off + count > size)
 293                count = size - off;
 294        memcpy(buf, (void *)IPL_PARMBLOCK_START + off, count);
 295        return count;
 296}
 297
 298static struct bin_attribute ipl_parameter_attr = {
 299        .attr = {
 300                .name = "binary_parameter",
 301                .mode = S_IRUGO,
 302        },
 303        .size = PAGE_SIZE,
 304        .read = &ipl_parameter_read,
 305};
 306
 307static ssize_t ipl_scp_data_read(struct kobject *kobj, struct bin_attribute *attr,
 308                                 char *buf, loff_t off, size_t count)
 309{
 310        unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
 311        void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
 312
 313        if (off > size)
 314                return 0;
 315        if (off + count > size)
 316                count = size - off;
 317        memcpy(buf, scp_data + off, count);
 318        return count;
 319}
 320
 321static struct bin_attribute ipl_scp_data_attr = {
 322        .attr = {
 323                .name = "scp_data",
 324                .mode = S_IRUGO,
 325        },
 326        .size = PAGE_SIZE,
 327        .read = ipl_scp_data_read,
 328};
 329
 330/* FCP ipl device attributes */
 331
 332DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n", (unsigned long long)
 333                   IPL_PARMBLOCK_START->ipl_info.fcp.wwpn);
 334DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n", (unsigned long long)
 335                   IPL_PARMBLOCK_START->ipl_info.fcp.lun);
 336DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long)
 337                   IPL_PARMBLOCK_START->ipl_info.fcp.bootprog);
 338DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
 339                   IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
 340
 341static struct attribute *ipl_fcp_attrs[] = {
 342        &sys_ipl_type_attr.attr,
 343        &sys_ipl_device_attr.attr,
 344        &sys_ipl_fcp_wwpn_attr.attr,
 345        &sys_ipl_fcp_lun_attr.attr,
 346        &sys_ipl_fcp_bootprog_attr.attr,
 347        &sys_ipl_fcp_br_lba_attr.attr,
 348        NULL,
 349};
 350
 351static struct attribute_group ipl_fcp_attr_group = {
 352        .attrs = ipl_fcp_attrs,
 353};
 354
 355/* CCW ipl device attributes */
 356
 357static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
 358                                     struct kobj_attribute *attr, char *page)
 359{
 360        char loadparm[LOADPARM_LEN + 1] = {};
 361
 362        if (!sclp_ipl_info.is_valid)
 363                return sprintf(page, "#unknown#\n");
 364        memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
 365        EBCASC(loadparm, LOADPARM_LEN);
 366        strstrip(loadparm);
 367        return sprintf(page, "%s\n", loadparm);
 368}
 369
 370static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
 371        __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
 372
 373static struct attribute *ipl_ccw_attrs[] = {
 374        &sys_ipl_type_attr.attr,
 375        &sys_ipl_device_attr.attr,
 376        &sys_ipl_ccw_loadparm_attr.attr,
 377        NULL,
 378};
 379
 380static struct attribute_group ipl_ccw_attr_group = {
 381        .attrs = ipl_ccw_attrs,
 382};
 383
 384/* NSS ipl device attributes */
 385
 386DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name);
 387
 388static struct attribute *ipl_nss_attrs[] = {
 389        &sys_ipl_type_attr.attr,
 390        &sys_ipl_nss_name_attr.attr,
 391        NULL,
 392};
 393
 394static struct attribute_group ipl_nss_attr_group = {
 395        .attrs = ipl_nss_attrs,
 396};
 397
 398/* UNKNOWN ipl device attributes */
 399
 400static struct attribute *ipl_unknown_attrs[] = {
 401        &sys_ipl_type_attr.attr,
 402        NULL,
 403};
 404
 405static struct attribute_group ipl_unknown_attr_group = {
 406        .attrs = ipl_unknown_attrs,
 407};
 408
 409static struct kset *ipl_kset;
 410
 411static int __init ipl_register_fcp_files(void)
 412{
 413        int rc;
 414
 415        rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
 416        if (rc)
 417                goto out;
 418        rc = sysfs_create_bin_file(&ipl_kset->kobj, &ipl_parameter_attr);
 419        if (rc)
 420                goto out_ipl_parm;
 421        rc = sysfs_create_bin_file(&ipl_kset->kobj, &ipl_scp_data_attr);
 422        if (!rc)
 423                goto out;
 424
 425        sysfs_remove_bin_file(&ipl_kset->kobj, &ipl_parameter_attr);
 426
 427out_ipl_parm:
 428        sysfs_remove_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
 429out:
 430        return rc;
 431}
 432
 433static void ipl_run(struct shutdown_trigger *trigger)
 434{
 435        diag308(DIAG308_IPL, NULL);
 436        if (MACHINE_IS_VM)
 437                __cpcmd("IPL", NULL, 0, NULL);
 438        else if (ipl_info.type == IPL_TYPE_CCW)
 439                reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
 440}
 441
 442static int __init ipl_init(void)
 443{
 444        int rc;
 445
 446        ipl_kset = kset_create_and_add("ipl", NULL, firmware_kobj);
 447        if (!ipl_kset) {
 448                rc = -ENOMEM;
 449                goto out;
 450        }
 451        switch (ipl_info.type) {
 452        case IPL_TYPE_CCW:
 453                rc = sysfs_create_group(&ipl_kset->kobj, &ipl_ccw_attr_group);
 454                break;
 455        case IPL_TYPE_FCP:
 456        case IPL_TYPE_FCP_DUMP:
 457                rc = ipl_register_fcp_files();
 458                break;
 459        case IPL_TYPE_NSS:
 460                rc = sysfs_create_group(&ipl_kset->kobj, &ipl_nss_attr_group);
 461                break;
 462        default:
 463                rc = sysfs_create_group(&ipl_kset->kobj,
 464                                        &ipl_unknown_attr_group);
 465                break;
 466        }
 467out:
 468        if (rc)
 469                panic("ipl_init failed: rc = %i\n", rc);
 470
 471        return 0;
 472}
 473
 474static struct shutdown_action __refdata ipl_action = {
 475        .name   = SHUTDOWN_ACTION_IPL_STR,
 476        .fn     = ipl_run,
 477        .init   = ipl_init,
 478};
 479
 480/*
 481 * reipl shutdown action: Reboot Linux on shutdown.
 482 */
 483
 484/* FCP reipl device attributes */
 485
 486DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n",
 487                   reipl_block_fcp->ipl_info.fcp.wwpn);
 488DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%016llx\n",
 489                   reipl_block_fcp->ipl_info.fcp.lun);
 490DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
 491                   reipl_block_fcp->ipl_info.fcp.bootprog);
 492DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
 493                   reipl_block_fcp->ipl_info.fcp.br_lba);
 494DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
 495                   reipl_block_fcp->ipl_info.fcp.devno);
 496
 497static struct attribute *reipl_fcp_attrs[] = {
 498        &sys_reipl_fcp_device_attr.attr,
 499        &sys_reipl_fcp_wwpn_attr.attr,
 500        &sys_reipl_fcp_lun_attr.attr,
 501        &sys_reipl_fcp_bootprog_attr.attr,
 502        &sys_reipl_fcp_br_lba_attr.attr,
 503        NULL,
 504};
 505
 506static struct attribute_group reipl_fcp_attr_group = {
 507        .name  = IPL_FCP_STR,
 508        .attrs = reipl_fcp_attrs,
 509};
 510
 511/* CCW reipl device attributes */
 512
 513DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
 514        reipl_block_ccw->ipl_info.ccw.devno);
 515
 516static void reipl_get_ascii_loadparm(char *loadparm)
 517{
 518        memcpy(loadparm, &reipl_block_ccw->ipl_info.ccw.load_param,
 519               LOADPARM_LEN);
 520        EBCASC(loadparm, LOADPARM_LEN);
 521        loadparm[LOADPARM_LEN] = 0;
 522        strstrip(loadparm);
 523}
 524
 525static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj,
 526                                       struct kobj_attribute *attr, char *page)
 527{
 528        char buf[LOADPARM_LEN + 1];
 529
 530        reipl_get_ascii_loadparm(buf);
 531        return sprintf(page, "%s\n", buf);
 532}
 533
 534static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
 535                                        struct kobj_attribute *attr,
 536                                        const char *buf, size_t len)
 537{
 538        int i, lp_len;
 539
 540        /* ignore trailing newline */
 541        lp_len = len;
 542        if ((len > 0) && (buf[len - 1] == '\n'))
 543                lp_len--;
 544        /* loadparm can have max 8 characters and must not start with a blank */
 545        if ((lp_len > LOADPARM_LEN) || ((lp_len > 0) && (buf[0] == ' ')))
 546                return -EINVAL;
 547        /* loadparm can only contain "a-z,A-Z,0-9,SP,." */
 548        for (i = 0; i < lp_len; i++) {
 549                if (isalpha(buf[i]) || isdigit(buf[i]) || (buf[i] == ' ') ||
 550                    (buf[i] == '.'))
 551                        continue;
 552                return -EINVAL;
 553        }
 554        /* initialize loadparm with blanks */
 555        memset(&reipl_block_ccw->ipl_info.ccw.load_param, ' ', LOADPARM_LEN);
 556        /* copy and convert to ebcdic */
 557        memcpy(&reipl_block_ccw->ipl_info.ccw.load_param, buf, lp_len);
 558        ASCEBC(reipl_block_ccw->ipl_info.ccw.load_param, LOADPARM_LEN);
 559        return len;
 560}
 561
 562static struct kobj_attribute sys_reipl_ccw_loadparm_attr =
 563        __ATTR(loadparm, 0644, reipl_ccw_loadparm_show,
 564               reipl_ccw_loadparm_store);
 565
 566static struct attribute *reipl_ccw_attrs[] = {
 567        &sys_reipl_ccw_device_attr.attr,
 568        &sys_reipl_ccw_loadparm_attr.attr,
 569        NULL,
 570};
 571
 572static struct attribute_group reipl_ccw_attr_group = {
 573        .name  = IPL_CCW_STR,
 574        .attrs = reipl_ccw_attrs,
 575};
 576
 577
 578/* NSS reipl device attributes */
 579
 580DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name);
 581
 582static struct attribute *reipl_nss_attrs[] = {
 583        &sys_reipl_nss_name_attr.attr,
 584        NULL,
 585};
 586
 587static struct attribute_group reipl_nss_attr_group = {
 588        .name  = IPL_NSS_STR,
 589        .attrs = reipl_nss_attrs,
 590};
 591
 592/* reipl type */
 593
 594static int reipl_set_type(enum ipl_type type)
 595{
 596        if (!(reipl_capabilities & type))
 597                return -EINVAL;
 598
 599        switch(type) {
 600        case IPL_TYPE_CCW:
 601                if (diag308_set_works)
 602                        reipl_method = REIPL_METHOD_CCW_DIAG;
 603                else if (MACHINE_IS_VM)
 604                        reipl_method = REIPL_METHOD_CCW_VM;
 605                else
 606                        reipl_method = REIPL_METHOD_CCW_CIO;
 607                break;
 608        case IPL_TYPE_FCP:
 609                if (diag308_set_works)
 610                        reipl_method = REIPL_METHOD_FCP_RW_DIAG;
 611                else if (MACHINE_IS_VM)
 612                        reipl_method = REIPL_METHOD_FCP_RO_VM;
 613                else
 614                        reipl_method = REIPL_METHOD_FCP_RO_DIAG;
 615                break;
 616        case IPL_TYPE_FCP_DUMP:
 617                reipl_method = REIPL_METHOD_FCP_DUMP;
 618                break;
 619        case IPL_TYPE_NSS:
 620                reipl_method = REIPL_METHOD_NSS;
 621                break;
 622        case IPL_TYPE_UNKNOWN:
 623                reipl_method = REIPL_METHOD_DEFAULT;
 624                break;
 625        default:
 626                BUG();
 627        }
 628        reipl_type = type;
 629        return 0;
 630}
 631
 632static ssize_t reipl_type_show(struct kobject *kobj,
 633                               struct kobj_attribute *attr, char *page)
 634{
 635        return sprintf(page, "%s\n", ipl_type_str(reipl_type));
 636}
 637
 638static ssize_t reipl_type_store(struct kobject *kobj,
 639                                struct kobj_attribute *attr,
 640                                const char *buf, size_t len)
 641{
 642        int rc = -EINVAL;
 643
 644        if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
 645                rc = reipl_set_type(IPL_TYPE_CCW);
 646        else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
 647                rc = reipl_set_type(IPL_TYPE_FCP);
 648        else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
 649                rc = reipl_set_type(IPL_TYPE_NSS);
 650        return (rc != 0) ? rc : len;
 651}
 652
 653static struct kobj_attribute reipl_type_attr =
 654        __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
 655
 656static struct kset *reipl_kset;
 657
 658void reipl_run(struct shutdown_trigger *trigger)
 659{
 660        struct ccw_dev_id devid;
 661        static char buf[100];
 662        char loadparm[LOADPARM_LEN + 1];
 663
 664        switch (reipl_method) {
 665        case REIPL_METHOD_CCW_CIO:
 666                devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
 667                devid.ssid  = 0;
 668                reipl_ccw_dev(&devid);
 669                break;
 670        case REIPL_METHOD_CCW_VM:
 671                reipl_get_ascii_loadparm(loadparm);
 672                if (strlen(loadparm) == 0)
 673                        sprintf(buf, "IPL %X CLEAR",
 674                                reipl_block_ccw->ipl_info.ccw.devno);
 675                else
 676                        sprintf(buf, "IPL %X CLEAR LOADPARM '%s'",
 677                                reipl_block_ccw->ipl_info.ccw.devno, loadparm);
 678                __cpcmd(buf, NULL, 0, NULL);
 679                break;
 680        case REIPL_METHOD_CCW_DIAG:
 681                diag308(DIAG308_SET, reipl_block_ccw);
 682                diag308(DIAG308_IPL, NULL);
 683                break;
 684        case REIPL_METHOD_FCP_RW_DIAG:
 685                diag308(DIAG308_SET, reipl_block_fcp);
 686                diag308(DIAG308_IPL, NULL);
 687                break;
 688        case REIPL_METHOD_FCP_RO_DIAG:
 689                diag308(DIAG308_IPL, NULL);
 690                break;
 691        case REIPL_METHOD_FCP_RO_VM:
 692                __cpcmd("IPL", NULL, 0, NULL);
 693                break;
 694        case REIPL_METHOD_NSS:
 695                sprintf(buf, "IPL %s", reipl_nss_name);
 696                __cpcmd(buf, NULL, 0, NULL);
 697                break;
 698        case REIPL_METHOD_DEFAULT:
 699                if (MACHINE_IS_VM)
 700                        __cpcmd("IPL", NULL, 0, NULL);
 701                diag308(DIAG308_IPL, NULL);
 702                break;
 703        case REIPL_METHOD_FCP_DUMP:
 704        default:
 705                break;
 706        }
 707        disabled_wait((unsigned long) __builtin_return_address(0));
 708}
 709
 710static void __init reipl_probe(void)
 711{
 712        void *buffer;
 713
 714        buffer = (void *) get_zeroed_page(GFP_KERNEL);
 715        if (!buffer)
 716                return;
 717        if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK)
 718                diag308_set_works = 1;
 719        free_page((unsigned long)buffer);
 720}
 721
 722static int __init reipl_nss_init(void)
 723{
 724        int rc;
 725
 726        if (!MACHINE_IS_VM)
 727                return 0;
 728        rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group);
 729        if (rc)
 730                return rc;
 731        strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
 732        reipl_capabilities |= IPL_TYPE_NSS;
 733        return 0;
 734}
 735
 736static int __init reipl_ccw_init(void)
 737{
 738        int rc;
 739
 740        reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
 741        if (!reipl_block_ccw)
 742                return -ENOMEM;
 743        rc = sysfs_create_group(&reipl_kset->kobj, &reipl_ccw_attr_group);
 744        if (rc) {
 745                free_page((unsigned long)reipl_block_ccw);
 746                return rc;
 747        }
 748        reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
 749        reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
 750        reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
 751        reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
 752        reipl_block_ccw->hdr.flags = DIAG308_FLAGS_LP_VALID;
 753        /* check if read scp info worked and set loadparm */
 754        if (sclp_ipl_info.is_valid)
 755                memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
 756                       &sclp_ipl_info.loadparm, LOADPARM_LEN);
 757        else
 758                /* read scp info failed: set empty loadparm (EBCDIC blanks) */
 759                memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
 760                       LOADPARM_LEN);
 761        if (!MACHINE_IS_VM && !diag308_set_works)
 762                sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
 763        if (ipl_info.type == IPL_TYPE_CCW)
 764                reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
 765        reipl_capabilities |= IPL_TYPE_CCW;
 766        return 0;
 767}
 768
 769static int __init reipl_fcp_init(void)
 770{
 771        int rc;
 772
 773        if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP))
 774                return 0;
 775        if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP))
 776                make_attrs_ro(reipl_fcp_attrs);
 777
 778        reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
 779        if (!reipl_block_fcp)
 780                return -ENOMEM;
 781        rc = sysfs_create_group(&reipl_kset->kobj, &reipl_fcp_attr_group);
 782        if (rc) {
 783                free_page((unsigned long)reipl_block_fcp);
 784                return rc;
 785        }
 786        if (ipl_info.type == IPL_TYPE_FCP) {
 787                memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
 788        } else {
 789                reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
 790                reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
 791                reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
 792                reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
 793                reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL;
 794        }
 795        reipl_capabilities |= IPL_TYPE_FCP;
 796        return 0;
 797}
 798
 799static int __init reipl_init(void)
 800{
 801        int rc;
 802
 803        reipl_kset = kset_create_and_add("reipl", NULL, firmware_kobj);
 804        if (!reipl_kset)
 805                return -ENOMEM;
 806        rc = sysfs_create_file(&reipl_kset->kobj, &reipl_type_attr.attr);
 807        if (rc) {
 808                kset_unregister(reipl_kset);
 809                return rc;
 810        }
 811        rc = reipl_ccw_init();
 812        if (rc)
 813                return rc;
 814        rc = reipl_fcp_init();
 815        if (rc)
 816                return rc;
 817        rc = reipl_nss_init();
 818        if (rc)
 819                return rc;
 820        rc = reipl_set_type(ipl_info.type);
 821        if (rc)
 822                return rc;
 823        return 0;
 824}
 825
 826static struct shutdown_action __refdata reipl_action = {
 827        .name   = SHUTDOWN_ACTION_REIPL_STR,
 828        .fn     = reipl_run,
 829        .init   = reipl_init,
 830};
 831
 832/*
 833 * dump shutdown action: Dump Linux on shutdown.
 834 */
 835
 836/* FCP dump device attributes */
 837
 838DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n",
 839                   dump_block_fcp->ipl_info.fcp.wwpn);
 840DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n",
 841                   dump_block_fcp->ipl_info.fcp.lun);
 842DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
 843                   dump_block_fcp->ipl_info.fcp.bootprog);
 844DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
 845                   dump_block_fcp->ipl_info.fcp.br_lba);
 846DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
 847                   dump_block_fcp->ipl_info.fcp.devno);
 848
 849static struct attribute *dump_fcp_attrs[] = {
 850        &sys_dump_fcp_device_attr.attr,
 851        &sys_dump_fcp_wwpn_attr.attr,
 852        &sys_dump_fcp_lun_attr.attr,
 853        &sys_dump_fcp_bootprog_attr.attr,
 854        &sys_dump_fcp_br_lba_attr.attr,
 855        NULL,
 856};
 857
 858static struct attribute_group dump_fcp_attr_group = {
 859        .name  = IPL_FCP_STR,
 860        .attrs = dump_fcp_attrs,
 861};
 862
 863/* CCW dump device attributes */
 864
 865DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
 866                   dump_block_ccw->ipl_info.ccw.devno);
 867
 868static struct attribute *dump_ccw_attrs[] = {
 869        &sys_dump_ccw_device_attr.attr,
 870        NULL,
 871};
 872
 873static struct attribute_group dump_ccw_attr_group = {
 874        .name  = IPL_CCW_STR,
 875        .attrs = dump_ccw_attrs,
 876};
 877
 878/* dump type */
 879
 880static int dump_set_type(enum dump_type type)
 881{
 882        if (!(dump_capabilities & type))
 883                return -EINVAL;
 884        switch (type) {
 885        case DUMP_TYPE_CCW:
 886                if (diag308_set_works)
 887                        dump_method = DUMP_METHOD_CCW_DIAG;
 888                else if (MACHINE_IS_VM)
 889                        dump_method = DUMP_METHOD_CCW_VM;
 890                else
 891                        dump_method = DUMP_METHOD_CCW_CIO;
 892                break;
 893        case DUMP_TYPE_FCP:
 894                dump_method = DUMP_METHOD_FCP_DIAG;
 895                break;
 896        default:
 897                dump_method = DUMP_METHOD_NONE;
 898        }
 899        dump_type = type;
 900        return 0;
 901}
 902
 903static ssize_t dump_type_show(struct kobject *kobj,
 904                              struct kobj_attribute *attr, char *page)
 905{
 906        return sprintf(page, "%s\n", dump_type_str(dump_type));
 907}
 908
 909static ssize_t dump_type_store(struct kobject *kobj,
 910                               struct kobj_attribute *attr,
 911                               const char *buf, size_t len)
 912{
 913        int rc = -EINVAL;
 914
 915        if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
 916                rc = dump_set_type(DUMP_TYPE_NONE);
 917        else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
 918                rc = dump_set_type(DUMP_TYPE_CCW);
 919        else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
 920                rc = dump_set_type(DUMP_TYPE_FCP);
 921        return (rc != 0) ? rc : len;
 922}
 923
 924static struct kobj_attribute dump_type_attr =
 925        __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
 926
 927static struct kset *dump_kset;
 928
 929static void dump_run(struct shutdown_trigger *trigger)
 930{
 931        struct ccw_dev_id devid;
 932        static char buf[100];
 933
 934        switch (dump_method) {
 935        case DUMP_METHOD_CCW_CIO:
 936                smp_send_stop();
 937                devid.devno = dump_block_ccw->ipl_info.ccw.devno;
 938                devid.ssid  = 0;
 939                reipl_ccw_dev(&devid);
 940                break;
 941        case DUMP_METHOD_CCW_VM:
 942                smp_send_stop();
 943                sprintf(buf, "STORE STATUS");
 944                __cpcmd(buf, NULL, 0, NULL);
 945                sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
 946                __cpcmd(buf, NULL, 0, NULL);
 947                break;
 948        case DUMP_METHOD_CCW_DIAG:
 949                diag308(DIAG308_SET, dump_block_ccw);
 950                diag308(DIAG308_DUMP, NULL);
 951                break;
 952        case DUMP_METHOD_FCP_DIAG:
 953                diag308(DIAG308_SET, dump_block_fcp);
 954                diag308(DIAG308_DUMP, NULL);
 955                break;
 956        case DUMP_METHOD_NONE:
 957        default:
 958                return;
 959        }
 960        printk(KERN_EMERG "Dump failed!\n");
 961}
 962
 963static int __init dump_ccw_init(void)
 964{
 965        int rc;
 966
 967        dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
 968        if (!dump_block_ccw)
 969                return -ENOMEM;
 970        rc = sysfs_create_group(&dump_kset->kobj, &dump_ccw_attr_group);
 971        if (rc) {
 972                free_page((unsigned long)dump_block_ccw);
 973                return rc;
 974        }
 975        dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
 976        dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
 977        dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
 978        dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
 979        dump_capabilities |= DUMP_TYPE_CCW;
 980        return 0;
 981}
 982
 983static int __init dump_fcp_init(void)
 984{
 985        int rc;
 986
 987        if (!sclp_ipl_info.has_dump)
 988                return 0; /* LDIPL DUMP is not installed */
 989        if (!diag308_set_works)
 990                return 0;
 991        dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
 992        if (!dump_block_fcp)
 993                return -ENOMEM;
 994        rc = sysfs_create_group(&dump_kset->kobj, &dump_fcp_attr_group);
 995        if (rc) {
 996                free_page((unsigned long)dump_block_fcp);
 997                return rc;
 998        }
 999        dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
1000        dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
1001        dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
1002        dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
1003        dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
1004        dump_capabilities |= DUMP_TYPE_FCP;
1005        return 0;
1006}
1007
1008static int __init dump_init(void)
1009{
1010        int rc;
1011
1012        dump_kset = kset_create_and_add("dump", NULL, firmware_kobj);
1013        if (!dump_kset)
1014                return -ENOMEM;
1015        rc = sysfs_create_file(&dump_kset->kobj, &dump_type_attr.attr);
1016        if (rc) {
1017                kset_unregister(dump_kset);
1018                return rc;
1019        }
1020        rc = dump_ccw_init();
1021        if (rc)
1022                return rc;
1023        rc = dump_fcp_init();
1024        if (rc)
1025                return rc;
1026        dump_set_type(DUMP_TYPE_NONE);
1027        return 0;
1028}
1029
1030static struct shutdown_action __refdata dump_action = {
1031        .name   = SHUTDOWN_ACTION_DUMP_STR,
1032        .fn     = dump_run,
1033        .init   = dump_init,
1034};
1035
1036/*
1037 * vmcmd shutdown action: Trigger vm command on shutdown.
1038 */
1039
1040static char vmcmd_on_reboot[128];
1041static char vmcmd_on_panic[128];
1042static char vmcmd_on_halt[128];
1043static char vmcmd_on_poff[128];
1044
1045DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot);
1046DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic);
1047DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt);
1048DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff);
1049
1050static struct attribute *vmcmd_attrs[] = {
1051        &sys_vmcmd_on_reboot_attr.attr,
1052        &sys_vmcmd_on_panic_attr.attr,
1053        &sys_vmcmd_on_halt_attr.attr,
1054        &sys_vmcmd_on_poff_attr.attr,
1055        NULL,
1056};
1057
1058static struct attribute_group vmcmd_attr_group = {
1059        .attrs = vmcmd_attrs,
1060};
1061
1062static struct kset *vmcmd_kset;
1063
1064static void vmcmd_run(struct shutdown_trigger *trigger)
1065{
1066        char *cmd, *next_cmd;
1067
1068        if (strcmp(trigger->name, ON_REIPL_STR) == 0)
1069                cmd = vmcmd_on_reboot;
1070        else if (strcmp(trigger->name, ON_PANIC_STR) == 0)
1071                cmd = vmcmd_on_panic;
1072        else if (strcmp(trigger->name, ON_HALT_STR) == 0)
1073                cmd = vmcmd_on_halt;
1074        else if (strcmp(trigger->name, ON_POFF_STR) == 0)
1075                cmd = vmcmd_on_poff;
1076        else
1077                return;
1078
1079        if (strlen(cmd) == 0)
1080                return;
1081        do {
1082                next_cmd = strchr(cmd, '\n');
1083                if (next_cmd) {
1084                        next_cmd[0] = 0;
1085                        next_cmd += 1;
1086                }
1087                __cpcmd(cmd, NULL, 0, NULL);
1088                cmd = next_cmd;
1089        } while (cmd != NULL);
1090}
1091
1092static int vmcmd_init(void)
1093{
1094        if (!MACHINE_IS_VM)
1095                return -ENOTSUPP;
1096        vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj);
1097        if (!vmcmd_kset)
1098                return -ENOMEM;
1099        return sysfs_create_group(&vmcmd_kset->kobj, &vmcmd_attr_group);
1100}
1101
1102static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR,
1103                                              vmcmd_run, vmcmd_init};
1104
1105/*
1106 * stop shutdown action: Stop Linux on shutdown.
1107 */
1108
1109static void stop_run(struct shutdown_trigger *trigger)
1110{
1111        if (strcmp(trigger->name, ON_PANIC_STR) == 0)
1112                disabled_wait((unsigned long) __builtin_return_address(0));
1113        else {
1114                signal_processor(smp_processor_id(), sigp_stop);
1115                for (;;);
1116        }
1117}
1118
1119static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
1120                                             stop_run, NULL};
1121
1122/* action list */
1123
1124static struct shutdown_action *shutdown_actions_list[] = {
1125        &ipl_action, &reipl_action, &dump_action, &vmcmd_action, &stop_action};
1126#define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *))
1127
1128/*
1129 * Trigger section
1130 */
1131
1132static struct kset *shutdown_actions_kset;
1133
1134static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
1135                       size_t len)
1136{
1137        int i;
1138        for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
1139                if (!shutdown_actions_list[i])
1140                        continue;
1141                if (strncmp(buf, shutdown_actions_list[i]->name,
1142                            strlen(shutdown_actions_list[i]->name)) == 0) {
1143                        trigger->action = shutdown_actions_list[i];
1144                        return len;
1145                }
1146        }
1147        return -EINVAL;
1148}
1149
1150/* on reipl */
1151
1152static struct shutdown_trigger on_reboot_trigger = {ON_REIPL_STR,
1153                                                    &reipl_action};
1154
1155static ssize_t on_reboot_show(struct kobject *kobj,
1156                              struct kobj_attribute *attr, char *page)
1157{
1158        return sprintf(page, "%s\n", on_reboot_trigger.action->name);
1159}
1160
1161static ssize_t on_reboot_store(struct kobject *kobj,
1162                               struct kobj_attribute *attr,
1163                               const char *buf, size_t len)
1164{
1165        return set_trigger(buf, &on_reboot_trigger, len);
1166}
1167
1168static struct kobj_attribute on_reboot_attr =
1169        __ATTR(on_reboot, 0644, on_reboot_show, on_reboot_store);
1170
1171static void do_machine_restart(char *__unused)
1172{
1173        smp_send_stop();
1174        on_reboot_trigger.action->fn(&on_reboot_trigger);
1175        reipl_run(NULL);
1176}
1177void (*_machine_restart)(char *command) = do_machine_restart;
1178
1179/* on panic */
1180
1181static struct shutdown_trigger on_panic_trigger = {ON_PANIC_STR, &stop_action};
1182
1183static ssize_t on_panic_show(struct kobject *kobj,
1184                             struct kobj_attribute *attr, char *page)
1185{
1186        return sprintf(page, "%s\n", on_panic_trigger.action->name);
1187}
1188
1189static ssize_t on_panic_store(struct kobject *kobj,
1190                              struct kobj_attribute *attr,
1191                              const char *buf, size_t len)
1192{
1193        return set_trigger(buf, &on_panic_trigger, len);
1194}
1195
1196static struct kobj_attribute on_panic_attr =
1197        __ATTR(on_panic, 0644, on_panic_show, on_panic_store);
1198
1199static void do_panic(void)
1200{
1201        on_panic_trigger.action->fn(&on_panic_trigger);
1202        stop_run(&on_panic_trigger);
1203}
1204
1205/* on halt */
1206
1207static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};
1208
1209static ssize_t on_halt_show(struct kobject *kobj,
1210                            struct kobj_attribute *attr, char *page)
1211{
1212        return sprintf(page, "%s\n", on_halt_trigger.action->name);
1213}
1214
1215static ssize_t on_halt_store(struct kobject *kobj,
1216                             struct kobj_attribute *attr,
1217                             const char *buf, size_t len)
1218{
1219        return set_trigger(buf, &on_halt_trigger, len);
1220}
1221
1222static struct kobj_attribute on_halt_attr =
1223        __ATTR(on_halt, 0644, on_halt_show, on_halt_store);
1224
1225
1226static void do_machine_halt(void)
1227{
1228        smp_send_stop();
1229        on_halt_trigger.action->fn(&on_halt_trigger);
1230        stop_run(&on_halt_trigger);
1231}
1232void (*_machine_halt)(void) = do_machine_halt;
1233
1234/* on power off */
1235
1236static struct shutdown_trigger on_poff_trigger = {ON_POFF_STR, &stop_action};
1237
1238static ssize_t on_poff_show(struct kobject *kobj,
1239                            struct kobj_attribute *attr, char *page)
1240{
1241        return sprintf(page, "%s\n", on_poff_trigger.action->name);
1242}
1243
1244static ssize_t on_poff_store(struct kobject *kobj,
1245                             struct kobj_attribute *attr,
1246                             const char *buf, size_t len)
1247{
1248        return set_trigger(buf, &on_poff_trigger, len);
1249}
1250
1251static struct kobj_attribute on_poff_attr =
1252        __ATTR(on_poff, 0644, on_poff_show, on_poff_store);
1253
1254
1255static void do_machine_power_off(void)
1256{
1257        smp_send_stop();
1258        on_poff_trigger.action->fn(&on_poff_trigger);
1259        stop_run(&on_poff_trigger);
1260}
1261void (*_machine_power_off)(void) = do_machine_power_off;
1262
1263static void __init shutdown_triggers_init(void)
1264{
1265        shutdown_actions_kset = kset_create_and_add("shutdown_actions", NULL,
1266                                                    firmware_kobj);
1267        if (!shutdown_actions_kset)
1268                goto fail;
1269        if (sysfs_create_file(&shutdown_actions_kset->kobj,
1270                              &on_reboot_attr.attr))
1271                goto fail;
1272        if (sysfs_create_file(&shutdown_actions_kset->kobj,
1273                              &on_panic_attr.attr))
1274                goto fail;
1275        if (sysfs_create_file(&shutdown_actions_kset->kobj,
1276                              &on_halt_attr.attr))
1277                goto fail;
1278        if (sysfs_create_file(&shutdown_actions_kset->kobj,
1279                              &on_poff_attr.attr))
1280                goto fail;
1281
1282        return;
1283fail:
1284        panic("shutdown_triggers_init failed\n");
1285}
1286
1287static void __init shutdown_actions_init(void)
1288{
1289        int i;
1290
1291        for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
1292                if (!shutdown_actions_list[i]->init)
1293                        continue;
1294                if (shutdown_actions_list[i]->init())
1295                        shutdown_actions_list[i] = NULL;
1296        }
1297}
1298
1299static int __init s390_ipl_init(void)
1300{
1301        reipl_probe();
1302        sclp_get_ipl_info(&sclp_ipl_info);
1303        shutdown_actions_init();
1304        shutdown_triggers_init();
1305        return 0;
1306}
1307
1308__initcall(s390_ipl_init);
1309
1310static void __init strncpy_skip_quote(char *dst, char *src, int n)
1311{
1312        int sx, dx;
1313
1314        dx = 0;
1315        for (sx = 0; src[sx] != 0; sx++) {
1316                if (src[sx] == '"')
1317                        continue;
1318                dst[dx++] = src[sx];
1319                if (dx >= n)
1320                        break;
1321        }
1322}
1323
1324static int __init vmcmd_on_reboot_setup(char *str)
1325{
1326        if (!MACHINE_IS_VM)
1327                return 1;
1328        strncpy_skip_quote(vmcmd_on_reboot, str, 127);
1329        vmcmd_on_reboot[127] = 0;
1330        on_reboot_trigger.action = &vmcmd_action;
1331        return 1;
1332}
1333__setup("vmreboot=", vmcmd_on_reboot_setup);
1334
1335static int __init vmcmd_on_panic_setup(char *str)
1336{
1337        if (!MACHINE_IS_VM)
1338                return 1;
1339        strncpy_skip_quote(vmcmd_on_panic, str, 127);
1340        vmcmd_on_panic[127] = 0;
1341        on_panic_trigger.action = &vmcmd_action;
1342        return 1;
1343}
1344__setup("vmpanic=", vmcmd_on_panic_setup);
1345
1346static int __init vmcmd_on_halt_setup(char *str)
1347{
1348        if (!MACHINE_IS_VM)
1349                return 1;
1350        strncpy_skip_quote(vmcmd_on_halt, str, 127);
1351        vmcmd_on_halt[127] = 0;
1352        on_halt_trigger.action = &vmcmd_action;
1353        return 1;
1354}
1355__setup("vmhalt=", vmcmd_on_halt_setup);
1356
1357static int __init vmcmd_on_poff_setup(char *str)
1358{
1359        if (!MACHINE_IS_VM)
1360                return 1;
1361        strncpy_skip_quote(vmcmd_on_poff, str, 127);
1362        vmcmd_on_poff[127] = 0;
1363        on_poff_trigger.action = &vmcmd_action;
1364        return 1;
1365}
1366__setup("vmpoff=", vmcmd_on_poff_setup);
1367
1368static int on_panic_notify(struct notifier_block *self,
1369                           unsigned long event, void *data)
1370{
1371        do_panic();
1372        return NOTIFY_OK;
1373}
1374
1375static struct notifier_block on_panic_nb = {
1376        .notifier_call = on_panic_notify,
1377        .priority = 0,
1378};
1379
1380void __init setup_ipl(void)
1381{
1382        ipl_info.type = get_ipl_type();
1383        switch (ipl_info.type) {
1384        case IPL_TYPE_CCW:
1385                ipl_info.data.ccw.dev_id.devno = ipl_devno;
1386                ipl_info.data.ccw.dev_id.ssid = 0;
1387                break;
1388        case IPL_TYPE_FCP:
1389        case IPL_TYPE_FCP_DUMP:
1390                ipl_info.data.fcp.dev_id.devno =
1391                        IPL_PARMBLOCK_START->ipl_info.fcp.devno;
1392                ipl_info.data.fcp.dev_id.ssid = 0;
1393                ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn;
1394                ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun;
1395                break;
1396        case IPL_TYPE_NSS:
1397                strncpy(ipl_info.data.nss.name, kernel_nss_name,
1398                        sizeof(ipl_info.data.nss.name));
1399                break;
1400        case IPL_TYPE_UNKNOWN:
1401        default:
1402                /* We have no info to copy */
1403                break;
1404        }
1405        atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
1406}
1407
1408void __init ipl_save_parameters(void)
1409{
1410        struct cio_iplinfo iplinfo;
1411        unsigned int *ipl_ptr;
1412        void *src, *dst;
1413
1414        if (cio_get_iplinfo(&iplinfo))
1415                return;
1416
1417        ipl_devno = iplinfo.devno;
1418        ipl_flags |= IPL_DEVNO_VALID;
1419        if (!iplinfo.is_qdio)
1420                return;
1421        ipl_flags |= IPL_PARMBLOCK_VALID;
1422        ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR;
1423        src = (void *)(unsigned long)*ipl_ptr;
1424        dst = (void *)IPL_PARMBLOCK_ORIGIN;
1425        memmove(dst, src, PAGE_SIZE);
1426        *ipl_ptr = IPL_PARMBLOCK_ORIGIN;
1427}
1428
1429static LIST_HEAD(rcall);
1430static DEFINE_MUTEX(rcall_mutex);
1431
1432void register_reset_call(struct reset_call *reset)
1433{
1434        mutex_lock(&rcall_mutex);
1435        list_add(&reset->list, &rcall);
1436        mutex_unlock(&rcall_mutex);
1437}
1438EXPORT_SYMBOL_GPL(register_reset_call);
1439
1440void unregister_reset_call(struct reset_call *reset)
1441{
1442        mutex_lock(&rcall_mutex);
1443        list_del(&reset->list);
1444        mutex_unlock(&rcall_mutex);
1445}
1446EXPORT_SYMBOL_GPL(unregister_reset_call);
1447
1448static void do_reset_calls(void)
1449{
1450        struct reset_call *reset;
1451
1452        list_for_each_entry(reset, &rcall, list)
1453                reset->fn();
1454}
1455
1456u32 dump_prefix_page;
1457
1458void s390_reset_system(void)
1459{
1460        struct _lowcore *lc;
1461
1462        lc = (struct _lowcore *)(unsigned long) store_prefix();
1463
1464        /* Stack for interrupt/machine check handler */
1465        lc->panic_stack = S390_lowcore.panic_stack;
1466
1467        /* Save prefix page address for dump case */
1468        dump_prefix_page = (u32)(unsigned long) lc;
1469
1470        /* Disable prefixing */
1471        set_prefix(0);
1472
1473        /* Disable lowcore protection */
1474        __ctl_clear_bit(0,28);
1475
1476        /* Set new machine check handler */
1477        S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
1478        S390_lowcore.mcck_new_psw.addr =
1479                PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
1480
1481        /* Set new program check handler */
1482        S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
1483        S390_lowcore.program_new_psw.addr =
1484                PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
1485
1486        do_reset_calls();
1487}
1488
1489
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.