hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/arch/s390/kernel/ipl.c
....@@ -29,6 +29,8 @@
2929 #include <asm/checksum.h>
3030 #include <asm/debug.h>
3131 #include <asm/os_info.h>
32
+#include <asm/sections.h>
33
+#include <asm/boot_data.h>
3234 #include "entry.h"
3335
3436 #define IPL_PARM_BLOCK_VERSION 0
....@@ -37,10 +39,13 @@
3739 #define IPL_CCW_STR "ccw"
3840 #define IPL_FCP_STR "fcp"
3941 #define IPL_FCP_DUMP_STR "fcp_dump"
42
+#define IPL_NVME_STR "nvme"
43
+#define IPL_NVME_DUMP_STR "nvme_dump"
4044 #define IPL_NSS_STR "nss"
4145
4246 #define DUMP_CCW_STR "ccw"
4347 #define DUMP_FCP_STR "fcp"
48
+#define DUMP_NVME_STR "nvme"
4449 #define DUMP_NONE_STR "none"
4550
4651 /*
....@@ -91,6 +96,10 @@
9196 return IPL_FCP_DUMP_STR;
9297 case IPL_TYPE_NSS:
9398 return IPL_NSS_STR;
99
+ case IPL_TYPE_NVME:
100
+ return IPL_NVME_STR;
101
+ case IPL_TYPE_NVME_DUMP:
102
+ return IPL_NVME_DUMP_STR;
94103 case IPL_TYPE_UNKNOWN:
95104 default:
96105 return IPL_UNKNOWN_STR;
....@@ -101,6 +110,7 @@
101110 DUMP_TYPE_NONE = 1,
102111 DUMP_TYPE_CCW = 2,
103112 DUMP_TYPE_FCP = 4,
113
+ DUMP_TYPE_NVME = 8,
104114 };
105115
106116 static char *dump_type_str(enum dump_type type)
....@@ -112,18 +122,28 @@
112122 return DUMP_CCW_STR;
113123 case DUMP_TYPE_FCP:
114124 return DUMP_FCP_STR;
125
+ case DUMP_TYPE_NVME:
126
+ return DUMP_NVME_STR;
115127 default:
116128 return NULL;
117129 }
118130 }
119131
120
-static int ipl_block_valid;
121
-static struct ipl_parameter_block ipl_block;
132
+int __bootdata_preserved(ipl_block_valid);
133
+struct ipl_parameter_block __bootdata_preserved(ipl_block);
134
+int __bootdata_preserved(ipl_secure_flag);
135
+
136
+unsigned long __bootdata_preserved(ipl_cert_list_addr);
137
+unsigned long __bootdata_preserved(ipl_cert_list_size);
138
+
139
+unsigned long __bootdata(early_ipl_comp_list_addr);
140
+unsigned long __bootdata(early_ipl_comp_list_size);
122141
123142 static int reipl_capabilities = IPL_TYPE_UNKNOWN;
124143
125144 static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
126145 static struct ipl_parameter_block *reipl_block_fcp;
146
+static struct ipl_parameter_block *reipl_block_nvme;
127147 static struct ipl_parameter_block *reipl_block_ccw;
128148 static struct ipl_parameter_block *reipl_block_nss;
129149 static struct ipl_parameter_block *reipl_block_actual;
....@@ -131,9 +151,14 @@
131151 static int dump_capabilities = DUMP_TYPE_NONE;
132152 static enum dump_type dump_type = DUMP_TYPE_NONE;
133153 static struct ipl_parameter_block *dump_block_fcp;
154
+static struct ipl_parameter_block *dump_block_nvme;
134155 static struct ipl_parameter_block *dump_block_ccw;
135156
136157 static struct sclp_ipl_info sclp_ipl_info;
158
+
159
+static bool reipl_nvme_clear;
160
+static bool reipl_fcp_clear;
161
+static bool reipl_ccw_clear;
137162
138163 static inline int __diag308(unsigned long subcode, void *addr)
139164 {
....@@ -151,6 +176,8 @@
151176
152177 int diag308(unsigned long subcode, void *addr)
153178 {
179
+ if (IS_ENABLED(CONFIG_KASAN))
180
+ __arch_local_irq_stosm(0x04); /* enable DAT */
154181 diag_stat_inc(DIAG_STAT_X308);
155182 return __diag308(subcode, addr);
156183 }
....@@ -163,7 +190,7 @@
163190 struct kobj_attribute *attr, \
164191 char *page) \
165192 { \
166
- return snprintf(page, PAGE_SIZE, _format, ##args); \
193
+ return scnprintf(page, PAGE_SIZE, _format, ##args); \
167194 }
168195
169196 #define IPL_ATTR_CCW_STORE_FN(_prefix, _name, _ipl_blk) \
....@@ -239,14 +266,19 @@
239266 if (!ipl_block_valid)
240267 return IPL_TYPE_UNKNOWN;
241268
242
- switch (ipl_block.hdr.pbt) {
243
- case DIAG308_IPL_TYPE_CCW:
269
+ switch (ipl_block.pb0_hdr.pbt) {
270
+ case IPL_PBT_CCW:
244271 return IPL_TYPE_CCW;
245
- case DIAG308_IPL_TYPE_FCP:
246
- if (ipl_block.ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP)
272
+ case IPL_PBT_FCP:
273
+ if (ipl_block.fcp.opt == IPL_PB0_FCP_OPT_DUMP)
247274 return IPL_TYPE_FCP_DUMP;
248275 else
249276 return IPL_TYPE_FCP;
277
+ case IPL_PBT_NVME:
278
+ if (ipl_block.nvme.opt == IPL_PB0_NVME_OPT_DUMP)
279
+ return IPL_TYPE_NVME_DUMP;
280
+ else
281
+ return IPL_TYPE_NVME;
250282 }
251283 return IPL_TYPE_UNKNOWN;
252284 }
....@@ -262,114 +294,33 @@
262294
263295 static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
264296
265
-/* VM IPL PARM routines */
266
-static size_t reipl_get_ascii_vmparm(char *dest, size_t size,
267
- const struct ipl_parameter_block *ipb)
297
+static ssize_t ipl_secure_show(struct kobject *kobj,
298
+ struct kobj_attribute *attr, char *page)
268299 {
269
- int i;
270
- size_t len;
271
- char has_lowercase = 0;
272
-
273
- len = 0;
274
- if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
275
- (ipb->ipl_info.ccw.vm_parm_len > 0)) {
276
-
277
- len = min_t(size_t, size - 1, ipb->ipl_info.ccw.vm_parm_len);
278
- memcpy(dest, ipb->ipl_info.ccw.vm_parm, len);
279
- /* If at least one character is lowercase, we assume mixed
280
- * case; otherwise we convert everything to lowercase.
281
- */
282
- for (i = 0; i < len; i++)
283
- if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */
284
- (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */
285
- (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */
286
- has_lowercase = 1;
287
- break;
288
- }
289
- if (!has_lowercase)
290
- EBC_TOLOWER(dest, len);
291
- EBCASC(dest, len);
292
- }
293
- dest[len] = 0;
294
-
295
- return len;
300
+ return sprintf(page, "%i\n", !!ipl_secure_flag);
296301 }
297302
298
-size_t append_ipl_vmparm(char *dest, size_t size)
299
-{
300
- size_t rc;
303
+static struct kobj_attribute sys_ipl_secure_attr =
304
+ __ATTR(secure, 0444, ipl_secure_show, NULL);
301305
302
- rc = 0;
303
- if (ipl_block_valid && ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW)
304
- rc = reipl_get_ascii_vmparm(dest, size, &ipl_block);
305
- else
306
- dest[0] = 0;
307
- return rc;
306
+static ssize_t ipl_has_secure_show(struct kobject *kobj,
307
+ struct kobj_attribute *attr, char *page)
308
+{
309
+ return sprintf(page, "%i\n", !!sclp.has_sipl);
308310 }
311
+
312
+static struct kobj_attribute sys_ipl_has_secure_attr =
313
+ __ATTR(has_secure, 0444, ipl_has_secure_show, NULL);
309314
310315 static ssize_t ipl_vm_parm_show(struct kobject *kobj,
311316 struct kobj_attribute *attr, char *page)
312317 {
313318 char parm[DIAG308_VMPARM_SIZE + 1] = {};
314319
315
- append_ipl_vmparm(parm, sizeof(parm));
320
+ if (ipl_block_valid && (ipl_block.pb0_hdr.pbt == IPL_PBT_CCW))
321
+ ipl_block_get_ascii_vmparm(parm, sizeof(parm), &ipl_block);
316322 return sprintf(page, "%s\n", parm);
317323 }
318
-
319
-static size_t scpdata_length(const char* buf, size_t count)
320
-{
321
- while (count) {
322
- if (buf[count - 1] != '\0' && buf[count - 1] != ' ')
323
- break;
324
- count--;
325
- }
326
- return count;
327
-}
328
-
329
-static size_t reipl_append_ascii_scpdata(char *dest, size_t size,
330
- const struct ipl_parameter_block *ipb)
331
-{
332
- size_t count;
333
- size_t i;
334
- int has_lowercase;
335
-
336
- count = min(size - 1, scpdata_length(ipb->ipl_info.fcp.scp_data,
337
- ipb->ipl_info.fcp.scp_data_len));
338
- if (!count)
339
- goto out;
340
-
341
- has_lowercase = 0;
342
- for (i = 0; i < count; i++) {
343
- if (!isascii(ipb->ipl_info.fcp.scp_data[i])) {
344
- count = 0;
345
- goto out;
346
- }
347
- if (!has_lowercase && islower(ipb->ipl_info.fcp.scp_data[i]))
348
- has_lowercase = 1;
349
- }
350
-
351
- if (has_lowercase)
352
- memcpy(dest, ipb->ipl_info.fcp.scp_data, count);
353
- else
354
- for (i = 0; i < count; i++)
355
- dest[i] = tolower(ipb->ipl_info.fcp.scp_data[i]);
356
-out:
357
- dest[count] = '\0';
358
- return count;
359
-}
360
-
361
-size_t append_ipl_scpdata(char *dest, size_t len)
362
-{
363
- size_t rc;
364
-
365
- rc = 0;
366
- if (ipl_block_valid && ipl_block.hdr.pbt == DIAG308_IPL_TYPE_FCP)
367
- rc = reipl_append_ascii_scpdata(dest, len, &ipl_block);
368
- else
369
- dest[0] = 0;
370
- return rc;
371
-}
372
-
373324
374325 static struct kobj_attribute sys_ipl_vm_parm_attr =
375326 __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL);
....@@ -379,12 +330,14 @@
379330 {
380331 switch (ipl_info.type) {
381332 case IPL_TYPE_CCW:
382
- return sprintf(page, "0.%x.%04x\n", ipl_block.ipl_info.ccw.ssid,
383
- ipl_block.ipl_info.ccw.devno);
333
+ return sprintf(page, "0.%x.%04x\n", ipl_block.ccw.ssid,
334
+ ipl_block.ccw.devno);
384335 case IPL_TYPE_FCP:
385336 case IPL_TYPE_FCP_DUMP:
386
- return sprintf(page, "0.0.%04x\n",
387
- ipl_block.ipl_info.fcp.devno);
337
+ return sprintf(page, "0.0.%04x\n", ipl_block.fcp.devno);
338
+ case IPL_TYPE_NVME:
339
+ case IPL_TYPE_NVME_DUMP:
340
+ return sprintf(page, "%08ux\n", ipl_block.nvme.fid);
388341 default:
389342 return 0;
390343 }
....@@ -408,13 +361,27 @@
408361 struct bin_attribute *attr, char *buf,
409362 loff_t off, size_t count)
410363 {
411
- unsigned int size = ipl_block.ipl_info.fcp.scp_data_len;
412
- void *scp_data = &ipl_block.ipl_info.fcp.scp_data;
364
+ unsigned int size = ipl_block.fcp.scp_data_len;
365
+ void *scp_data = &ipl_block.fcp.scp_data;
413366
414367 return memory_read_from_buffer(buf, count, &off, scp_data, size);
415368 }
369
+
370
+static ssize_t ipl_nvme_scp_data_read(struct file *filp, struct kobject *kobj,
371
+ struct bin_attribute *attr, char *buf,
372
+ loff_t off, size_t count)
373
+{
374
+ unsigned int size = ipl_block.nvme.scp_data_len;
375
+ void *scp_data = &ipl_block.nvme.scp_data;
376
+
377
+ return memory_read_from_buffer(buf, count, &off, scp_data, size);
378
+}
379
+
416380 static struct bin_attribute ipl_scp_data_attr =
417381 __BIN_ATTR(scp_data, S_IRUGO, ipl_scp_data_read, NULL, PAGE_SIZE);
382
+
383
+static struct bin_attribute ipl_nvme_scp_data_attr =
384
+ __BIN_ATTR(scp_data, S_IRUGO, ipl_nvme_scp_data_read, NULL, PAGE_SIZE);
418385
419386 static struct bin_attribute *ipl_fcp_bin_attrs[] = {
420387 &ipl_parameter_attr,
....@@ -422,16 +389,32 @@
422389 NULL,
423390 };
424391
392
+static struct bin_attribute *ipl_nvme_bin_attrs[] = {
393
+ &ipl_parameter_attr,
394
+ &ipl_nvme_scp_data_attr,
395
+ NULL,
396
+};
397
+
425398 /* FCP ipl device attributes */
426399
427400 DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n",
428
- (unsigned long long)ipl_block.ipl_info.fcp.wwpn);
401
+ (unsigned long long)ipl_block.fcp.wwpn);
429402 DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n",
430
- (unsigned long long)ipl_block.ipl_info.fcp.lun);
403
+ (unsigned long long)ipl_block.fcp.lun);
431404 DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n",
432
- (unsigned long long)ipl_block.ipl_info.fcp.bootprog);
405
+ (unsigned long long)ipl_block.fcp.bootprog);
433406 DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n",
434
- (unsigned long long)ipl_block.ipl_info.fcp.br_lba);
407
+ (unsigned long long)ipl_block.fcp.br_lba);
408
+
409
+/* NVMe ipl device attributes */
410
+DEFINE_IPL_ATTR_RO(ipl_nvme, fid, "0x%08llx\n",
411
+ (unsigned long long)ipl_block.nvme.fid);
412
+DEFINE_IPL_ATTR_RO(ipl_nvme, nsid, "0x%08llx\n",
413
+ (unsigned long long)ipl_block.nvme.nsid);
414
+DEFINE_IPL_ATTR_RO(ipl_nvme, bootprog, "%lld\n",
415
+ (unsigned long long)ipl_block.nvme.bootprog);
416
+DEFINE_IPL_ATTR_RO(ipl_nvme, br_lba, "%lld\n",
417
+ (unsigned long long)ipl_block.nvme.br_lba);
435418
436419 static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
437420 struct kobj_attribute *attr, char *page)
....@@ -457,6 +440,8 @@
457440 &sys_ipl_fcp_bootprog_attr.attr,
458441 &sys_ipl_fcp_br_lba_attr.attr,
459442 &sys_ipl_ccw_loadparm_attr.attr,
443
+ &sys_ipl_secure_attr.attr,
444
+ &sys_ipl_has_secure_attr.attr,
460445 NULL,
461446 };
462447
....@@ -465,6 +450,24 @@
465450 .bin_attrs = ipl_fcp_bin_attrs,
466451 };
467452
453
+static struct attribute *ipl_nvme_attrs[] = {
454
+ &sys_ipl_type_attr.attr,
455
+ &sys_ipl_nvme_fid_attr.attr,
456
+ &sys_ipl_nvme_nsid_attr.attr,
457
+ &sys_ipl_nvme_bootprog_attr.attr,
458
+ &sys_ipl_nvme_br_lba_attr.attr,
459
+ &sys_ipl_ccw_loadparm_attr.attr,
460
+ &sys_ipl_secure_attr.attr,
461
+ &sys_ipl_has_secure_attr.attr,
462
+ NULL,
463
+};
464
+
465
+static struct attribute_group ipl_nvme_attr_group = {
466
+ .attrs = ipl_nvme_attrs,
467
+ .bin_attrs = ipl_nvme_bin_attrs,
468
+};
469
+
470
+
468471 /* CCW ipl device attributes */
469472
470473 static struct attribute *ipl_ccw_attrs_vm[] = {
....@@ -472,6 +475,8 @@
472475 &sys_ipl_device_attr.attr,
473476 &sys_ipl_ccw_loadparm_attr.attr,
474477 &sys_ipl_vm_parm_attr.attr,
478
+ &sys_ipl_secure_attr.attr,
479
+ &sys_ipl_has_secure_attr.attr,
475480 NULL,
476481 };
477482
....@@ -479,6 +484,8 @@
479484 &sys_ipl_type_attr.attr,
480485 &sys_ipl_device_attr.attr,
481486 &sys_ipl_ccw_loadparm_attr.attr,
487
+ &sys_ipl_secure_attr.attr,
488
+ &sys_ipl_has_secure_attr.attr,
482489 NULL,
483490 };
484491
....@@ -494,6 +501,8 @@
494501
495502 static struct attribute *ipl_unknown_attrs[] = {
496503 &sys_ipl_type_attr.attr,
504
+ &sys_ipl_secure_attr.attr,
505
+ &sys_ipl_has_secure_attr.attr,
497506 NULL,
498507 };
499508
....@@ -536,6 +545,10 @@
536545 case IPL_TYPE_FCP_DUMP:
537546 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
538547 break;
548
+ case IPL_TYPE_NVME:
549
+ case IPL_TYPE_NVME_DUMP:
550
+ rc = sysfs_create_group(&ipl_kset->kobj, &ipl_nvme_attr_group);
551
+ break;
539552 default:
540553 rc = sysfs_create_group(&ipl_kset->kobj,
541554 &ipl_unknown_attr_group);
....@@ -564,7 +577,7 @@
564577 {
565578 char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
566579
567
- reipl_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
580
+ ipl_block_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
568581 return sprintf(page, "%s\n", vmparm);
569582 }
570583
....@@ -587,14 +600,14 @@
587600 if (!(isalnum(buf[i]) || isascii(buf[i]) || isprint(buf[i])))
588601 return -EINVAL;
589602
590
- memset(ipb->ipl_info.ccw.vm_parm, 0, DIAG308_VMPARM_SIZE);
591
- ipb->ipl_info.ccw.vm_parm_len = ip_len;
603
+ memset(ipb->ccw.vm_parm, 0, DIAG308_VMPARM_SIZE);
604
+ ipb->ccw.vm_parm_len = ip_len;
592605 if (ip_len > 0) {
593
- ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
594
- memcpy(ipb->ipl_info.ccw.vm_parm, buf, ip_len);
595
- ASCEBC(ipb->ipl_info.ccw.vm_parm, ip_len);
606
+ ipb->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_VP;
607
+ memcpy(ipb->ccw.vm_parm, buf, ip_len);
608
+ ASCEBC(ipb->ccw.vm_parm, ip_len);
596609 } else {
597
- ipb->ipl_info.ccw.vm_flags &= ~DIAG308_VM_FLAGS_VP_VALID;
610
+ ipb->ccw.vm_flags &= ~IPL_PB0_CCW_VM_FLAG_VP;
598611 }
599612
600613 return len;
....@@ -641,8 +654,8 @@
641654 struct bin_attribute *attr,
642655 char *buf, loff_t off, size_t count)
643656 {
644
- size_t size = reipl_block_fcp->ipl_info.fcp.scp_data_len;
645
- void *scp_data = reipl_block_fcp->ipl_info.fcp.scp_data;
657
+ size_t size = reipl_block_fcp->fcp.scp_data_len;
658
+ void *scp_data = reipl_block_fcp->fcp.scp_data;
646659
647660 return memory_read_from_buffer(buf, count, &off, scp_data, size);
648661 }
....@@ -658,17 +671,17 @@
658671 if (off)
659672 return -EINVAL;
660673
661
- memcpy(reipl_block_fcp->ipl_info.fcp.scp_data, buf, count);
674
+ memcpy(reipl_block_fcp->fcp.scp_data, buf, count);
662675 if (scpdata_len % 8) {
663676 padding = 8 - (scpdata_len % 8);
664
- memset(reipl_block_fcp->ipl_info.fcp.scp_data + scpdata_len,
677
+ memset(reipl_block_fcp->fcp.scp_data + scpdata_len,
665678 0, padding);
666679 scpdata_len += padding;
667680 }
668681
669
- reipl_block_fcp->ipl_info.fcp.scp_data_len = scpdata_len;
670
- reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN + scpdata_len;
671
- reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN + scpdata_len;
682
+ reipl_block_fcp->hdr.len = IPL_BP_FCP_LEN + scpdata_len;
683
+ reipl_block_fcp->fcp.len = IPL_BP0_FCP_LEN + scpdata_len;
684
+ reipl_block_fcp->fcp.scp_data_len = scpdata_len;
672685
673686 return count;
674687 }
....@@ -682,20 +695,20 @@
682695 };
683696
684697 DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%llx\n",
685
- reipl_block_fcp->ipl_info.fcp.wwpn);
698
+ reipl_block_fcp->fcp.wwpn);
686699 DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%llx\n",
687
- reipl_block_fcp->ipl_info.fcp.lun);
700
+ reipl_block_fcp->fcp.lun);
688701 DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
689
- reipl_block_fcp->ipl_info.fcp.bootprog);
702
+ reipl_block_fcp->fcp.bootprog);
690703 DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
691
- reipl_block_fcp->ipl_info.fcp.br_lba);
704
+ reipl_block_fcp->fcp.br_lba);
692705 DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
693
- reipl_block_fcp->ipl_info.fcp.devno);
706
+ reipl_block_fcp->fcp.devno);
694707
695708 static void reipl_get_ascii_loadparm(char *loadparm,
696709 struct ipl_parameter_block *ibp)
697710 {
698
- memcpy(loadparm, ibp->hdr.loadparm, LOADPARM_LEN);
711
+ memcpy(loadparm, ibp->common.loadparm, LOADPARM_LEN);
699712 EBCASC(loadparm, LOADPARM_LEN);
700713 loadparm[LOADPARM_LEN] = 0;
701714 strim(loadparm);
....@@ -730,11 +743,11 @@
730743 return -EINVAL;
731744 }
732745 /* initialize loadparm with blanks */
733
- memset(ipb->hdr.loadparm, ' ', LOADPARM_LEN);
746
+ memset(ipb->common.loadparm, ' ', LOADPARM_LEN);
734747 /* copy and convert to ebcdic */
735
- memcpy(ipb->hdr.loadparm, buf, lp_len);
736
- ASCEBC(ipb->hdr.loadparm, LOADPARM_LEN);
737
- ipb->hdr.flags |= DIAG308_FLAGS_LP_VALID;
748
+ memcpy(ipb->common.loadparm, buf, lp_len);
749
+ ASCEBC(ipb->common.loadparm, LOADPARM_LEN);
750
+ ipb->common.flags |= IPL_PB0_FLAG_LOADPARM;
738751 return len;
739752 }
740753
....@@ -756,6 +769,21 @@
756769 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_fcp_loadparm_show,
757770 reipl_fcp_loadparm_store);
758771
772
+static ssize_t reipl_fcp_clear_show(struct kobject *kobj,
773
+ struct kobj_attribute *attr, char *page)
774
+{
775
+ return sprintf(page, "%u\n", reipl_fcp_clear);
776
+}
777
+
778
+static ssize_t reipl_fcp_clear_store(struct kobject *kobj,
779
+ struct kobj_attribute *attr,
780
+ const char *buf, size_t len)
781
+{
782
+ if (strtobool(buf, &reipl_fcp_clear) < 0)
783
+ return -EINVAL;
784
+ return len;
785
+}
786
+
759787 static struct attribute *reipl_fcp_attrs[] = {
760788 &sys_reipl_fcp_device_attr.attr,
761789 &sys_reipl_fcp_wwpn_attr.attr,
....@@ -771,8 +799,116 @@
771799 .bin_attrs = reipl_fcp_bin_attrs,
772800 };
773801
802
+static struct kobj_attribute sys_reipl_fcp_clear_attr =
803
+ __ATTR(clear, 0644, reipl_fcp_clear_show, reipl_fcp_clear_store);
804
+
805
+/* NVME reipl device attributes */
806
+
807
+static ssize_t reipl_nvme_scpdata_read(struct file *filp, struct kobject *kobj,
808
+ struct bin_attribute *attr,
809
+ char *buf, loff_t off, size_t count)
810
+{
811
+ size_t size = reipl_block_nvme->nvme.scp_data_len;
812
+ void *scp_data = reipl_block_nvme->nvme.scp_data;
813
+
814
+ return memory_read_from_buffer(buf, count, &off, scp_data, size);
815
+}
816
+
817
+static ssize_t reipl_nvme_scpdata_write(struct file *filp, struct kobject *kobj,
818
+ struct bin_attribute *attr,
819
+ char *buf, loff_t off, size_t count)
820
+{
821
+ size_t scpdata_len = count;
822
+ size_t padding;
823
+
824
+ if (off)
825
+ return -EINVAL;
826
+
827
+ memcpy(reipl_block_nvme->nvme.scp_data, buf, count);
828
+ if (scpdata_len % 8) {
829
+ padding = 8 - (scpdata_len % 8);
830
+ memset(reipl_block_nvme->nvme.scp_data + scpdata_len,
831
+ 0, padding);
832
+ scpdata_len += padding;
833
+ }
834
+
835
+ reipl_block_nvme->hdr.len = IPL_BP_FCP_LEN + scpdata_len;
836
+ reipl_block_nvme->nvme.len = IPL_BP0_FCP_LEN + scpdata_len;
837
+ reipl_block_nvme->nvme.scp_data_len = scpdata_len;
838
+
839
+ return count;
840
+}
841
+
842
+static struct bin_attribute sys_reipl_nvme_scp_data_attr =
843
+ __BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_nvme_scpdata_read,
844
+ reipl_nvme_scpdata_write, DIAG308_SCPDATA_SIZE);
845
+
846
+static struct bin_attribute *reipl_nvme_bin_attrs[] = {
847
+ &sys_reipl_nvme_scp_data_attr,
848
+ NULL,
849
+};
850
+
851
+DEFINE_IPL_ATTR_RW(reipl_nvme, fid, "0x%08llx\n", "%llx\n",
852
+ reipl_block_nvme->nvme.fid);
853
+DEFINE_IPL_ATTR_RW(reipl_nvme, nsid, "0x%08llx\n", "%llx\n",
854
+ reipl_block_nvme->nvme.nsid);
855
+DEFINE_IPL_ATTR_RW(reipl_nvme, bootprog, "%lld\n", "%lld\n",
856
+ reipl_block_nvme->nvme.bootprog);
857
+DEFINE_IPL_ATTR_RW(reipl_nvme, br_lba, "%lld\n", "%lld\n",
858
+ reipl_block_nvme->nvme.br_lba);
859
+
860
+/* nvme wrapper */
861
+static ssize_t reipl_nvme_loadparm_show(struct kobject *kobj,
862
+ struct kobj_attribute *attr, char *page)
863
+{
864
+ return reipl_generic_loadparm_show(reipl_block_nvme, page);
865
+}
866
+
867
+static ssize_t reipl_nvme_loadparm_store(struct kobject *kobj,
868
+ struct kobj_attribute *attr,
869
+ const char *buf, size_t len)
870
+{
871
+ return reipl_generic_loadparm_store(reipl_block_nvme, buf, len);
872
+}
873
+
874
+static struct kobj_attribute sys_reipl_nvme_loadparm_attr =
875
+ __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nvme_loadparm_show,
876
+ reipl_nvme_loadparm_store);
877
+
878
+static struct attribute *reipl_nvme_attrs[] = {
879
+ &sys_reipl_nvme_fid_attr.attr,
880
+ &sys_reipl_nvme_nsid_attr.attr,
881
+ &sys_reipl_nvme_bootprog_attr.attr,
882
+ &sys_reipl_nvme_br_lba_attr.attr,
883
+ &sys_reipl_nvme_loadparm_attr.attr,
884
+ NULL,
885
+};
886
+
887
+static struct attribute_group reipl_nvme_attr_group = {
888
+ .attrs = reipl_nvme_attrs,
889
+ .bin_attrs = reipl_nvme_bin_attrs
890
+};
891
+
892
+static ssize_t reipl_nvme_clear_show(struct kobject *kobj,
893
+ struct kobj_attribute *attr, char *page)
894
+{
895
+ return sprintf(page, "%u\n", reipl_nvme_clear);
896
+}
897
+
898
+static ssize_t reipl_nvme_clear_store(struct kobject *kobj,
899
+ struct kobj_attribute *attr,
900
+ const char *buf, size_t len)
901
+{
902
+ if (strtobool(buf, &reipl_nvme_clear) < 0)
903
+ return -EINVAL;
904
+ return len;
905
+}
906
+
907
+static struct kobj_attribute sys_reipl_nvme_clear_attr =
908
+ __ATTR(clear, 0644, reipl_nvme_clear_show, reipl_nvme_clear_store);
909
+
774910 /* CCW reipl device attributes */
775
-DEFINE_IPL_CCW_ATTR_RW(reipl_ccw, device, reipl_block_ccw->ipl_info.ccw);
911
+DEFINE_IPL_CCW_ATTR_RW(reipl_ccw, device, reipl_block_ccw->ccw);
776912
777913 /* NSS wrapper */
778914 static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
....@@ -806,16 +942,36 @@
806942 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_ccw_loadparm_show,
807943 reipl_ccw_loadparm_store);
808944
945
+static ssize_t reipl_ccw_clear_show(struct kobject *kobj,
946
+ struct kobj_attribute *attr, char *page)
947
+{
948
+ return sprintf(page, "%u\n", reipl_ccw_clear);
949
+}
950
+
951
+static ssize_t reipl_ccw_clear_store(struct kobject *kobj,
952
+ struct kobj_attribute *attr,
953
+ const char *buf, size_t len)
954
+{
955
+ if (strtobool(buf, &reipl_ccw_clear) < 0)
956
+ return -EINVAL;
957
+ return len;
958
+}
959
+
960
+static struct kobj_attribute sys_reipl_ccw_clear_attr =
961
+ __ATTR(clear, 0644, reipl_ccw_clear_show, reipl_ccw_clear_store);
962
+
809963 static struct attribute *reipl_ccw_attrs_vm[] = {
810964 &sys_reipl_ccw_device_attr.attr,
811965 &sys_reipl_ccw_loadparm_attr.attr,
812966 &sys_reipl_ccw_vmparm_attr.attr,
967
+ &sys_reipl_ccw_clear_attr.attr,
813968 NULL,
814969 };
815970
816971 static struct attribute *reipl_ccw_attrs_lpar[] = {
817972 &sys_reipl_ccw_device_attr.attr,
818973 &sys_reipl_ccw_loadparm_attr.attr,
974
+ &sys_reipl_ccw_clear_attr.attr,
819975 NULL,
820976 };
821977
....@@ -834,7 +990,7 @@
834990 static void reipl_get_ascii_nss_name(char *dst,
835991 struct ipl_parameter_block *ipb)
836992 {
837
- memcpy(dst, ipb->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
993
+ memcpy(dst, ipb->ccw.nss_name, NSS_NAME_SIZE);
838994 EBCASC(dst, NSS_NAME_SIZE);
839995 dst[NSS_NAME_SIZE] = 0;
840996 }
....@@ -862,16 +1018,14 @@
8621018 if (nss_len > NSS_NAME_SIZE)
8631019 return -EINVAL;
8641020
865
- memset(reipl_block_nss->ipl_info.ccw.nss_name, 0x40, NSS_NAME_SIZE);
1021
+ memset(reipl_block_nss->ccw.nss_name, 0x40, NSS_NAME_SIZE);
8661022 if (nss_len > 0) {
867
- reipl_block_nss->ipl_info.ccw.vm_flags |=
868
- DIAG308_VM_FLAGS_NSS_VALID;
869
- memcpy(reipl_block_nss->ipl_info.ccw.nss_name, buf, nss_len);
870
- ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
871
- EBC_TOUPPER(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
1023
+ reipl_block_nss->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_NSS;
1024
+ memcpy(reipl_block_nss->ccw.nss_name, buf, nss_len);
1025
+ ASCEBC(reipl_block_nss->ccw.nss_name, nss_len);
1026
+ EBC_TOUPPER(reipl_block_nss->ccw.nss_name, nss_len);
8721027 } else {
873
- reipl_block_nss->ipl_info.ccw.vm_flags &=
874
- ~DIAG308_VM_FLAGS_NSS_VALID;
1028
+ reipl_block_nss->ccw.vm_flags &= ~IPL_PB0_CCW_VM_FLAG_NSS;
8751029 }
8761030
8771031 return len;
....@@ -917,6 +1071,9 @@
9171071 case IPL_TYPE_FCP:
9181072 reipl_block_actual = reipl_block_fcp;
9191073 break;
1074
+ case IPL_TYPE_NVME:
1075
+ reipl_block_actual = reipl_block_nvme;
1076
+ break;
9201077 case IPL_TYPE_NSS:
9211078 reipl_block_actual = reipl_block_nss;
9221079 break;
....@@ -943,6 +1100,8 @@
9431100 rc = reipl_set_type(IPL_TYPE_CCW);
9441101 else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
9451102 rc = reipl_set_type(IPL_TYPE_FCP);
1103
+ else if (strncmp(buf, IPL_NVME_STR, strlen(IPL_NVME_STR)) == 0)
1104
+ rc = reipl_set_type(IPL_TYPE_NVME);
9461105 else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
9471106 rc = reipl_set_type(IPL_TYPE_NSS);
9481107 return (rc != 0) ? rc : len;
....@@ -953,17 +1112,31 @@
9531112
9541113 static struct kset *reipl_kset;
9551114 static struct kset *reipl_fcp_kset;
1115
+static struct kset *reipl_nvme_kset;
9561116
9571117 static void __reipl_run(void *unused)
9581118 {
9591119 switch (reipl_type) {
9601120 case IPL_TYPE_CCW:
9611121 diag308(DIAG308_SET, reipl_block_ccw);
962
- diag308(DIAG308_LOAD_CLEAR, NULL);
1122
+ if (reipl_ccw_clear)
1123
+ diag308(DIAG308_LOAD_CLEAR, NULL);
1124
+ else
1125
+ diag308(DIAG308_LOAD_NORMAL_DUMP, NULL);
9631126 break;
9641127 case IPL_TYPE_FCP:
9651128 diag308(DIAG308_SET, reipl_block_fcp);
966
- diag308(DIAG308_LOAD_CLEAR, NULL);
1129
+ if (reipl_fcp_clear)
1130
+ diag308(DIAG308_LOAD_CLEAR, NULL);
1131
+ else
1132
+ diag308(DIAG308_LOAD_NORMAL, NULL);
1133
+ break;
1134
+ case IPL_TYPE_NVME:
1135
+ diag308(DIAG308_SET, reipl_block_nvme);
1136
+ if (reipl_nvme_clear)
1137
+ diag308(DIAG308_LOAD_CLEAR, NULL);
1138
+ else
1139
+ diag308(DIAG308_LOAD_NORMAL, NULL);
9671140 break;
9681141 case IPL_TYPE_NSS:
9691142 diag308(DIAG308_SET, reipl_block_nss);
....@@ -973,9 +1146,10 @@
9731146 diag308(DIAG308_LOAD_CLEAR, NULL);
9741147 break;
9751148 case IPL_TYPE_FCP_DUMP:
1149
+ case IPL_TYPE_NVME_DUMP:
9761150 break;
9771151 }
978
- disabled_wait((unsigned long) __builtin_return_address(0));
1152
+ disabled_wait();
9791153 }
9801154
9811155 static void reipl_run(struct shutdown_trigger *trigger)
....@@ -985,10 +1159,10 @@
9851159
9861160 static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
9871161 {
988
- ipb->hdr.len = IPL_PARM_BLK_CCW_LEN;
1162
+ ipb->hdr.len = IPL_BP_CCW_LEN;
9891163 ipb->hdr.version = IPL_PARM_BLOCK_VERSION;
990
- ipb->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
991
- ipb->hdr.pbt = DIAG308_IPL_TYPE_CCW;
1164
+ ipb->pb0_hdr.len = IPL_BP0_CCW_LEN;
1165
+ ipb->pb0_hdr.pbt = IPL_PBT_CCW;
9921166 }
9931167
9941168 static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
....@@ -996,21 +1170,20 @@
9961170 /* LOADPARM */
9971171 /* check if read scp info worked and set loadparm */
9981172 if (sclp_ipl_info.is_valid)
999
- memcpy(ipb->hdr.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
1173
+ memcpy(ipb->ccw.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
10001174 else
10011175 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
1002
- memset(ipb->hdr.loadparm, 0x40, LOADPARM_LEN);
1003
- ipb->hdr.flags = DIAG308_FLAGS_LP_VALID;
1176
+ memset(ipb->ccw.loadparm, 0x40, LOADPARM_LEN);
1177
+ ipb->ccw.flags = IPL_PB0_FLAG_LOADPARM;
10041178
10051179 /* VM PARM */
10061180 if (MACHINE_IS_VM && ipl_block_valid &&
1007
- (ipl_block.ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID)) {
1181
+ (ipl_block.ccw.vm_flags & IPL_PB0_CCW_VM_FLAG_VP)) {
10081182
1009
- ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
1010
- ipb->ipl_info.ccw.vm_parm_len =
1011
- ipl_block.ipl_info.ccw.vm_parm_len;
1012
- memcpy(ipb->ipl_info.ccw.vm_parm,
1013
- ipl_block.ipl_info.ccw.vm_parm, DIAG308_VMPARM_SIZE);
1183
+ ipb->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_VP;
1184
+ ipb->ccw.vm_parm_len = ipl_block.ccw.vm_parm_len;
1185
+ memcpy(ipb->ccw.vm_parm,
1186
+ ipl_block.ccw.vm_parm, DIAG308_VMPARM_SIZE);
10141187 }
10151188 }
10161189
....@@ -1050,8 +1223,8 @@
10501223
10511224 reipl_block_ccw_init(reipl_block_ccw);
10521225 if (ipl_info.type == IPL_TYPE_CCW) {
1053
- reipl_block_ccw->ipl_info.ccw.ssid = ipl_block.ipl_info.ccw.ssid;
1054
- reipl_block_ccw->ipl_info.ccw.devno = ipl_block.ipl_info.ccw.devno;
1226
+ reipl_block_ccw->ccw.ssid = ipl_block.ccw.ssid;
1227
+ reipl_block_ccw->ccw.devno = ipl_block.ccw.devno;
10551228 reipl_block_ccw_fill_parms(reipl_block_ccw);
10561229 }
10571230
....@@ -1076,10 +1249,16 @@
10761249 }
10771250
10781251 rc = sysfs_create_group(&reipl_fcp_kset->kobj, &reipl_fcp_attr_group);
1079
- if (rc) {
1080
- kset_unregister(reipl_fcp_kset);
1081
- free_page((unsigned long) reipl_block_fcp);
1082
- return rc;
1252
+ if (rc)
1253
+ goto out1;
1254
+
1255
+ if (test_facility(141)) {
1256
+ rc = sysfs_create_file(&reipl_fcp_kset->kobj,
1257
+ &sys_reipl_fcp_clear_attr.attr);
1258
+ if (rc)
1259
+ goto out2;
1260
+ } else {
1261
+ reipl_fcp_clear = true;
10831262 }
10841263
10851264 if (ipl_info.type == IPL_TYPE_FCP) {
....@@ -1089,17 +1268,80 @@
10891268 * is invalid in the SCSI IPL parameter block, so take it
10901269 * always from sclp_ipl_info.
10911270 */
1092
- memcpy(reipl_block_fcp->hdr.loadparm, sclp_ipl_info.loadparm,
1271
+ memcpy(reipl_block_fcp->fcp.loadparm, sclp_ipl_info.loadparm,
10931272 LOADPARM_LEN);
10941273 } else {
1095
- reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
1274
+ reipl_block_fcp->hdr.len = IPL_BP_FCP_LEN;
10961275 reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
1097
- reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
1098
- reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
1099
- reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL;
1276
+ reipl_block_fcp->fcp.len = IPL_BP0_FCP_LEN;
1277
+ reipl_block_fcp->fcp.pbt = IPL_PBT_FCP;
1278
+ reipl_block_fcp->fcp.opt = IPL_PB0_FCP_OPT_IPL;
11001279 }
11011280 reipl_capabilities |= IPL_TYPE_FCP;
11021281 return 0;
1282
+
1283
+out2:
1284
+ sysfs_remove_group(&reipl_fcp_kset->kobj, &reipl_fcp_attr_group);
1285
+out1:
1286
+ kset_unregister(reipl_fcp_kset);
1287
+ free_page((unsigned long) reipl_block_fcp);
1288
+ return rc;
1289
+}
1290
+
1291
+static int __init reipl_nvme_init(void)
1292
+{
1293
+ int rc;
1294
+
1295
+ reipl_block_nvme = (void *) get_zeroed_page(GFP_KERNEL);
1296
+ if (!reipl_block_nvme)
1297
+ return -ENOMEM;
1298
+
1299
+ /* sysfs: create kset for mixing attr group and bin attrs */
1300
+ reipl_nvme_kset = kset_create_and_add(IPL_NVME_STR, NULL,
1301
+ &reipl_kset->kobj);
1302
+ if (!reipl_nvme_kset) {
1303
+ free_page((unsigned long) reipl_block_nvme);
1304
+ return -ENOMEM;
1305
+ }
1306
+
1307
+ rc = sysfs_create_group(&reipl_nvme_kset->kobj, &reipl_nvme_attr_group);
1308
+ if (rc)
1309
+ goto out1;
1310
+
1311
+ if (test_facility(141)) {
1312
+ rc = sysfs_create_file(&reipl_nvme_kset->kobj,
1313
+ &sys_reipl_nvme_clear_attr.attr);
1314
+ if (rc)
1315
+ goto out2;
1316
+ } else {
1317
+ reipl_nvme_clear = true;
1318
+ }
1319
+
1320
+ if (ipl_info.type == IPL_TYPE_NVME) {
1321
+ memcpy(reipl_block_nvme, &ipl_block, sizeof(ipl_block));
1322
+ /*
1323
+ * Fix loadparm: There are systems where the (SCSI) LOADPARM
1324
+ * is invalid in the IPL parameter block, so take it
1325
+ * always from sclp_ipl_info.
1326
+ */
1327
+ memcpy(reipl_block_nvme->nvme.loadparm, sclp_ipl_info.loadparm,
1328
+ LOADPARM_LEN);
1329
+ } else {
1330
+ reipl_block_nvme->hdr.len = IPL_BP_NVME_LEN;
1331
+ reipl_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION;
1332
+ reipl_block_nvme->nvme.len = IPL_BP0_NVME_LEN;
1333
+ reipl_block_nvme->nvme.pbt = IPL_PBT_NVME;
1334
+ reipl_block_nvme->nvme.opt = IPL_PB0_NVME_OPT_IPL;
1335
+ }
1336
+ reipl_capabilities |= IPL_TYPE_NVME;
1337
+ return 0;
1338
+
1339
+out2:
1340
+ sysfs_remove_group(&reipl_nvme_kset->kobj, &reipl_nvme_attr_group);
1341
+out1:
1342
+ kset_unregister(reipl_nvme_kset);
1343
+ free_page((unsigned long) reipl_block_nvme);
1344
+ return rc;
11031345 }
11041346
11051347 static int __init reipl_type_init(void)
....@@ -1114,10 +1356,13 @@
11141356 /*
11151357 * If we have an OS info reipl block, this will be used
11161358 */
1117
- if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_FCP) {
1359
+ if (reipl_block->pb0_hdr.pbt == IPL_PBT_FCP) {
11181360 memcpy(reipl_block_fcp, reipl_block, size);
11191361 reipl_type = IPL_TYPE_FCP;
1120
- } else if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_CCW) {
1362
+ } else if (reipl_block->pb0_hdr.pbt == IPL_PBT_NVME) {
1363
+ memcpy(reipl_block_nvme, reipl_block, size);
1364
+ reipl_type = IPL_TYPE_NVME;
1365
+ } else if (reipl_block->pb0_hdr.pbt == IPL_PBT_CCW) {
11211366 memcpy(reipl_block_ccw, reipl_block, size);
11221367 reipl_type = IPL_TYPE_CCW;
11231368 }
....@@ -1143,6 +1388,9 @@
11431388 rc = reipl_fcp_init();
11441389 if (rc)
11451390 return rc;
1391
+ rc = reipl_nvme_init();
1392
+ if (rc)
1393
+ return rc;
11461394 rc = reipl_nss_init();
11471395 if (rc)
11481396 return rc;
....@@ -1162,15 +1410,15 @@
11621410 /* FCP dump device attributes */
11631411
11641412 DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%llx\n",
1165
- dump_block_fcp->ipl_info.fcp.wwpn);
1413
+ dump_block_fcp->fcp.wwpn);
11661414 DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%llx\n",
1167
- dump_block_fcp->ipl_info.fcp.lun);
1415
+ dump_block_fcp->fcp.lun);
11681416 DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
1169
- dump_block_fcp->ipl_info.fcp.bootprog);
1417
+ dump_block_fcp->fcp.bootprog);
11701418 DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
1171
- dump_block_fcp->ipl_info.fcp.br_lba);
1419
+ dump_block_fcp->fcp.br_lba);
11721420 DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
1173
- dump_block_fcp->ipl_info.fcp.devno);
1421
+ dump_block_fcp->fcp.devno);
11741422
11751423 static struct attribute *dump_fcp_attrs[] = {
11761424 &sys_dump_fcp_device_attr.attr,
....@@ -1186,8 +1434,31 @@
11861434 .attrs = dump_fcp_attrs,
11871435 };
11881436
1437
+/* NVME dump device attributes */
1438
+DEFINE_IPL_ATTR_RW(dump_nvme, fid, "0x%08llx\n", "%llx\n",
1439
+ dump_block_nvme->nvme.fid);
1440
+DEFINE_IPL_ATTR_RW(dump_nvme, nsid, "0x%08llx\n", "%llx\n",
1441
+ dump_block_nvme->nvme.nsid);
1442
+DEFINE_IPL_ATTR_RW(dump_nvme, bootprog, "%lld\n", "%llx\n",
1443
+ dump_block_nvme->nvme.bootprog);
1444
+DEFINE_IPL_ATTR_RW(dump_nvme, br_lba, "%lld\n", "%llx\n",
1445
+ dump_block_nvme->nvme.br_lba);
1446
+
1447
+static struct attribute *dump_nvme_attrs[] = {
1448
+ &sys_dump_nvme_fid_attr.attr,
1449
+ &sys_dump_nvme_nsid_attr.attr,
1450
+ &sys_dump_nvme_bootprog_attr.attr,
1451
+ &sys_dump_nvme_br_lba_attr.attr,
1452
+ NULL,
1453
+};
1454
+
1455
+static struct attribute_group dump_nvme_attr_group = {
1456
+ .name = IPL_NVME_STR,
1457
+ .attrs = dump_nvme_attrs,
1458
+};
1459
+
11891460 /* CCW dump device attributes */
1190
-DEFINE_IPL_CCW_ATTR_RW(dump_ccw, device, dump_block_ccw->ipl_info.ccw);
1461
+DEFINE_IPL_CCW_ATTR_RW(dump_ccw, device, dump_block_ccw->ccw);
11911462
11921463 static struct attribute *dump_ccw_attrs[] = {
11931464 &sys_dump_ccw_device_attr.attr,
....@@ -1227,6 +1498,8 @@
12271498 rc = dump_set_type(DUMP_TYPE_CCW);
12281499 else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
12291500 rc = dump_set_type(DUMP_TYPE_FCP);
1501
+ else if (strncmp(buf, DUMP_NVME_STR, strlen(DUMP_NVME_STR)) == 0)
1502
+ rc = dump_set_type(DUMP_TYPE_NVME);
12301503 return (rc != 0) ? rc : len;
12311504 }
12321505
....@@ -1254,6 +1527,9 @@
12541527 case DUMP_TYPE_FCP:
12551528 diag308_dump(dump_block_fcp);
12561529 break;
1530
+ case DUMP_TYPE_NVME:
1531
+ diag308_dump(dump_block_nvme);
1532
+ break;
12571533 default:
12581534 break;
12591535 }
....@@ -1279,10 +1555,10 @@
12791555 free_page((unsigned long)dump_block_ccw);
12801556 return rc;
12811557 }
1282
- dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
1558
+ dump_block_ccw->hdr.len = IPL_BP_CCW_LEN;
12831559 dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
1284
- dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
1285
- dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
1560
+ dump_block_ccw->ccw.len = IPL_BP0_CCW_LEN;
1561
+ dump_block_ccw->ccw.pbt = IPL_PBT_CCW;
12861562 dump_capabilities |= DUMP_TYPE_CCW;
12871563 return 0;
12881564 }
....@@ -1301,12 +1577,35 @@
13011577 free_page((unsigned long)dump_block_fcp);
13021578 return rc;
13031579 }
1304
- dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
1580
+ dump_block_fcp->hdr.len = IPL_BP_FCP_LEN;
13051581 dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
1306
- dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
1307
- dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
1308
- dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
1582
+ dump_block_fcp->fcp.len = IPL_BP0_FCP_LEN;
1583
+ dump_block_fcp->fcp.pbt = IPL_PBT_FCP;
1584
+ dump_block_fcp->fcp.opt = IPL_PB0_FCP_OPT_DUMP;
13091585 dump_capabilities |= DUMP_TYPE_FCP;
1586
+ return 0;
1587
+}
1588
+
1589
+static int __init dump_nvme_init(void)
1590
+{
1591
+ int rc;
1592
+
1593
+ if (!sclp_ipl_info.has_dump)
1594
+ return 0; /* LDIPL DUMP is not installed */
1595
+ dump_block_nvme = (void *) get_zeroed_page(GFP_KERNEL);
1596
+ if (!dump_block_nvme)
1597
+ return -ENOMEM;
1598
+ rc = sysfs_create_group(&dump_kset->kobj, &dump_nvme_attr_group);
1599
+ if (rc) {
1600
+ free_page((unsigned long)dump_block_nvme);
1601
+ return rc;
1602
+ }
1603
+ dump_block_nvme->hdr.len = IPL_BP_NVME_LEN;
1604
+ dump_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION;
1605
+ dump_block_nvme->fcp.len = IPL_BP0_NVME_LEN;
1606
+ dump_block_nvme->fcp.pbt = IPL_PBT_NVME;
1607
+ dump_block_nvme->fcp.opt = IPL_PB0_NVME_OPT_DUMP;
1608
+ dump_capabilities |= DUMP_TYPE_NVME;
13101609 return 0;
13111610 }
13121611
....@@ -1326,6 +1625,9 @@
13261625 if (rc)
13271626 return rc;
13281627 rc = dump_fcp_init();
1628
+ if (rc)
1629
+ return rc;
1630
+ rc = dump_nvme_init();
13291631 if (rc)
13301632 return rc;
13311633 dump_set_type(DUMP_TYPE_NONE);
....@@ -1429,7 +1731,7 @@
14291731 {
14301732 if (strcmp(trigger->name, ON_PANIC_STR) == 0 ||
14311733 strcmp(trigger->name, ON_RESTART_STR) == 0)
1432
- disabled_wait((unsigned long) __builtin_return_address(0));
1734
+ disabled_wait();
14331735 smp_stop_cpu();
14341736 }
14351737
....@@ -1664,7 +1966,7 @@
16641966 * READ SCP info provides the correct value.
16651967 */
16661968 if (memcmp(sclp_ipl_info.loadparm, str, sizeof(str)) == 0 && ipl_block_valid)
1667
- memcpy(sclp_ipl_info.loadparm, ipl_block.hdr.loadparm, LOADPARM_LEN);
1969
+ memcpy(sclp_ipl_info.loadparm, ipl_block.ccw.loadparm, LOADPARM_LEN);
16681970 shutdown_actions_init();
16691971 shutdown_triggers_init();
16701972 return 0;
....@@ -1749,15 +2051,20 @@
17492051 ipl_info.type = get_ipl_type();
17502052 switch (ipl_info.type) {
17512053 case IPL_TYPE_CCW:
1752
- ipl_info.data.ccw.dev_id.ssid = ipl_block.ipl_info.ccw.ssid;
1753
- ipl_info.data.ccw.dev_id.devno = ipl_block.ipl_info.ccw.devno;
2054
+ ipl_info.data.ccw.dev_id.ssid = ipl_block.ccw.ssid;
2055
+ ipl_info.data.ccw.dev_id.devno = ipl_block.ccw.devno;
17542056 break;
17552057 case IPL_TYPE_FCP:
17562058 case IPL_TYPE_FCP_DUMP:
17572059 ipl_info.data.fcp.dev_id.ssid = 0;
1758
- ipl_info.data.fcp.dev_id.devno = ipl_block.ipl_info.fcp.devno;
1759
- ipl_info.data.fcp.wwpn = ipl_block.ipl_info.fcp.wwpn;
1760
- ipl_info.data.fcp.lun = ipl_block.ipl_info.fcp.lun;
2060
+ ipl_info.data.fcp.dev_id.devno = ipl_block.fcp.devno;
2061
+ ipl_info.data.fcp.wwpn = ipl_block.fcp.wwpn;
2062
+ ipl_info.data.fcp.lun = ipl_block.fcp.lun;
2063
+ break;
2064
+ case IPL_TYPE_NVME:
2065
+ case IPL_TYPE_NVME_DUMP:
2066
+ ipl_info.data.nvme.fid = ipl_block.nvme.fid;
2067
+ ipl_info.data.nvme.nsid = ipl_block.nvme.nsid;
17612068 break;
17622069 case IPL_TYPE_NSS:
17632070 case IPL_TYPE_UNKNOWN:
....@@ -1767,15 +2074,6 @@
17672074 atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
17682075 }
17692076
1770
-void __init ipl_store_parameters(void)
1771
-{
1772
- int rc;
1773
-
1774
- rc = diag308(DIAG308_STORE, &ipl_block);
1775
- if (rc == DIAG308_RC_OK && ipl_block.hdr.version <= IPL_MAX_SUPPORTED_VERSION)
1776
- ipl_block_valid = 1;
1777
-}
1778
-
17792077 void s390_reset_system(void)
17802078 {
17812079 /* Disable prefixing */
....@@ -1783,5 +2081,140 @@
17832081
17842082 /* Disable lowcore protection */
17852083 __ctl_clear_bit(0, 28);
1786
- diag308_reset();
2084
+ diag_dma_ops.diag308_reset();
17872085 }
2086
+
2087
+#ifdef CONFIG_KEXEC_FILE
2088
+
2089
+int ipl_report_add_component(struct ipl_report *report, struct kexec_buf *kbuf,
2090
+ unsigned char flags, unsigned short cert)
2091
+{
2092
+ struct ipl_report_component *comp;
2093
+
2094
+ comp = vzalloc(sizeof(*comp));
2095
+ if (!comp)
2096
+ return -ENOMEM;
2097
+ list_add_tail(&comp->list, &report->components);
2098
+
2099
+ comp->entry.addr = kbuf->mem;
2100
+ comp->entry.len = kbuf->memsz;
2101
+ comp->entry.flags = flags;
2102
+ comp->entry.certificate_index = cert;
2103
+
2104
+ report->size += sizeof(comp->entry);
2105
+
2106
+ return 0;
2107
+}
2108
+
2109
+int ipl_report_add_certificate(struct ipl_report *report, void *key,
2110
+ unsigned long addr, unsigned long len)
2111
+{
2112
+ struct ipl_report_certificate *cert;
2113
+
2114
+ cert = vzalloc(sizeof(*cert));
2115
+ if (!cert)
2116
+ return -ENOMEM;
2117
+ list_add_tail(&cert->list, &report->certificates);
2118
+
2119
+ cert->entry.addr = addr;
2120
+ cert->entry.len = len;
2121
+ cert->key = key;
2122
+
2123
+ report->size += sizeof(cert->entry);
2124
+ report->size += cert->entry.len;
2125
+
2126
+ return 0;
2127
+}
2128
+
2129
+struct ipl_report *ipl_report_init(struct ipl_parameter_block *ipib)
2130
+{
2131
+ struct ipl_report *report;
2132
+
2133
+ report = vzalloc(sizeof(*report));
2134
+ if (!report)
2135
+ return ERR_PTR(-ENOMEM);
2136
+
2137
+ report->ipib = ipib;
2138
+ INIT_LIST_HEAD(&report->components);
2139
+ INIT_LIST_HEAD(&report->certificates);
2140
+
2141
+ report->size = ALIGN(ipib->hdr.len, 8);
2142
+ report->size += sizeof(struct ipl_rl_hdr);
2143
+ report->size += sizeof(struct ipl_rb_components);
2144
+ report->size += sizeof(struct ipl_rb_certificates);
2145
+
2146
+ return report;
2147
+}
2148
+
2149
+void *ipl_report_finish(struct ipl_report *report)
2150
+{
2151
+ struct ipl_report_certificate *cert;
2152
+ struct ipl_report_component *comp;
2153
+ struct ipl_rb_certificates *certs;
2154
+ struct ipl_parameter_block *ipib;
2155
+ struct ipl_rb_components *comps;
2156
+ struct ipl_rl_hdr *rl_hdr;
2157
+ void *buf, *ptr;
2158
+
2159
+ buf = vzalloc(report->size);
2160
+ if (!buf)
2161
+ goto out;
2162
+ ptr = buf;
2163
+
2164
+ memcpy(ptr, report->ipib, report->ipib->hdr.len);
2165
+ ipib = ptr;
2166
+ if (ipl_secure_flag)
2167
+ ipib->hdr.flags |= IPL_PL_FLAG_SIPL;
2168
+ ipib->hdr.flags |= IPL_PL_FLAG_IPLSR;
2169
+ ptr += report->ipib->hdr.len;
2170
+ ptr = PTR_ALIGN(ptr, 8);
2171
+
2172
+ rl_hdr = ptr;
2173
+ ptr += sizeof(*rl_hdr);
2174
+
2175
+ comps = ptr;
2176
+ comps->rbt = IPL_RBT_COMPONENTS;
2177
+ ptr += sizeof(*comps);
2178
+ list_for_each_entry(comp, &report->components, list) {
2179
+ memcpy(ptr, &comp->entry, sizeof(comp->entry));
2180
+ ptr += sizeof(comp->entry);
2181
+ }
2182
+ comps->len = ptr - (void *)comps;
2183
+
2184
+ certs = ptr;
2185
+ certs->rbt = IPL_RBT_CERTIFICATES;
2186
+ ptr += sizeof(*certs);
2187
+ list_for_each_entry(cert, &report->certificates, list) {
2188
+ memcpy(ptr, &cert->entry, sizeof(cert->entry));
2189
+ ptr += sizeof(cert->entry);
2190
+ }
2191
+ certs->len = ptr - (void *)certs;
2192
+ rl_hdr->len = ptr - (void *)rl_hdr;
2193
+
2194
+ list_for_each_entry(cert, &report->certificates, list) {
2195
+ memcpy(ptr, cert->key, cert->entry.len);
2196
+ ptr += cert->entry.len;
2197
+ }
2198
+
2199
+ BUG_ON(ptr > buf + report->size);
2200
+out:
2201
+ return buf;
2202
+}
2203
+
2204
+int ipl_report_free(struct ipl_report *report)
2205
+{
2206
+ struct ipl_report_component *comp, *ncomp;
2207
+ struct ipl_report_certificate *cert, *ncert;
2208
+
2209
+ list_for_each_entry_safe(comp, ncomp, &report->components, list)
2210
+ vfree(comp);
2211
+
2212
+ list_for_each_entry_safe(cert, ncert, &report->certificates, list)
2213
+ vfree(cert);
2214
+
2215
+ vfree(report);
2216
+
2217
+ return 0;
2218
+}
2219
+
2220
+#endif