]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - arch/s390/kernel/ipl.c
Merge branch 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
[mirror_ubuntu-bionic-kernel.git] / arch / s390 / kernel / ipl.c
CommitLineData
ff6b8ea6 1/*
ff6b8ea6
MH
2 * ipl/reipl/dump support for Linux on s390.
3 *
a53c8fab 4 * Copyright IBM Corp. 2005, 2012
ff6b8ea6
MH
5 * Author(s): Michael Holzheu <holzheu@de.ibm.com>
6 * Heiko Carstens <heiko.carstens@de.ibm.com>
7 * Volker Sameske <sameske@de.ibm.com>
8 */
9
10#include <linux/types.h>
11#include <linux/module.h>
12#include <linux/device.h>
13#include <linux/delay.h>
14#include <linux/reboot.h>
03a4d208 15#include <linux/ctype.h>
0788fea4 16#include <linux/fs.h>
5a0e3ad6 17#include <linux/gfp.h>
60a0c68d 18#include <linux/crash_dump.h>
3ab121ab 19#include <linux/debug_locks.h>
46b05d26 20#include <asm/ipl.h>
ff6b8ea6
MH
21#include <asm/smp.h>
22#include <asm/setup.h>
23#include <asm/cpcmd.h>
24#include <asm/cio.h>
03a4d208 25#include <asm/ebcdic.h>
15e9b586 26#include <asm/reset.h>
ab14de6c 27#include <asm/sclp.h>
159d1ff8 28#include <asm/checksum.h>
3ab121ab 29#include <asm/debug.h>
4857d4bb 30#include <asm/os_info.h>
638ad34a 31#include "entry.h"
ff6b8ea6
MH
32
33#define IPL_PARM_BLOCK_VERSION 0
03a4d208 34
411ed322
MH
35#define IPL_UNKNOWN_STR "unknown"
36#define IPL_CCW_STR "ccw"
37#define IPL_FCP_STR "fcp"
38#define IPL_FCP_DUMP_STR "fcp_dump"
39#define IPL_NSS_STR "nss"
615b04b3 40
99ca4e58
MH
41#define DUMP_CCW_STR "ccw"
42#define DUMP_FCP_STR "fcp"
43#define DUMP_NONE_STR "none"
44
45/*
46 * Four shutdown trigger types are supported:
47 * - panic
48 * - halt
49 * - power off
50 * - reipl
7dd6b334 51 * - restart
99ca4e58
MH
52 */
53#define ON_PANIC_STR "on_panic"
54#define ON_HALT_STR "on_halt"
55#define ON_POFF_STR "on_poff"
56#define ON_REIPL_STR "on_reboot"
7dd6b334 57#define ON_RESTART_STR "on_restart"
99ca4e58
MH
58
59struct shutdown_action;
60struct shutdown_trigger {
61 char *name;
62 struct shutdown_action *action;
63};
64
65/*
099b7651 66 * The following shutdown action types are supported:
99ca4e58
MH
67 */
68#define SHUTDOWN_ACTION_IPL_STR "ipl"
69#define SHUTDOWN_ACTION_REIPL_STR "reipl"
70#define SHUTDOWN_ACTION_DUMP_STR "dump"
71#define SHUTDOWN_ACTION_VMCMD_STR "vmcmd"
72#define SHUTDOWN_ACTION_STOP_STR "stop"
099b7651 73#define SHUTDOWN_ACTION_DUMP_REIPL_STR "dump_reipl"
99ca4e58
MH
74
75struct shutdown_action {
76 char *name;
77 void (*fn) (struct shutdown_trigger *trigger);
78 int (*init) (void);
81088819 79 int init_rc;
99ca4e58
MH
80};
81
ff6b8ea6
MH
82static char *ipl_type_str(enum ipl_type type)
83{
84 switch (type) {
ff6b8ea6
MH
85 case IPL_TYPE_CCW:
86 return IPL_CCW_STR;
87 case IPL_TYPE_FCP:
88 return IPL_FCP_STR;
411ed322
MH
89 case IPL_TYPE_FCP_DUMP:
90 return IPL_FCP_DUMP_STR;
fe355b7f
HY
91 case IPL_TYPE_NSS:
92 return IPL_NSS_STR;
ff6b8ea6
MH
93 case IPL_TYPE_UNKNOWN:
94 default:
95 return IPL_UNKNOWN_STR;
96 }
97}
98
411ed322
MH
99enum dump_type {
100 DUMP_TYPE_NONE = 1,
101 DUMP_TYPE_CCW = 2,
102 DUMP_TYPE_FCP = 4,
103};
104
411ed322
MH
105static char *dump_type_str(enum dump_type type)
106{
107 switch (type) {
108 case DUMP_TYPE_NONE:
109 return DUMP_NONE_STR;
110 case DUMP_TYPE_CCW:
111 return DUMP_CCW_STR;
112 case DUMP_TYPE_FCP:
113 return DUMP_FCP_STR;
114 default:
115 return NULL;
116 }
117}
118
119/*
120 * Must be in data section since the bss section
121 * is not cleared when these are accessed.
122 */
123static u16 ipl_devno __attribute__((__section__(".data"))) = 0;
124u32 ipl_flags __attribute__((__section__(".data"))) = 0;
125
ff6b8ea6 126enum ipl_method {
411ed322
MH
127 REIPL_METHOD_CCW_CIO,
128 REIPL_METHOD_CCW_DIAG,
129 REIPL_METHOD_CCW_VM,
130 REIPL_METHOD_FCP_RO_DIAG,
131 REIPL_METHOD_FCP_RW_DIAG,
132 REIPL_METHOD_FCP_RO_VM,
133 REIPL_METHOD_FCP_DUMP,
134 REIPL_METHOD_NSS,
a0443fbb 135 REIPL_METHOD_NSS_DIAG,
411ed322
MH
136 REIPL_METHOD_DEFAULT,
137};
138
139enum dump_method {
140 DUMP_METHOD_NONE,
141 DUMP_METHOD_CCW_CIO,
142 DUMP_METHOD_CCW_DIAG,
143 DUMP_METHOD_CCW_VM,
144 DUMP_METHOD_FCP_DIAG,
ff6b8ea6
MH
145};
146
ff6b8ea6
MH
147static int diag308_set_works = 0;
148
a0443fbb
HB
149static struct ipl_parameter_block ipl_block;
150
ff6b8ea6 151static int reipl_capabilities = IPL_TYPE_UNKNOWN;
fe355b7f 152
ff6b8ea6 153static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
411ed322 154static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
ff6b8ea6
MH
155static struct ipl_parameter_block *reipl_block_fcp;
156static struct ipl_parameter_block *reipl_block_ccw;
a0443fbb 157static struct ipl_parameter_block *reipl_block_nss;
099b7651 158static struct ipl_parameter_block *reipl_block_actual;
fe355b7f 159
411ed322
MH
160static int dump_capabilities = DUMP_TYPE_NONE;
161static enum dump_type dump_type = DUMP_TYPE_NONE;
162static enum dump_method dump_method = DUMP_METHOD_NONE;
ff6b8ea6
MH
163static struct ipl_parameter_block *dump_block_fcp;
164static struct ipl_parameter_block *dump_block_ccw;
165
05dd2530
HC
166static struct sclp_ipl_info sclp_ipl_info;
167
46b05d26 168int diag308(unsigned long subcode, void *addr)
ff6b8ea6 169{
94c12cc7 170 register unsigned long _addr asm("0") = (unsigned long) addr;
ff6b8ea6
MH
171 register unsigned long _rc asm("1") = 0;
172
94c12cc7
MS
173 asm volatile(
174 " diag %0,%2,0x308\n"
175 "0:\n"
176 EX_TABLE(0b,0b)
ff6b8ea6 177 : "+d" (_addr), "+d" (_rc)
94c12cc7 178 : "d" (subcode) : "cc", "memory");
ff6b8ea6
MH
179 return _rc;
180}
411ed322 181EXPORT_SYMBOL_GPL(diag308);
ff6b8ea6
MH
182
183/* SYSFS */
184
3be7ae63 185#define IPL_ATTR_SHOW_FN(_prefix, _name, _format, args...) \
9b949165
GKH
186static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
187 struct kobj_attribute *attr, \
ff6b8ea6
MH
188 char *page) \
189{ \
3be7ae63
SO
190 return snprintf(page, PAGE_SIZE, _format, ##args); \
191}
192
193#define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \
194IPL_ATTR_SHOW_FN(_prefix, _name, _format, _value) \
9b949165 195static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
3be7ae63 196 __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL)
ff6b8ea6
MH
197
198#define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \
3be7ae63 199IPL_ATTR_SHOW_FN(_prefix, _name, _fmt_out, (unsigned long long) _value) \
9b949165
GKH
200static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
201 struct kobj_attribute *attr, \
ff6b8ea6
MH
202 const char *buf, size_t len) \
203{ \
204 unsigned long long value; \
205 if (sscanf(buf, _fmt_in, &value) != 1) \
206 return -EINVAL; \
207 _value = value; \
208 return len; \
209} \
9b949165 210static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
ff6b8ea6
MH
211 __ATTR(_name,(S_IRUGO | S_IWUSR), \
212 sys_##_prefix##_##_name##_show, \
3be7ae63 213 sys_##_prefix##_##_name##_store)
ff6b8ea6 214
fe355b7f 215#define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
3be7ae63 216IPL_ATTR_SHOW_FN(_prefix, _name, _fmt_out, _value) \
9b949165
GKH
217static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
218 struct kobj_attribute *attr, \
fe355b7f
HY
219 const char *buf, size_t len) \
220{ \
99ca4e58 221 strncpy(_value, buf, sizeof(_value) - 1); \
1d802e24 222 strim(_value); \
fe355b7f
HY
223 return len; \
224} \
9b949165 225static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
fe355b7f
HY
226 __ATTR(_name,(S_IRUGO | S_IWUSR), \
227 sys_##_prefix##_##_name##_show, \
3be7ae63 228 sys_##_prefix##_##_name##_store)
fe355b7f 229
ff6b8ea6
MH
230static void make_attrs_ro(struct attribute **attrs)
231{
232 while (*attrs) {
233 (*attrs)->mode = S_IRUGO;
234 attrs++;
235 }
236}
237
238/*
239 * ipl section
240 */
241
411ed322 242static __init enum ipl_type get_ipl_type(void)
ff6b8ea6
MH
243{
244 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
245
fe355b7f
HY
246 if (ipl_flags & IPL_NSS_VALID)
247 return IPL_TYPE_NSS;
e87bfe51 248 if (!(ipl_flags & IPL_DEVNO_VALID))
ff6b8ea6 249 return IPL_TYPE_UNKNOWN;
e87bfe51 250 if (!(ipl_flags & IPL_PARMBLOCK_VALID))
ff6b8ea6
MH
251 return IPL_TYPE_CCW;
252 if (ipl->hdr.version > IPL_MAX_SUPPORTED_VERSION)
253 return IPL_TYPE_UNKNOWN;
254 if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP)
255 return IPL_TYPE_UNKNOWN;
411ed322
MH
256 if (ipl->ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP)
257 return IPL_TYPE_FCP_DUMP;
ff6b8ea6
MH
258 return IPL_TYPE_FCP;
259}
260
411ed322
MH
261struct ipl_info ipl_info;
262EXPORT_SYMBOL_GPL(ipl_info);
263
9b949165
GKH
264static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
265 char *page)
ff6b8ea6 266{
411ed322 267 return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
ff6b8ea6
MH
268}
269
9b949165 270static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
ff6b8ea6 271
a0443fbb 272/* VM IPL PARM routines */
c4736d96
MS
273static size_t reipl_get_ascii_vmparm(char *dest, size_t size,
274 const struct ipl_parameter_block *ipb)
a0443fbb
HB
275{
276 int i;
684d2fd4 277 size_t len;
a0443fbb
HB
278 char has_lowercase = 0;
279
684d2fd4 280 len = 0;
a0443fbb
HB
281 if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
282 (ipb->ipl_info.ccw.vm_parm_len > 0)) {
283
684d2fd4 284 len = min_t(size_t, size - 1, ipb->ipl_info.ccw.vm_parm_len);
a0443fbb
HB
285 memcpy(dest, ipb->ipl_info.ccw.vm_parm, len);
286 /* If at least one character is lowercase, we assume mixed
287 * case; otherwise we convert everything to lowercase.
288 */
289 for (i = 0; i < len; i++)
290 if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */
291 (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */
292 (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */
293 has_lowercase = 1;
294 break;
295 }
296 if (!has_lowercase)
297 EBC_TOLOWER(dest, len);
298 EBCASC(dest, len);
299 }
300 dest[len] = 0;
684d2fd4
HB
301
302 return len;
a0443fbb
HB
303}
304
684d2fd4 305size_t append_ipl_vmparm(char *dest, size_t size)
a0443fbb 306{
684d2fd4
HB
307 size_t rc;
308
309 rc = 0;
a0443fbb 310 if (diag308_set_works && (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW))
684d2fd4 311 rc = reipl_get_ascii_vmparm(dest, size, &ipl_block);
a0443fbb
HB
312 else
313 dest[0] = 0;
684d2fd4 314 return rc;
a0443fbb
HB
315}
316
317static ssize_t ipl_vm_parm_show(struct kobject *kobj,
318 struct kobj_attribute *attr, char *page)
319{
320 char parm[DIAG308_VMPARM_SIZE + 1] = {};
321
684d2fd4 322 append_ipl_vmparm(parm, sizeof(parm));
a0443fbb
HB
323 return sprintf(page, "%s\n", parm);
324}
325
684d2fd4
HB
326static size_t scpdata_length(const char* buf, size_t count)
327{
328 while (count) {
329 if (buf[count - 1] != '\0' && buf[count - 1] != ' ')
330 break;
331 count--;
332 }
333 return count;
334}
335
c4736d96
MS
336static size_t reipl_append_ascii_scpdata(char *dest, size_t size,
337 const struct ipl_parameter_block *ipb)
684d2fd4
HB
338{
339 size_t count;
340 size_t i;
18d00acf 341 int has_lowercase;
684d2fd4
HB
342
343 count = min(size - 1, scpdata_length(ipb->ipl_info.fcp.scp_data,
344 ipb->ipl_info.fcp.scp_data_len));
345 if (!count)
346 goto out;
347
18d00acf
HB
348 has_lowercase = 0;
349 for (i = 0; i < count; i++) {
684d2fd4
HB
350 if (!isascii(ipb->ipl_info.fcp.scp_data[i])) {
351 count = 0;
352 goto out;
353 }
18d00acf
HB
354 if (!has_lowercase && islower(ipb->ipl_info.fcp.scp_data[i]))
355 has_lowercase = 1;
356 }
684d2fd4 357
18d00acf
HB
358 if (has_lowercase)
359 memcpy(dest, ipb->ipl_info.fcp.scp_data, count);
360 else
361 for (i = 0; i < count; i++)
362 dest[i] = tolower(ipb->ipl_info.fcp.scp_data[i]);
684d2fd4
HB
363out:
364 dest[count] = '\0';
365 return count;
366}
367
368size_t append_ipl_scpdata(char *dest, size_t len)
369{
370 size_t rc;
371
372 rc = 0;
373 if (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_FCP)
374 rc = reipl_append_ascii_scpdata(dest, len, &ipl_block);
375 else
376 dest[0] = 0;
377 return rc;
378}
379
380
a0443fbb
HB
381static struct kobj_attribute sys_ipl_vm_parm_attr =
382 __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL);
383
9b949165
GKH
384static ssize_t sys_ipl_device_show(struct kobject *kobj,
385 struct kobj_attribute *attr, char *page)
ff6b8ea6
MH
386{
387 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
388
411ed322 389 switch (ipl_info.type) {
ff6b8ea6
MH
390 case IPL_TYPE_CCW:
391 return sprintf(page, "0.0.%04x\n", ipl_devno);
392 case IPL_TYPE_FCP:
411ed322 393 case IPL_TYPE_FCP_DUMP:
ff6b8ea6
MH
394 return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno);
395 default:
396 return 0;
397 }
398}
399
9b949165 400static struct kobj_attribute sys_ipl_device_attr =
ff6b8ea6
MH
401 __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
402
2c3c8bea
CW
403static ssize_t ipl_parameter_read(struct file *filp, struct kobject *kobj,
404 struct bin_attribute *attr, char *buf,
405 loff_t off, size_t count)
ff6b8ea6 406{
0788fea4
AM
407 return memory_read_from_buffer(buf, count, &off, IPL_PARMBLOCK_START,
408 IPL_PARMBLOCK_SIZE);
ff6b8ea6 409}
22d557ab
SO
410static struct bin_attribute ipl_parameter_attr =
411 __BIN_ATTR(binary_parameter, S_IRUGO, ipl_parameter_read, NULL,
412 PAGE_SIZE);
ff6b8ea6 413
2c3c8bea
CW
414static ssize_t ipl_scp_data_read(struct file *filp, struct kobject *kobj,
415 struct bin_attribute *attr, char *buf,
416 loff_t off, size_t count)
ff6b8ea6
MH
417{
418 unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
419 void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
420
0788fea4 421 return memory_read_from_buffer(buf, count, &off, scp_data, size);
ff6b8ea6 422}
22d557ab
SO
423static struct bin_attribute ipl_scp_data_attr =
424 __BIN_ATTR(scp_data, S_IRUGO, ipl_scp_data_read, NULL, PAGE_SIZE);
ff6b8ea6 425
22d557ab
SO
426static struct bin_attribute *ipl_fcp_bin_attrs[] = {
427 &ipl_parameter_attr,
428 &ipl_scp_data_attr,
429 NULL,
ff6b8ea6
MH
430};
431
432/* FCP ipl device attributes */
433
434DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n", (unsigned long long)
435 IPL_PARMBLOCK_START->ipl_info.fcp.wwpn);
436DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n", (unsigned long long)
437 IPL_PARMBLOCK_START->ipl_info.fcp.lun);
438DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long)
439 IPL_PARMBLOCK_START->ipl_info.fcp.bootprog);
440DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
441 IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
442
9b949165
GKH
443static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
444 struct kobj_attribute *attr, char *page)
03a4d208
MH
445{
446 char loadparm[LOADPARM_LEN + 1] = {};
447
05dd2530 448 if (!sclp_ipl_info.is_valid)
03a4d208 449 return sprintf(page, "#unknown#\n");
05dd2530 450 memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
03a4d208 451 EBCASC(loadparm, LOADPARM_LEN);
1d802e24 452 strim(loadparm);
03a4d208
MH
453 return sprintf(page, "%s\n", loadparm);
454}
455
9b949165 456static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
03a4d208
MH
457 __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
458
69928601
MH
459static struct attribute *ipl_fcp_attrs[] = {
460 &sys_ipl_type_attr.attr,
461 &sys_ipl_device_attr.attr,
462 &sys_ipl_fcp_wwpn_attr.attr,
463 &sys_ipl_fcp_lun_attr.attr,
464 &sys_ipl_fcp_bootprog_attr.attr,
465 &sys_ipl_fcp_br_lba_attr.attr,
466 &sys_ipl_ccw_loadparm_attr.attr,
467 NULL,
468};
469
470static struct attribute_group ipl_fcp_attr_group = {
471 .attrs = ipl_fcp_attrs,
22d557ab 472 .bin_attrs = ipl_fcp_bin_attrs,
69928601
MH
473};
474
475/* CCW ipl device attributes */
476
a0443fbb
HB
477static struct attribute *ipl_ccw_attrs_vm[] = {
478 &sys_ipl_type_attr.attr,
479 &sys_ipl_device_attr.attr,
480 &sys_ipl_ccw_loadparm_attr.attr,
481 &sys_ipl_vm_parm_attr.attr,
482 NULL,
483};
484
485static struct attribute *ipl_ccw_attrs_lpar[] = {
ff6b8ea6
MH
486 &sys_ipl_type_attr.attr,
487 &sys_ipl_device_attr.attr,
03a4d208 488 &sys_ipl_ccw_loadparm_attr.attr,
ff6b8ea6
MH
489 NULL,
490};
491
a0443fbb
HB
492static struct attribute_group ipl_ccw_attr_group_vm = {
493 .attrs = ipl_ccw_attrs_vm,
494};
495
496static struct attribute_group ipl_ccw_attr_group_lpar = {
497 .attrs = ipl_ccw_attrs_lpar
ff6b8ea6
MH
498};
499
fe355b7f
HY
500/* NSS ipl device attributes */
501
502DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name);
503
504static struct attribute *ipl_nss_attrs[] = {
505 &sys_ipl_type_attr.attr,
506 &sys_ipl_nss_name_attr.attr,
a0443fbb
HB
507 &sys_ipl_ccw_loadparm_attr.attr,
508 &sys_ipl_vm_parm_attr.attr,
fe355b7f
HY
509 NULL,
510};
511
512static struct attribute_group ipl_nss_attr_group = {
513 .attrs = ipl_nss_attrs,
514};
515
ff6b8ea6
MH
516/* UNKNOWN ipl device attributes */
517
518static struct attribute *ipl_unknown_attrs[] = {
519 &sys_ipl_type_attr.attr,
520 NULL,
521};
522
523static struct attribute_group ipl_unknown_attr_group = {
524 .attrs = ipl_unknown_attrs,
525};
526
d91885be 527static struct kset *ipl_kset;
ff6b8ea6 528
2c2df118 529static void __ipl_run(void *unused)
99ca4e58
MH
530{
531 diag308(DIAG308_IPL, NULL);
532 if (MACHINE_IS_VM)
533 __cpcmd("IPL", NULL, 0, NULL);
534 else if (ipl_info.type == IPL_TYPE_CCW)
535 reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
536}
537
2c2df118
HC
538static void ipl_run(struct shutdown_trigger *trigger)
539{
8b646bd7 540 smp_call_ipl_cpu(__ipl_run, NULL);
2c2df118
HC
541}
542
2bc89b5e 543static int __init ipl_init(void)
99ca4e58
MH
544{
545 int rc;
546
547 ipl_kset = kset_create_and_add("ipl", NULL, firmware_kobj);
548 if (!ipl_kset) {
549 rc = -ENOMEM;
550 goto out;
551 }
552 switch (ipl_info.type) {
553 case IPL_TYPE_CCW:
a0443fbb
HB
554 if (MACHINE_IS_VM)
555 rc = sysfs_create_group(&ipl_kset->kobj,
556 &ipl_ccw_attr_group_vm);
557 else
558 rc = sysfs_create_group(&ipl_kset->kobj,
559 &ipl_ccw_attr_group_lpar);
99ca4e58
MH
560 break;
561 case IPL_TYPE_FCP:
562 case IPL_TYPE_FCP_DUMP:
22d557ab 563 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
99ca4e58
MH
564 break;
565 case IPL_TYPE_NSS:
566 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_nss_attr_group);
567 break;
568 default:
569 rc = sysfs_create_group(&ipl_kset->kobj,
570 &ipl_unknown_attr_group);
571 break;
572 }
573out:
574 if (rc)
575 panic("ipl_init failed: rc = %i\n", rc);
576
577 return 0;
578}
579
2bc89b5e
HC
580static struct shutdown_action __refdata ipl_action = {
581 .name = SHUTDOWN_ACTION_IPL_STR,
582 .fn = ipl_run,
583 .init = ipl_init,
584};
99ca4e58 585
ff6b8ea6 586/*
99ca4e58 587 * reipl shutdown action: Reboot Linux on shutdown.
ff6b8ea6
MH
588 */
589
a0443fbb
HB
590/* VM IPL PARM attributes */
591static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb,
592 char *page)
593{
594 char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
595
684d2fd4 596 reipl_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
a0443fbb
HB
597 return sprintf(page, "%s\n", vmparm);
598}
599
600static ssize_t reipl_generic_vmparm_store(struct ipl_parameter_block *ipb,
601 size_t vmparm_max,
602 const char *buf, size_t len)
603{
604 int i, ip_len;
605
606 /* ignore trailing newline */
607 ip_len = len;
608 if ((len > 0) && (buf[len - 1] == '\n'))
609 ip_len--;
610
611 if (ip_len > vmparm_max)
612 return -EINVAL;
613
614 /* parm is used to store kernel options, check for common chars */
615 for (i = 0; i < ip_len; i++)
616 if (!(isalnum(buf[i]) || isascii(buf[i]) || isprint(buf[i])))
617 return -EINVAL;
618
619 memset(ipb->ipl_info.ccw.vm_parm, 0, DIAG308_VMPARM_SIZE);
620 ipb->ipl_info.ccw.vm_parm_len = ip_len;
621 if (ip_len > 0) {
622 ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
623 memcpy(ipb->ipl_info.ccw.vm_parm, buf, ip_len);
624 ASCEBC(ipb->ipl_info.ccw.vm_parm, ip_len);
625 } else {
626 ipb->ipl_info.ccw.vm_flags &= ~DIAG308_VM_FLAGS_VP_VALID;
627 }
628
629 return len;
630}
631
632/* NSS wrapper */
633static ssize_t reipl_nss_vmparm_show(struct kobject *kobj,
634 struct kobj_attribute *attr, char *page)
635{
636 return reipl_generic_vmparm_show(reipl_block_nss, page);
637}
638
639static ssize_t reipl_nss_vmparm_store(struct kobject *kobj,
640 struct kobj_attribute *attr,
641 const char *buf, size_t len)
642{
643 return reipl_generic_vmparm_store(reipl_block_nss, 56, buf, len);
644}
645
646/* CCW wrapper */
647static ssize_t reipl_ccw_vmparm_show(struct kobject *kobj,
648 struct kobj_attribute *attr, char *page)
649{
650 return reipl_generic_vmparm_show(reipl_block_ccw, page);
651}
652
653static ssize_t reipl_ccw_vmparm_store(struct kobject *kobj,
654 struct kobj_attribute *attr,
655 const char *buf, size_t len)
656{
657 return reipl_generic_vmparm_store(reipl_block_ccw, 64, buf, len);
658}
659
660static struct kobj_attribute sys_reipl_nss_vmparm_attr =
661 __ATTR(parm, S_IRUGO | S_IWUSR, reipl_nss_vmparm_show,
662 reipl_nss_vmparm_store);
663static struct kobj_attribute sys_reipl_ccw_vmparm_attr =
664 __ATTR(parm, S_IRUGO | S_IWUSR, reipl_ccw_vmparm_show,
665 reipl_ccw_vmparm_store);
666
ff6b8ea6
MH
667/* FCP reipl device attributes */
668
2c3c8bea 669static ssize_t reipl_fcp_scpdata_read(struct file *filp, struct kobject *kobj,
684d2fd4
HB
670 struct bin_attribute *attr,
671 char *buf, loff_t off, size_t count)
672{
673 size_t size = reipl_block_fcp->ipl_info.fcp.scp_data_len;
674 void *scp_data = reipl_block_fcp->ipl_info.fcp.scp_data;
675
676 return memory_read_from_buffer(buf, count, &off, scp_data, size);
677}
678
2c3c8bea 679static ssize_t reipl_fcp_scpdata_write(struct file *filp, struct kobject *kobj,
684d2fd4
HB
680 struct bin_attribute *attr,
681 char *buf, loff_t off, size_t count)
682{
683 size_t padding;
684 size_t scpdata_len;
685
686 if (off < 0)
687 return -EINVAL;
688
689 if (off >= DIAG308_SCPDATA_SIZE)
690 return -ENOSPC;
691
692 if (count > DIAG308_SCPDATA_SIZE - off)
693 count = DIAG308_SCPDATA_SIZE - off;
694
695 memcpy(reipl_block_fcp->ipl_info.fcp.scp_data, buf + off, count);
696 scpdata_len = off + count;
697
698 if (scpdata_len % 8) {
699 padding = 8 - (scpdata_len % 8);
700 memset(reipl_block_fcp->ipl_info.fcp.scp_data + scpdata_len,
701 0, padding);
702 scpdata_len += padding;
703 }
704
705 reipl_block_fcp->ipl_info.fcp.scp_data_len = scpdata_len;
706 reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN + scpdata_len;
707 reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN + scpdata_len;
708
709 return count;
710}
22d557ab
SO
711static struct bin_attribute sys_reipl_fcp_scp_data_attr =
712 __BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_fcp_scpdata_read,
713 reipl_fcp_scpdata_write, PAGE_SIZE);
684d2fd4 714
22d557ab
SO
715static struct bin_attribute *reipl_fcp_bin_attrs[] = {
716 &sys_reipl_fcp_scp_data_attr,
717 NULL,
684d2fd4
HB
718};
719
eda4ddf7 720DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%llx\n",
ff6b8ea6 721 reipl_block_fcp->ipl_info.fcp.wwpn);
eda4ddf7 722DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%llx\n",
ff6b8ea6
MH
723 reipl_block_fcp->ipl_info.fcp.lun);
724DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
725 reipl_block_fcp->ipl_info.fcp.bootprog);
726DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
727 reipl_block_fcp->ipl_info.fcp.br_lba);
728DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
729 reipl_block_fcp->ipl_info.fcp.devno);
730
a0443fbb
HB
731static void reipl_get_ascii_loadparm(char *loadparm,
732 struct ipl_parameter_block *ibp)
03a4d208 733{
69928601 734 memcpy(loadparm, ibp->hdr.loadparm, LOADPARM_LEN);
03a4d208
MH
735 EBCASC(loadparm, LOADPARM_LEN);
736 loadparm[LOADPARM_LEN] = 0;
1d802e24 737 strim(loadparm);
03a4d208
MH
738}
739
a0443fbb
HB
740static ssize_t reipl_generic_loadparm_show(struct ipl_parameter_block *ipb,
741 char *page)
03a4d208
MH
742{
743 char buf[LOADPARM_LEN + 1];
744
a0443fbb 745 reipl_get_ascii_loadparm(buf, ipb);
03a4d208
MH
746 return sprintf(page, "%s\n", buf);
747}
748
a0443fbb
HB
749static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
750 const char *buf, size_t len)
03a4d208
MH
751{
752 int i, lp_len;
753
754 /* ignore trailing newline */
755 lp_len = len;
756 if ((len > 0) && (buf[len - 1] == '\n'))
757 lp_len--;
758 /* loadparm can have max 8 characters and must not start with a blank */
759 if ((lp_len > LOADPARM_LEN) || ((lp_len > 0) && (buf[0] == ' ')))
760 return -EINVAL;
761 /* loadparm can only contain "a-z,A-Z,0-9,SP,." */
762 for (i = 0; i < lp_len; i++) {
763 if (isalpha(buf[i]) || isdigit(buf[i]) || (buf[i] == ' ') ||
764 (buf[i] == '.'))
765 continue;
766 return -EINVAL;
767 }
768 /* initialize loadparm with blanks */
69928601 769 memset(ipb->hdr.loadparm, ' ', LOADPARM_LEN);
03a4d208 770 /* copy and convert to ebcdic */
69928601
MH
771 memcpy(ipb->hdr.loadparm, buf, lp_len);
772 ASCEBC(ipb->hdr.loadparm, LOADPARM_LEN);
03a4d208
MH
773 return len;
774}
775
69928601
MH
776/* FCP wrapper */
777static ssize_t reipl_fcp_loadparm_show(struct kobject *kobj,
778 struct kobj_attribute *attr, char *page)
779{
780 return reipl_generic_loadparm_show(reipl_block_fcp, page);
781}
782
783static ssize_t reipl_fcp_loadparm_store(struct kobject *kobj,
784 struct kobj_attribute *attr,
785 const char *buf, size_t len)
786{
787 return reipl_generic_loadparm_store(reipl_block_fcp, buf, len);
788}
789
790static struct kobj_attribute sys_reipl_fcp_loadparm_attr =
791 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_fcp_loadparm_show,
792 reipl_fcp_loadparm_store);
793
794static struct attribute *reipl_fcp_attrs[] = {
795 &sys_reipl_fcp_device_attr.attr,
796 &sys_reipl_fcp_wwpn_attr.attr,
797 &sys_reipl_fcp_lun_attr.attr,
798 &sys_reipl_fcp_bootprog_attr.attr,
799 &sys_reipl_fcp_br_lba_attr.attr,
800 &sys_reipl_fcp_loadparm_attr.attr,
801 NULL,
802};
803
804static struct attribute_group reipl_fcp_attr_group = {
805 .attrs = reipl_fcp_attrs,
22d557ab 806 .bin_attrs = reipl_fcp_bin_attrs,
69928601
MH
807};
808
809/* CCW reipl device attributes */
810
811DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
812 reipl_block_ccw->ipl_info.ccw.devno);
813
a0443fbb
HB
814/* NSS wrapper */
815static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
816 struct kobj_attribute *attr, char *page)
817{
818 return reipl_generic_loadparm_show(reipl_block_nss, page);
819}
820
821static ssize_t reipl_nss_loadparm_store(struct kobject *kobj,
822 struct kobj_attribute *attr,
823 const char *buf, size_t len)
824{
825 return reipl_generic_loadparm_store(reipl_block_nss, buf, len);
826}
827
828/* CCW wrapper */
829static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj,
830 struct kobj_attribute *attr, char *page)
831{
832 return reipl_generic_loadparm_show(reipl_block_ccw, page);
833}
834
835static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
836 struct kobj_attribute *attr,
837 const char *buf, size_t len)
838{
839 return reipl_generic_loadparm_store(reipl_block_ccw, buf, len);
840}
841
9b949165 842static struct kobj_attribute sys_reipl_ccw_loadparm_attr =
a0443fbb
HB
843 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_ccw_loadparm_show,
844 reipl_ccw_loadparm_store);
845
846static struct attribute *reipl_ccw_attrs_vm[] = {
847 &sys_reipl_ccw_device_attr.attr,
848 &sys_reipl_ccw_loadparm_attr.attr,
849 &sys_reipl_ccw_vmparm_attr.attr,
850 NULL,
851};
03a4d208 852
a0443fbb 853static struct attribute *reipl_ccw_attrs_lpar[] = {
ff6b8ea6 854 &sys_reipl_ccw_device_attr.attr,
03a4d208 855 &sys_reipl_ccw_loadparm_attr.attr,
ff6b8ea6
MH
856 NULL,
857};
858
a0443fbb 859static struct attribute_group reipl_ccw_attr_group_vm = {
ff6b8ea6 860 .name = IPL_CCW_STR,
a0443fbb
HB
861 .attrs = reipl_ccw_attrs_vm,
862};
863
864static struct attribute_group reipl_ccw_attr_group_lpar = {
865 .name = IPL_CCW_STR,
866 .attrs = reipl_ccw_attrs_lpar,
ff6b8ea6
MH
867};
868
fe355b7f
HY
869
870/* NSS reipl device attributes */
a0443fbb
HB
871static void reipl_get_ascii_nss_name(char *dst,
872 struct ipl_parameter_block *ipb)
873{
874 memcpy(dst, ipb->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
875 EBCASC(dst, NSS_NAME_SIZE);
876 dst[NSS_NAME_SIZE] = 0;
877}
878
879static ssize_t reipl_nss_name_show(struct kobject *kobj,
880 struct kobj_attribute *attr, char *page)
881{
882 char nss_name[NSS_NAME_SIZE + 1] = {};
883
884 reipl_get_ascii_nss_name(nss_name, reipl_block_nss);
885 return sprintf(page, "%s\n", nss_name);
886}
887
888static ssize_t reipl_nss_name_store(struct kobject *kobj,
889 struct kobj_attribute *attr,
890 const char *buf, size_t len)
891{
892 int nss_len;
893
894 /* ignore trailing newline */
895 nss_len = len;
896 if ((len > 0) && (buf[len - 1] == '\n'))
897 nss_len--;
fe355b7f 898
a0443fbb
HB
899 if (nss_len > NSS_NAME_SIZE)
900 return -EINVAL;
901
902 memset(reipl_block_nss->ipl_info.ccw.nss_name, 0x40, NSS_NAME_SIZE);
903 if (nss_len > 0) {
904 reipl_block_nss->ipl_info.ccw.vm_flags |=
905 DIAG308_VM_FLAGS_NSS_VALID;
906 memcpy(reipl_block_nss->ipl_info.ccw.nss_name, buf, nss_len);
907 ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
908 EBC_TOUPPER(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
909 } else {
910 reipl_block_nss->ipl_info.ccw.vm_flags &=
911 ~DIAG308_VM_FLAGS_NSS_VALID;
912 }
913
914 return len;
915}
916
917static struct kobj_attribute sys_reipl_nss_name_attr =
918 __ATTR(name, S_IRUGO | S_IWUSR, reipl_nss_name_show,
919 reipl_nss_name_store);
920
921static struct kobj_attribute sys_reipl_nss_loadparm_attr =
922 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nss_loadparm_show,
923 reipl_nss_loadparm_store);
fe355b7f
HY
924
925static struct attribute *reipl_nss_attrs[] = {
926 &sys_reipl_nss_name_attr.attr,
a0443fbb
HB
927 &sys_reipl_nss_loadparm_attr.attr,
928 &sys_reipl_nss_vmparm_attr.attr,
fe355b7f
HY
929 NULL,
930};
931
932static struct attribute_group reipl_nss_attr_group = {
933 .name = IPL_NSS_STR,
934 .attrs = reipl_nss_attrs,
935};
936
4857d4bb
MH
937static void set_reipl_block_actual(struct ipl_parameter_block *reipl_block)
938{
939 reipl_block_actual = reipl_block;
940 os_info_entry_add(OS_INFO_REIPL_BLOCK, reipl_block_actual,
941 reipl_block->hdr.len);
942}
943
ff6b8ea6
MH
944/* reipl type */
945
946static int reipl_set_type(enum ipl_type type)
947{
948 if (!(reipl_capabilities & type))
949 return -EINVAL;
950
951 switch(type) {
952 case IPL_TYPE_CCW:
48657d22
MH
953 if (diag308_set_works)
954 reipl_method = REIPL_METHOD_CCW_DIAG;
955 else if (MACHINE_IS_VM)
411ed322 956 reipl_method = REIPL_METHOD_CCW_VM;
ff6b8ea6 957 else
411ed322 958 reipl_method = REIPL_METHOD_CCW_CIO;
4857d4bb 959 set_reipl_block_actual(reipl_block_ccw);
ff6b8ea6
MH
960 break;
961 case IPL_TYPE_FCP:
962 if (diag308_set_works)
411ed322 963 reipl_method = REIPL_METHOD_FCP_RW_DIAG;
ff6b8ea6 964 else if (MACHINE_IS_VM)
411ed322 965 reipl_method = REIPL_METHOD_FCP_RO_VM;
ff6b8ea6 966 else
411ed322 967 reipl_method = REIPL_METHOD_FCP_RO_DIAG;
4857d4bb 968 set_reipl_block_actual(reipl_block_fcp);
411ed322
MH
969 break;
970 case IPL_TYPE_FCP_DUMP:
971 reipl_method = REIPL_METHOD_FCP_DUMP;
ff6b8ea6 972 break;
fe355b7f 973 case IPL_TYPE_NSS:
a0443fbb
HB
974 if (diag308_set_works)
975 reipl_method = REIPL_METHOD_NSS_DIAG;
976 else
977 reipl_method = REIPL_METHOD_NSS;
4857d4bb 978 set_reipl_block_actual(reipl_block_nss);
411ed322
MH
979 break;
980 case IPL_TYPE_UNKNOWN:
981 reipl_method = REIPL_METHOD_DEFAULT;
fe355b7f 982 break;
ff6b8ea6 983 default:
411ed322 984 BUG();
ff6b8ea6
MH
985 }
986 reipl_type = type;
987 return 0;
988}
989
9b949165
GKH
990static ssize_t reipl_type_show(struct kobject *kobj,
991 struct kobj_attribute *attr, char *page)
ff6b8ea6
MH
992{
993 return sprintf(page, "%s\n", ipl_type_str(reipl_type));
994}
995
9b949165
GKH
996static ssize_t reipl_type_store(struct kobject *kobj,
997 struct kobj_attribute *attr,
998 const char *buf, size_t len)
ff6b8ea6
MH
999{
1000 int rc = -EINVAL;
1001
1002 if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
1003 rc = reipl_set_type(IPL_TYPE_CCW);
1004 else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
1005 rc = reipl_set_type(IPL_TYPE_FCP);
fe355b7f
HY
1006 else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
1007 rc = reipl_set_type(IPL_TYPE_NSS);
ff6b8ea6
MH
1008 return (rc != 0) ? rc : len;
1009}
1010
9b949165 1011static struct kobj_attribute reipl_type_attr =
99ca4e58 1012 __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
ff6b8ea6 1013
d91885be 1014static struct kset *reipl_kset;
684d2fd4 1015static struct kset *reipl_fcp_kset;
ff6b8ea6 1016
a0443fbb
HB
1017static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb,
1018 const enum ipl_method m)
1019{
1020 char loadparm[LOADPARM_LEN + 1] = {};
1021 char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
1022 char nss_name[NSS_NAME_SIZE + 1] = {};
1023 size_t pos = 0;
1024
1025 reipl_get_ascii_loadparm(loadparm, ipb);
1026 reipl_get_ascii_nss_name(nss_name, ipb);
684d2fd4 1027 reipl_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
a0443fbb
HB
1028
1029 switch (m) {
1030 case REIPL_METHOD_CCW_VM:
1031 pos = sprintf(dst, "IPL %X CLEAR", ipb->ipl_info.ccw.devno);
1032 break;
1033 case REIPL_METHOD_NSS:
1034 pos = sprintf(dst, "IPL %s", nss_name);
1035 break;
1036 default:
1037 break;
1038 }
1039 if (strlen(loadparm) > 0)
1040 pos += sprintf(dst + pos, " LOADPARM '%s'", loadparm);
1041 if (strlen(vmparm) > 0)
1042 sprintf(dst + pos, " PARM %s", vmparm);
1043}
1044
2c2df118 1045static void __reipl_run(void *unused)
ff6b8ea6
MH
1046{
1047 struct ccw_dev_id devid;
a0443fbb 1048 static char buf[128];
ff6b8ea6 1049
ff6b8ea6 1050 switch (reipl_method) {
411ed322 1051 case REIPL_METHOD_CCW_CIO:
ff6b8ea6
MH
1052 devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
1053 devid.ssid = 0;
1054 reipl_ccw_dev(&devid);
1055 break;
411ed322 1056 case REIPL_METHOD_CCW_VM:
a0443fbb 1057 get_ipl_string(buf, reipl_block_ccw, REIPL_METHOD_CCW_VM);
740b5706 1058 __cpcmd(buf, NULL, 0, NULL);
ff6b8ea6 1059 break;
411ed322 1060 case REIPL_METHOD_CCW_DIAG:
ff6b8ea6
MH
1061 diag308(DIAG308_SET, reipl_block_ccw);
1062 diag308(DIAG308_IPL, NULL);
1063 break;
411ed322 1064 case REIPL_METHOD_FCP_RW_DIAG:
ff6b8ea6
MH
1065 diag308(DIAG308_SET, reipl_block_fcp);
1066 diag308(DIAG308_IPL, NULL);
1067 break;
411ed322 1068 case REIPL_METHOD_FCP_RO_DIAG:
ff6b8ea6
MH
1069 diag308(DIAG308_IPL, NULL);
1070 break;
411ed322 1071 case REIPL_METHOD_FCP_RO_VM:
740b5706 1072 __cpcmd("IPL", NULL, 0, NULL);
ff6b8ea6 1073 break;
a0443fbb
HB
1074 case REIPL_METHOD_NSS_DIAG:
1075 diag308(DIAG308_SET, reipl_block_nss);
1076 diag308(DIAG308_IPL, NULL);
1077 break;
411ed322 1078 case REIPL_METHOD_NSS:
a0443fbb 1079 get_ipl_string(buf, reipl_block_nss, REIPL_METHOD_NSS);
fe355b7f
HY
1080 __cpcmd(buf, NULL, 0, NULL);
1081 break;
411ed322 1082 case REIPL_METHOD_DEFAULT:
ff6b8ea6 1083 if (MACHINE_IS_VM)
740b5706 1084 __cpcmd("IPL", NULL, 0, NULL);
ff6b8ea6
MH
1085 diag308(DIAG308_IPL, NULL);
1086 break;
411ed322 1087 case REIPL_METHOD_FCP_DUMP:
411ed322 1088 break;
ff6b8ea6 1089 }
208e5591 1090 disabled_wait((unsigned long) __builtin_return_address(0));
ff6b8ea6
MH
1091}
1092
2c2df118
HC
1093static void reipl_run(struct shutdown_trigger *trigger)
1094{
8b646bd7 1095 smp_call_ipl_cpu(__reipl_run, NULL);
2c2df118
HC
1096}
1097
a0443fbb 1098static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
ff6b8ea6 1099{
a0443fbb
HB
1100 ipb->hdr.len = IPL_PARM_BLK_CCW_LEN;
1101 ipb->hdr.version = IPL_PARM_BLOCK_VERSION;
1102 ipb->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
1103 ipb->hdr.pbt = DIAG308_IPL_TYPE_CCW;
1104}
ff6b8ea6 1105
a0443fbb
HB
1106static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
1107{
1108 /* LOADPARM */
1109 /* check if read scp info worked and set loadparm */
1110 if (sclp_ipl_info.is_valid)
69928601 1111 memcpy(ipb->hdr.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
a0443fbb
HB
1112 else
1113 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
69928601 1114 memset(ipb->hdr.loadparm, 0x40, LOADPARM_LEN);
a0443fbb
HB
1115 ipb->hdr.flags = DIAG308_FLAGS_LP_VALID;
1116
1117 /* VM PARM */
1118 if (MACHINE_IS_VM && diag308_set_works &&
1119 (ipl_block.ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID)) {
1120
1121 ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
1122 ipb->ipl_info.ccw.vm_parm_len =
1123 ipl_block.ipl_info.ccw.vm_parm_len;
1124 memcpy(ipb->ipl_info.ccw.vm_parm,
1125 ipl_block.ipl_info.ccw.vm_parm, DIAG308_VMPARM_SIZE);
1126 }
ff6b8ea6
MH
1127}
1128
99ca4e58 1129static int __init reipl_nss_init(void)
ff6b8ea6
MH
1130{
1131 int rc;
1132
99ca4e58
MH
1133 if (!MACHINE_IS_VM)
1134 return 0;
a0443fbb
HB
1135
1136 reipl_block_nss = (void *) get_zeroed_page(GFP_KERNEL);
1137 if (!reipl_block_nss)
1138 return -ENOMEM;
1139
1140 if (!diag308_set_works)
1141 sys_reipl_nss_vmparm_attr.attr.mode = S_IRUGO;
1142
99ca4e58 1143 rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group);
fe355b7f
HY
1144 if (rc)
1145 return rc;
a0443fbb
HB
1146
1147 reipl_block_ccw_init(reipl_block_nss);
1148 if (ipl_info.type == IPL_TYPE_NSS) {
1149 memset(reipl_block_nss->ipl_info.ccw.nss_name,
1150 ' ', NSS_NAME_SIZE);
1151 memcpy(reipl_block_nss->ipl_info.ccw.nss_name,
1152 kernel_nss_name, strlen(kernel_nss_name));
1153 ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
1154 reipl_block_nss->ipl_info.ccw.vm_flags |=
1155 DIAG308_VM_FLAGS_NSS_VALID;
1156
1157 reipl_block_ccw_fill_parms(reipl_block_nss);
1158 }
1159
fe355b7f
HY
1160 reipl_capabilities |= IPL_TYPE_NSS;
1161 return 0;
1162}
1163
ff6b8ea6
MH
1164static int __init reipl_ccw_init(void)
1165{
1166 int rc;
1167
1168 reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
1169 if (!reipl_block_ccw)
1170 return -ENOMEM;
a0443fbb
HB
1171
1172 if (MACHINE_IS_VM) {
1173 if (!diag308_set_works)
1174 sys_reipl_ccw_vmparm_attr.attr.mode = S_IRUGO;
1175 rc = sysfs_create_group(&reipl_kset->kobj,
1176 &reipl_ccw_attr_group_vm);
1177 } else {
1178 if(!diag308_set_works)
1179 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
1180 rc = sysfs_create_group(&reipl_kset->kobj,
1181 &reipl_ccw_attr_group_lpar);
ff6b8ea6 1182 }
a0443fbb
HB
1183 if (rc)
1184 return rc;
1185
1186 reipl_block_ccw_init(reipl_block_ccw);
1187 if (ipl_info.type == IPL_TYPE_CCW) {
ff6b8ea6 1188 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
a0443fbb
HB
1189 reipl_block_ccw_fill_parms(reipl_block_ccw);
1190 }
1191
ff6b8ea6
MH
1192 reipl_capabilities |= IPL_TYPE_CCW;
1193 return 0;
1194}
1195
1196static int __init reipl_fcp_init(void)
1197{
1198 int rc;
1199
008d2d11 1200 if (!diag308_set_works) {
684d2fd4 1201 if (ipl_info.type == IPL_TYPE_FCP) {
008d2d11 1202 make_attrs_ro(reipl_fcp_attrs);
684d2fd4
HB
1203 sys_reipl_fcp_scp_data_attr.attr.mode = S_IRUGO;
1204 } else
008d2d11
MH
1205 return 0;
1206 }
ff6b8ea6
MH
1207
1208 reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
1209 if (!reipl_block_fcp)
1210 return -ENOMEM;
684d2fd4
HB
1211
1212 /* sysfs: create fcp kset for mixing attr group and bin attrs */
1213 reipl_fcp_kset = kset_create_and_add(IPL_FCP_STR, NULL,
1214 &reipl_kset->kobj);
798620fb 1215 if (!reipl_fcp_kset) {
684d2fd4
HB
1216 free_page((unsigned long) reipl_block_fcp);
1217 return -ENOMEM;
1218 }
1219
1220 rc = sysfs_create_group(&reipl_fcp_kset->kobj, &reipl_fcp_attr_group);
ff6b8ea6 1221 if (rc) {
684d2fd4
HB
1222 kset_unregister(reipl_fcp_kset);
1223 free_page((unsigned long) reipl_block_fcp);
ff6b8ea6
MH
1224 return rc;
1225 }
684d2fd4 1226
69928601 1227 if (ipl_info.type == IPL_TYPE_FCP) {
ff6b8ea6 1228 memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
69928601
MH
1229 /*
1230 * Fix loadparm: There are systems where the (SCSI) LOADPARM
1231 * is invalid in the SCSI IPL parameter block, so take it
1232 * always from sclp_ipl_info.
1233 */
1234 memcpy(reipl_block_fcp->hdr.loadparm, sclp_ipl_info.loadparm,
1235 LOADPARM_LEN);
1236 } else {
ff6b8ea6
MH
1237 reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
1238 reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
fbb04f38 1239 reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
ff6b8ea6
MH
1240 reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
1241 reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL;
1242 }
1243 reipl_capabilities |= IPL_TYPE_FCP;
1244 return 0;
1245}
1246
4857d4bb
MH
1247static int __init reipl_type_init(void)
1248{
1249 enum ipl_type reipl_type = ipl_info.type;
1250 struct ipl_parameter_block *reipl_block;
1251 unsigned long size;
1252
1253 reipl_block = os_info_old_entry(OS_INFO_REIPL_BLOCK, &size);
1254 if (!reipl_block)
1255 goto out;
1256 /*
1257 * If we have an OS info reipl block, this will be used
1258 */
1259 if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_FCP) {
1260 memcpy(reipl_block_fcp, reipl_block, size);
1261 reipl_type = IPL_TYPE_FCP;
1262 } else if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_CCW) {
1263 memcpy(reipl_block_ccw, reipl_block, size);
1264 reipl_type = IPL_TYPE_CCW;
1265 }
1266out:
1267 return reipl_set_type(reipl_type);
1268}
1269
2bc89b5e 1270static int __init reipl_init(void)
ff6b8ea6
MH
1271{
1272 int rc;
1273
f62ed9e3 1274 reipl_kset = kset_create_and_add("reipl", NULL, firmware_kobj);
d91885be
GKH
1275 if (!reipl_kset)
1276 return -ENOMEM;
1277 rc = sysfs_create_file(&reipl_kset->kobj, &reipl_type_attr.attr);
ff6b8ea6 1278 if (rc) {
d91885be 1279 kset_unregister(reipl_kset);
ff6b8ea6
MH
1280 return rc;
1281 }
1282 rc = reipl_ccw_init();
1283 if (rc)
1284 return rc;
1285 rc = reipl_fcp_init();
fe355b7f
HY
1286 if (rc)
1287 return rc;
1288 rc = reipl_nss_init();
ff6b8ea6
MH
1289 if (rc)
1290 return rc;
4857d4bb 1291 return reipl_type_init();
ff6b8ea6
MH
1292}
1293
2bc89b5e
HC
1294static struct shutdown_action __refdata reipl_action = {
1295 .name = SHUTDOWN_ACTION_REIPL_STR,
1296 .fn = reipl_run,
1297 .init = reipl_init,
1298};
99ca4e58
MH
1299
1300/*
1301 * dump shutdown action: Dump Linux on shutdown.
1302 */
1303
1304/* FCP dump device attributes */
1305
eda4ddf7 1306DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%llx\n",
99ca4e58 1307 dump_block_fcp->ipl_info.fcp.wwpn);
eda4ddf7 1308DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%llx\n",
99ca4e58
MH
1309 dump_block_fcp->ipl_info.fcp.lun);
1310DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
1311 dump_block_fcp->ipl_info.fcp.bootprog);
1312DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
1313 dump_block_fcp->ipl_info.fcp.br_lba);
1314DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
1315 dump_block_fcp->ipl_info.fcp.devno);
1316
1317static struct attribute *dump_fcp_attrs[] = {
1318 &sys_dump_fcp_device_attr.attr,
1319 &sys_dump_fcp_wwpn_attr.attr,
1320 &sys_dump_fcp_lun_attr.attr,
1321 &sys_dump_fcp_bootprog_attr.attr,
1322 &sys_dump_fcp_br_lba_attr.attr,
1323 NULL,
1324};
1325
1326static struct attribute_group dump_fcp_attr_group = {
1327 .name = IPL_FCP_STR,
1328 .attrs = dump_fcp_attrs,
1329};
1330
1331/* CCW dump device attributes */
1332
1333DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
1334 dump_block_ccw->ipl_info.ccw.devno);
1335
1336static struct attribute *dump_ccw_attrs[] = {
1337 &sys_dump_ccw_device_attr.attr,
1338 NULL,
1339};
1340
1341static struct attribute_group dump_ccw_attr_group = {
1342 .name = IPL_CCW_STR,
1343 .attrs = dump_ccw_attrs,
1344};
1345
1346/* dump type */
1347
1348static int dump_set_type(enum dump_type type)
1349{
1350 if (!(dump_capabilities & type))
1351 return -EINVAL;
1352 switch (type) {
1353 case DUMP_TYPE_CCW:
48657d22
MH
1354 if (diag308_set_works)
1355 dump_method = DUMP_METHOD_CCW_DIAG;
1356 else if (MACHINE_IS_VM)
99ca4e58
MH
1357 dump_method = DUMP_METHOD_CCW_VM;
1358 else
1359 dump_method = DUMP_METHOD_CCW_CIO;
1360 break;
1361 case DUMP_TYPE_FCP:
1362 dump_method = DUMP_METHOD_FCP_DIAG;
1363 break;
1364 default:
1365 dump_method = DUMP_METHOD_NONE;
1366 }
1367 dump_type = type;
1368 return 0;
1369}
1370
1371static ssize_t dump_type_show(struct kobject *kobj,
1372 struct kobj_attribute *attr, char *page)
1373{
1374 return sprintf(page, "%s\n", dump_type_str(dump_type));
1375}
1376
1377static ssize_t dump_type_store(struct kobject *kobj,
1378 struct kobj_attribute *attr,
1379 const char *buf, size_t len)
1380{
1381 int rc = -EINVAL;
1382
1383 if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
1384 rc = dump_set_type(DUMP_TYPE_NONE);
1385 else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
1386 rc = dump_set_type(DUMP_TYPE_CCW);
1387 else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
1388 rc = dump_set_type(DUMP_TYPE_FCP);
1389 return (rc != 0) ? rc : len;
1390}
1391
1392static struct kobj_attribute dump_type_attr =
1393 __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
1394
1395static struct kset *dump_kset;
1396
0894b3ae
MH
1397static void diag308_dump(void *dump_block)
1398{
1399 diag308(DIAG308_SET, dump_block);
1400 while (1) {
1401 if (diag308(DIAG308_DUMP, NULL) != 0x302)
1402 break;
1403 udelay_simple(USEC_PER_SEC);
1404 }
1405}
1406
2c2df118 1407static void __dump_run(void *unused)
99ca4e58
MH
1408{
1409 struct ccw_dev_id devid;
1410 static char buf[100];
1411
1412 switch (dump_method) {
1413 case DUMP_METHOD_CCW_CIO:
99ca4e58
MH
1414 devid.devno = dump_block_ccw->ipl_info.ccw.devno;
1415 devid.ssid = 0;
1416 reipl_ccw_dev(&devid);
1417 break;
1418 case DUMP_METHOD_CCW_VM:
99ca4e58
MH
1419 sprintf(buf, "STORE STATUS");
1420 __cpcmd(buf, NULL, 0, NULL);
1421 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
1422 __cpcmd(buf, NULL, 0, NULL);
1423 break;
1424 case DUMP_METHOD_CCW_DIAG:
0894b3ae 1425 diag308_dump(dump_block_ccw);
99ca4e58
MH
1426 break;
1427 case DUMP_METHOD_FCP_DIAG:
0894b3ae 1428 diag308_dump(dump_block_fcp);
99ca4e58 1429 break;
2c2df118
HC
1430 default:
1431 break;
99ca4e58 1432 }
2c2df118
HC
1433}
1434
1435static void dump_run(struct shutdown_trigger *trigger)
1436{
1437 if (dump_method == DUMP_METHOD_NONE)
1438 return;
1439 smp_send_stop();
8b646bd7 1440 smp_call_ipl_cpu(__dump_run, NULL);
99ca4e58
MH
1441}
1442
ff6b8ea6
MH
1443static int __init dump_ccw_init(void)
1444{
1445 int rc;
1446
1447 dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
1448 if (!dump_block_ccw)
1449 return -ENOMEM;
d91885be 1450 rc = sysfs_create_group(&dump_kset->kobj, &dump_ccw_attr_group);
ff6b8ea6
MH
1451 if (rc) {
1452 free_page((unsigned long)dump_block_ccw);
1453 return rc;
1454 }
1455 dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
1456 dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
fbb04f38 1457 dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
ff6b8ea6 1458 dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
411ed322 1459 dump_capabilities |= DUMP_TYPE_CCW;
ff6b8ea6
MH
1460 return 0;
1461}
1462
ff6b8ea6
MH
1463static int __init dump_fcp_init(void)
1464{
1465 int rc;
1466
05dd2530 1467 if (!sclp_ipl_info.has_dump)
ff6b8ea6
MH
1468 return 0; /* LDIPL DUMP is not installed */
1469 if (!diag308_set_works)
1470 return 0;
1471 dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
1472 if (!dump_block_fcp)
1473 return -ENOMEM;
d91885be 1474 rc = sysfs_create_group(&dump_kset->kobj, &dump_fcp_attr_group);
ff6b8ea6
MH
1475 if (rc) {
1476 free_page((unsigned long)dump_block_fcp);
1477 return rc;
1478 }
1479 dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
1480 dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
fbb04f38 1481 dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
ff6b8ea6
MH
1482 dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
1483 dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
411ed322 1484 dump_capabilities |= DUMP_TYPE_FCP;
ff6b8ea6
MH
1485 return 0;
1486}
1487
2bc89b5e 1488static int __init dump_init(void)
ff6b8ea6
MH
1489{
1490 int rc;
1491
f62ed9e3 1492 dump_kset = kset_create_and_add("dump", NULL, firmware_kobj);
d91885be
GKH
1493 if (!dump_kset)
1494 return -ENOMEM;
99ca4e58 1495 rc = sysfs_create_file(&dump_kset->kobj, &dump_type_attr.attr);
ff6b8ea6 1496 if (rc) {
d91885be 1497 kset_unregister(dump_kset);
ff6b8ea6
MH
1498 return rc;
1499 }
1500 rc = dump_ccw_init();
1501 if (rc)
1502 return rc;
1503 rc = dump_fcp_init();
1504 if (rc)
1505 return rc;
411ed322 1506 dump_set_type(DUMP_TYPE_NONE);
ff6b8ea6
MH
1507 return 0;
1508}
1509
2bc89b5e
HC
1510static struct shutdown_action __refdata dump_action = {
1511 .name = SHUTDOWN_ACTION_DUMP_STR,
1512 .fn = dump_run,
1513 .init = dump_init,
1514};
99ca4e58 1515
099b7651
FM
1516static void dump_reipl_run(struct shutdown_trigger *trigger)
1517{
a7df7a94 1518 unsigned long ipib = (unsigned long) reipl_block_actual;
fbe76568
HC
1519 unsigned int csum;
1520
1521 csum = csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0);
1522 mem_assign_absolute(S390_lowcore.ipib, ipib);
1523 mem_assign_absolute(S390_lowcore.ipib_checksum, csum);
099b7651
FM
1524 dump_run(trigger);
1525}
1526
1527static int __init dump_reipl_init(void)
1528{
1529 if (!diag308_set_works)
1530 return -EOPNOTSUPP;
1531 else
1532 return 0;
1533}
1534
1535static struct shutdown_action __refdata dump_reipl_action = {
1536 .name = SHUTDOWN_ACTION_DUMP_REIPL_STR,
1537 .fn = dump_reipl_run,
1538 .init = dump_reipl_init,
1539};
1540
99ca4e58
MH
1541/*
1542 * vmcmd shutdown action: Trigger vm command on shutdown.
1543 */
1544
1545static char vmcmd_on_reboot[128];
1546static char vmcmd_on_panic[128];
1547static char vmcmd_on_halt[128];
1548static char vmcmd_on_poff[128];
7dd6b334 1549static char vmcmd_on_restart[128];
99ca4e58
MH
1550
1551DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot);
1552DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic);
1553DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt);
1554DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff);
7dd6b334 1555DEFINE_IPL_ATTR_STR_RW(vmcmd, on_restart, "%s\n", "%s\n", vmcmd_on_restart);
99ca4e58
MH
1556
1557static struct attribute *vmcmd_attrs[] = {
1558 &sys_vmcmd_on_reboot_attr.attr,
1559 &sys_vmcmd_on_panic_attr.attr,
1560 &sys_vmcmd_on_halt_attr.attr,
1561 &sys_vmcmd_on_poff_attr.attr,
7dd6b334 1562 &sys_vmcmd_on_restart_attr.attr,
99ca4e58
MH
1563 NULL,
1564};
1565
1566static struct attribute_group vmcmd_attr_group = {
1567 .attrs = vmcmd_attrs,
1568};
1569
1570static struct kset *vmcmd_kset;
1571
1572static void vmcmd_run(struct shutdown_trigger *trigger)
ff6b8ea6 1573{
8143adaf 1574 char *cmd;
99ca4e58
MH
1575
1576 if (strcmp(trigger->name, ON_REIPL_STR) == 0)
1577 cmd = vmcmd_on_reboot;
1578 else if (strcmp(trigger->name, ON_PANIC_STR) == 0)
1579 cmd = vmcmd_on_panic;
1580 else if (strcmp(trigger->name, ON_HALT_STR) == 0)
1581 cmd = vmcmd_on_halt;
1582 else if (strcmp(trigger->name, ON_POFF_STR) == 0)
1583 cmd = vmcmd_on_poff;
7dd6b334
MH
1584 else if (strcmp(trigger->name, ON_RESTART_STR) == 0)
1585 cmd = vmcmd_on_restart;
99ca4e58
MH
1586 else
1587 return;
1588
1589 if (strlen(cmd) == 0)
1590 return;
8143adaf 1591 __cpcmd(cmd, NULL, 0, NULL);
99ca4e58
MH
1592}
1593
1594static int vmcmd_init(void)
1595{
1596 if (!MACHINE_IS_VM)
b8e660b8 1597 return -EOPNOTSUPP;
99ca4e58
MH
1598 vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj);
1599 if (!vmcmd_kset)
1600 return -ENOMEM;
1601 return sysfs_create_group(&vmcmd_kset->kobj, &vmcmd_attr_group);
1602}
1603
1604static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR,
1605 vmcmd_run, vmcmd_init};
1606
1607/*
1608 * stop shutdown action: Stop Linux on shutdown.
1609 */
1610
1611static void stop_run(struct shutdown_trigger *trigger)
1612{
e1202eda
MH
1613 if (strcmp(trigger->name, ON_PANIC_STR) == 0 ||
1614 strcmp(trigger->name, ON_RESTART_STR) == 0)
c6547497 1615 disabled_wait((unsigned long) __builtin_return_address(0));
8b646bd7 1616 smp_stop_cpu();
99ca4e58
MH
1617}
1618
1619static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
1620 stop_run, NULL};
1621
1622/* action list */
1623
1624static struct shutdown_action *shutdown_actions_list[] = {
099b7651
FM
1625 &ipl_action, &reipl_action, &dump_reipl_action, &dump_action,
1626 &vmcmd_action, &stop_action};
99ca4e58
MH
1627#define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *))
1628
1629/*
1630 * Trigger section
1631 */
1632
1633static struct kset *shutdown_actions_kset;
1634
1635static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
1636 size_t len)
1637{
1638 int i;
099b7651 1639
99ca4e58 1640 for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
099b7651 1641 if (sysfs_streq(buf, shutdown_actions_list[i]->name)) {
81088819
FM
1642 if (shutdown_actions_list[i]->init_rc) {
1643 return shutdown_actions_list[i]->init_rc;
1644 } else {
1645 trigger->action = shutdown_actions_list[i];
1646 return len;
1647 }
99ca4e58
MH
1648 }
1649 }
1650 return -EINVAL;
1651}
1652
1653/* on reipl */
1654
1655static struct shutdown_trigger on_reboot_trigger = {ON_REIPL_STR,
1656 &reipl_action};
1657
1658static ssize_t on_reboot_show(struct kobject *kobj,
1659 struct kobj_attribute *attr, char *page)
1660{
1661 return sprintf(page, "%s\n", on_reboot_trigger.action->name);
1662}
1663
1664static ssize_t on_reboot_store(struct kobject *kobj,
1665 struct kobj_attribute *attr,
1666 const char *buf, size_t len)
1667{
1668 return set_trigger(buf, &on_reboot_trigger, len);
1669}
0f024379 1670static struct kobj_attribute on_reboot_attr = __ATTR_RW(on_reboot);
99ca4e58
MH
1671
1672static void do_machine_restart(char *__unused)
1673{
1674 smp_send_stop();
1675 on_reboot_trigger.action->fn(&on_reboot_trigger);
1676 reipl_run(NULL);
1677}
1678void (*_machine_restart)(char *command) = do_machine_restart;
1679
1680/* on panic */
1681
1682static struct shutdown_trigger on_panic_trigger = {ON_PANIC_STR, &stop_action};
1683
1684static ssize_t on_panic_show(struct kobject *kobj,
1685 struct kobj_attribute *attr, char *page)
1686{
1687 return sprintf(page, "%s\n", on_panic_trigger.action->name);
1688}
1689
1690static ssize_t on_panic_store(struct kobject *kobj,
1691 struct kobj_attribute *attr,
1692 const char *buf, size_t len)
1693{
1694 return set_trigger(buf, &on_panic_trigger, len);
1695}
0f024379 1696static struct kobj_attribute on_panic_attr = __ATTR_RW(on_panic);
99ca4e58
MH
1697
1698static void do_panic(void)
1699{
3ab121ab 1700 lgr_info_log();
99ca4e58
MH
1701 on_panic_trigger.action->fn(&on_panic_trigger);
1702 stop_run(&on_panic_trigger);
1703}
1704
7dd6b334
MH
1705/* on restart */
1706
1707static struct shutdown_trigger on_restart_trigger = {ON_RESTART_STR,
e1202eda 1708 &stop_action};
7dd6b334
MH
1709
1710static ssize_t on_restart_show(struct kobject *kobj,
1711 struct kobj_attribute *attr, char *page)
1712{
1713 return sprintf(page, "%s\n", on_restart_trigger.action->name);
1714}
1715
1716static ssize_t on_restart_store(struct kobject *kobj,
1717 struct kobj_attribute *attr,
1718 const char *buf, size_t len)
1719{
1720 return set_trigger(buf, &on_restart_trigger, len);
1721}
0f024379 1722static struct kobj_attribute on_restart_attr = __ATTR_RW(on_restart);
7dd6b334 1723
8b646bd7 1724static void __do_restart(void *ignore)
7dd6b334 1725{
fa7c0043 1726 __arch_local_irq_stosm(0x04); /* enable DAT */
7dd6b334 1727 smp_send_stop();
60a0c68d
MH
1728#ifdef CONFIG_CRASH_DUMP
1729 crash_kexec(NULL);
1730#endif
7dd6b334
MH
1731 on_restart_trigger.action->fn(&on_restart_trigger);
1732 stop_run(&on_restart_trigger);
1733}
1734
8b646bd7
MS
1735void do_restart(void)
1736{
3ab121ab
MH
1737 tracing_off();
1738 debug_locks_off();
1739 lgr_info_log();
8b646bd7
MS
1740 smp_call_online_cpu(__do_restart, NULL);
1741}
1742
99ca4e58
MH
1743/* on halt */
1744
1745static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};
1746
1747static ssize_t on_halt_show(struct kobject *kobj,
1748 struct kobj_attribute *attr, char *page)
1749{
1750 return sprintf(page, "%s\n", on_halt_trigger.action->name);
1751}
1752
1753static ssize_t on_halt_store(struct kobject *kobj,
1754 struct kobj_attribute *attr,
1755 const char *buf, size_t len)
1756{
1757 return set_trigger(buf, &on_halt_trigger, len);
1758}
0f024379 1759static struct kobj_attribute on_halt_attr = __ATTR_RW(on_halt);
99ca4e58
MH
1760
1761static void do_machine_halt(void)
1762{
1763 smp_send_stop();
1764 on_halt_trigger.action->fn(&on_halt_trigger);
1765 stop_run(&on_halt_trigger);
1766}
1767void (*_machine_halt)(void) = do_machine_halt;
1768
1769/* on power off */
1770
1771static struct shutdown_trigger on_poff_trigger = {ON_POFF_STR, &stop_action};
1772
1773static ssize_t on_poff_show(struct kobject *kobj,
1774 struct kobj_attribute *attr, char *page)
1775{
1776 return sprintf(page, "%s\n", on_poff_trigger.action->name);
1777}
1778
1779static ssize_t on_poff_store(struct kobject *kobj,
1780 struct kobj_attribute *attr,
1781 const char *buf, size_t len)
1782{
1783 return set_trigger(buf, &on_poff_trigger, len);
1784}
0f024379 1785static struct kobj_attribute on_poff_attr = __ATTR_RW(on_poff);
99ca4e58
MH
1786
1787static void do_machine_power_off(void)
1788{
1789 smp_send_stop();
1790 on_poff_trigger.action->fn(&on_poff_trigger);
1791 stop_run(&on_poff_trigger);
1792}
1793void (*_machine_power_off)(void) = do_machine_power_off;
1794
0f024379
SO
1795static struct attribute *shutdown_action_attrs[] = {
1796 &on_restart_attr.attr,
1797 &on_reboot_attr.attr,
1798 &on_panic_attr.attr,
1799 &on_halt_attr.attr,
1800 &on_poff_attr.attr,
1801 NULL,
1802};
1803
1804static struct attribute_group shutdown_action_attr_group = {
1805 .attrs = shutdown_action_attrs,
1806};
1807
99ca4e58
MH
1808static void __init shutdown_triggers_init(void)
1809{
d91885be 1810 shutdown_actions_kset = kset_create_and_add("shutdown_actions", NULL,
f62ed9e3 1811 firmware_kobj);
d91885be 1812 if (!shutdown_actions_kset)
99ca4e58 1813 goto fail;
0f024379
SO
1814 if (sysfs_create_group(&shutdown_actions_kset->kobj,
1815 &shutdown_action_attr_group))
7dd6b334 1816 goto fail;
99ca4e58
MH
1817 return;
1818fail:
1819 panic("shutdown_triggers_init failed\n");
1820}
1821
1822static void __init shutdown_actions_init(void)
1823{
1824 int i;
1825
1826 for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
1827 if (!shutdown_actions_list[i]->init)
1828 continue;
81088819
FM
1829 shutdown_actions_list[i]->init_rc =
1830 shutdown_actions_list[i]->init();
ff6b8ea6 1831 }
ff6b8ea6
MH
1832}
1833
1834static int __init s390_ipl_init(void)
1835{
69928601
MH
1836 char str[8] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40};
1837
d09293ae 1838 sclp_get_ipl_info(&sclp_ipl_info);
69928601
MH
1839 /*
1840 * Fix loadparm: There are systems where the (SCSI) LOADPARM
1841 * returned by read SCP info is invalid (contains EBCDIC blanks)
1842 * when the system has been booted via diag308. In that case we use
1843 * the value from diag308, if available.
1844 *
1845 * There are also systems where diag308 store does not work in
1846 * case the system is booted from HMC. Fortunately in this case
1847 * READ SCP info provides the correct value.
1848 */
1849 if (memcmp(sclp_ipl_info.loadparm, str, sizeof(str)) == 0 &&
1850 diag308_set_works)
1851 memcpy(sclp_ipl_info.loadparm, ipl_block.hdr.loadparm,
1852 LOADPARM_LEN);
99ca4e58
MH
1853 shutdown_actions_init();
1854 shutdown_triggers_init();
ff6b8ea6
MH
1855 return 0;
1856}
1857
1858__initcall(s390_ipl_init);
15e9b586 1859
99ca4e58
MH
1860static void __init strncpy_skip_quote(char *dst, char *src, int n)
1861{
1862 int sx, dx;
1863
1864 dx = 0;
1865 for (sx = 0; src[sx] != 0; sx++) {
1866 if (src[sx] == '"')
1867 continue;
1868 dst[dx++] = src[sx];
1869 if (dx >= n)
1870 break;
1871 }
1872}
1873
1874static int __init vmcmd_on_reboot_setup(char *str)
1875{
1876 if (!MACHINE_IS_VM)
1877 return 1;
1878 strncpy_skip_quote(vmcmd_on_reboot, str, 127);
1879 vmcmd_on_reboot[127] = 0;
1880 on_reboot_trigger.action = &vmcmd_action;
1881 return 1;
1882}
1883__setup("vmreboot=", vmcmd_on_reboot_setup);
1884
1885static int __init vmcmd_on_panic_setup(char *str)
1886{
1887 if (!MACHINE_IS_VM)
1888 return 1;
1889 strncpy_skip_quote(vmcmd_on_panic, str, 127);
1890 vmcmd_on_panic[127] = 0;
1891 on_panic_trigger.action = &vmcmd_action;
1892 return 1;
1893}
1894__setup("vmpanic=", vmcmd_on_panic_setup);
1895
1896static int __init vmcmd_on_halt_setup(char *str)
1897{
1898 if (!MACHINE_IS_VM)
1899 return 1;
1900 strncpy_skip_quote(vmcmd_on_halt, str, 127);
1901 vmcmd_on_halt[127] = 0;
1902 on_halt_trigger.action = &vmcmd_action;
1903 return 1;
1904}
1905__setup("vmhalt=", vmcmd_on_halt_setup);
1906
1907static int __init vmcmd_on_poff_setup(char *str)
1908{
1909 if (!MACHINE_IS_VM)
1910 return 1;
1911 strncpy_skip_quote(vmcmd_on_poff, str, 127);
1912 vmcmd_on_poff[127] = 0;
1913 on_poff_trigger.action = &vmcmd_action;
1914 return 1;
1915}
1916__setup("vmpoff=", vmcmd_on_poff_setup);
1917
1918static int on_panic_notify(struct notifier_block *self,
1919 unsigned long event, void *data)
1920{
1921 do_panic();
1922 return NOTIFY_OK;
1923}
1924
1925static struct notifier_block on_panic_nb = {
1926 .notifier_call = on_panic_notify,
7e9b580e 1927 .priority = INT_MIN,
99ca4e58
MH
1928};
1929
1930void __init setup_ipl(void)
1931{
1932 ipl_info.type = get_ipl_type();
1933 switch (ipl_info.type) {
1934 case IPL_TYPE_CCW:
1935 ipl_info.data.ccw.dev_id.devno = ipl_devno;
1936 ipl_info.data.ccw.dev_id.ssid = 0;
1937 break;
1938 case IPL_TYPE_FCP:
1939 case IPL_TYPE_FCP_DUMP:
1940 ipl_info.data.fcp.dev_id.devno =
1941 IPL_PARMBLOCK_START->ipl_info.fcp.devno;
1942 ipl_info.data.fcp.dev_id.ssid = 0;
1943 ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn;
1944 ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun;
1945 break;
1946 case IPL_TYPE_NSS:
1947 strncpy(ipl_info.data.nss.name, kernel_nss_name,
1948 sizeof(ipl_info.data.nss.name));
1949 break;
1950 case IPL_TYPE_UNKNOWN:
99ca4e58
MH
1951 /* We have no info to copy */
1952 break;
1953 }
1954 atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
1955}
1956
a0443fbb
HB
1957void __init ipl_update_parameters(void)
1958{
3a95e8eb
MH
1959 int rc;
1960
1961 rc = diag308(DIAG308_STORE, &ipl_block);
1962 if ((rc == DIAG308_RC_OK) || (rc == DIAG308_RC_NOCONFIG))
a0443fbb
HB
1963 diag308_set_works = 1;
1964}
1965
6fc321fd
HC
1966void __init ipl_save_parameters(void)
1967{
1968 struct cio_iplinfo iplinfo;
6fc321fd
HC
1969 void *src, *dst;
1970
1971 if (cio_get_iplinfo(&iplinfo))
1972 return;
1973
1974 ipl_devno = iplinfo.devno;
1975 ipl_flags |= IPL_DEVNO_VALID;
1976 if (!iplinfo.is_qdio)
1977 return;
1978 ipl_flags |= IPL_PARMBLOCK_VALID;
cbb870c8 1979 src = (void *)(unsigned long)S390_lowcore.ipl_parmblock_ptr;
6fc321fd
HC
1980 dst = (void *)IPL_PARMBLOCK_ORIGIN;
1981 memmove(dst, src, PAGE_SIZE);
cbb870c8 1982 S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN;
6fc321fd
HC
1983}
1984
15e9b586
HC
1985static LIST_HEAD(rcall);
1986static DEFINE_MUTEX(rcall_mutex);
1987
1988void register_reset_call(struct reset_call *reset)
1989{
1990 mutex_lock(&rcall_mutex);
1991 list_add(&reset->list, &rcall);
1992 mutex_unlock(&rcall_mutex);
1993}
1994EXPORT_SYMBOL_GPL(register_reset_call);
1995
1996void unregister_reset_call(struct reset_call *reset)
1997{
1998 mutex_lock(&rcall_mutex);
1999 list_del(&reset->list);
2000 mutex_unlock(&rcall_mutex);
2001}
2002EXPORT_SYMBOL_GPL(unregister_reset_call);
2003
2004static void do_reset_calls(void)
2005{
2006 struct reset_call *reset;
2007
9dc7356e
MH
2008 if (diag308_set_works) {
2009 diag308_reset();
2010 return;
2011 }
15e9b586
HC
2012 list_for_each_entry(reset, &rcall, list)
2013 reset->fn();
2014}
2015
c5dd8586 2016u32 dump_prefix_page;
15e9b586 2017
10ad34bc
MS
2018void s390_reset_system(void (*fn_pre)(void),
2019 void (*fn_post)(void *), void *data)
15e9b586
HC
2020{
2021 struct _lowcore *lc;
2022
15e9b586 2023 lc = (struct _lowcore *)(unsigned long) store_prefix();
a45e1414
MH
2024
2025 /* Stack for interrupt/machine check handler */
15e9b586
HC
2026 lc->panic_stack = S390_lowcore.panic_stack;
2027
da1cf23e 2028 /* Save prefix page address for dump case */
c5dd8586 2029 dump_prefix_page = (u32)(unsigned long) lc;
da1cf23e 2030
15e9b586
HC
2031 /* Disable prefixing */
2032 set_prefix(0);
2033
2034 /* Disable lowcore protection */
2035 __ctl_clear_bit(0,28);
2036
2037 /* Set new machine check handler */
e258d719 2038 S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT;
15e9b586 2039 S390_lowcore.mcck_new_psw.addr =
ab14de6c 2040 PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
a45e1414
MH
2041
2042 /* Set new program check handler */
e258d719 2043 S390_lowcore.program_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT;
a45e1414 2044 S390_lowcore.program_new_psw.addr =
ab14de6c 2045 PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
a45e1414 2046
852ffd0f
MH
2047 /*
2048 * Clear subchannel ID and number to signal new kernel that no CCW or
2049 * SCSI IPL has been done (for kexec and kdump)
2050 */
2051 S390_lowcore.subchannel_id = 0;
2052 S390_lowcore.subchannel_nr = 0;
2053
60a0c68d
MH
2054 /* Store status at absolute zero */
2055 store_status();
2056
10ad34bc
MS
2057 /* Call function before reset */
2058 if (fn_pre)
2059 fn_pre();
15e9b586 2060 do_reset_calls();
10ad34bc
MS
2061 /* Call function after reset */
2062 if (fn_post)
2063 fn_post(data);
15e9b586 2064}