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